query compiler progress
This commit is contained in:
parent
b966a7a1a7
commit
a3f467a5a8
|
|
@ -58,7 +58,7 @@ std::unique_ptr<sql::query_result_impl> postgres_connection::fetch(const std::st
|
||||||
auto type = PQftype(res, i);
|
auto type = PQftype(res, i);
|
||||||
auto size = PQfmod(res, i);
|
auto size = PQfmod(res, i);
|
||||||
// std::cout << "column " << col_name << ", type " << type << " (size: " << size << ")\n";
|
// std::cout << "column " << col_name << ", type " << type << " (size: " << size << ")\n";
|
||||||
prototype.append({col_name});
|
prototype.append(sql::column_definition{col_name});
|
||||||
}
|
}
|
||||||
return std::move(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res), std::move(prototype)));
|
return std::move(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res), std::move(prototype)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ int sqlite_connection::parse_result(void* param, int column_count, char** values
|
||||||
|
|
||||||
if (context->prototype.empty()) {
|
if (context->prototype.empty()) {
|
||||||
for(int i = 0; i < column_count; ++i) {
|
for(int i = 0; i < column_count; ++i) {
|
||||||
context->prototype.append(sql::column{columns[i]});
|
context->prototype.append(sql::column_definition{columns[i]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column.hpp"
|
||||||
#include "matador/sql/condition.hpp"
|
#include "matador/sql/condition.hpp"
|
||||||
#include "matador/sql/connection.hpp"
|
#include "matador/sql/connection.hpp"
|
||||||
|
#include "matador/sql/query_builder.hpp"
|
||||||
|
|
||||||
#include "connection.hpp"
|
#include "connection.hpp"
|
||||||
|
|
||||||
|
|
@ -29,7 +30,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
void drop_table_if_exists(const std::string &table_name) {
|
void drop_table_if_exists(const std::string &table_name) {
|
||||||
if (db.exists(table_name)) {
|
if (db.exists(table_name)) {
|
||||||
db.drop().table(table_name).execute();
|
db.query().drop().table(table_name).execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -39,7 +40,7 @@ using namespace matador::sql;
|
||||||
TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement", "[session][record]")
|
TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement", "[session][record]")
|
||||||
{
|
{
|
||||||
REQUIRE(!db.exists("person"));
|
REQUIRE(!db.exists("person"));
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("person", {
|
.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),
|
||||||
|
|
@ -49,7 +50,7 @@ TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement", "[sessi
|
||||||
|
|
||||||
REQUIRE(db.exists("person"));
|
REQUIRE(db.exists("person"));
|
||||||
|
|
||||||
db.drop()
|
db.query().drop()
|
||||||
.table("person")
|
.table("person")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
|
@ -58,7 +59,7 @@ TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement", "[sessi
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement with foreign key", "[session][record]")
|
TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement with foreign key", "[session][record]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("airplane", {
|
.table("airplane", {
|
||||||
make_pk_column<unsigned long>("id"),
|
make_pk_column<unsigned long>("id"),
|
||||||
make_column<std::string>("brand", 255),
|
make_column<std::string>("brand", 255),
|
||||||
|
|
@ -68,7 +69,7 @@ TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement with fore
|
||||||
|
|
||||||
REQUIRE(db.exists("airplane"));
|
REQUIRE(db.exists("airplane"));
|
||||||
|
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("flight", {
|
.table("flight", {
|
||||||
make_pk_column<unsigned long>("id"),
|
make_pk_column<unsigned long>("id"),
|
||||||
make_fk_column<unsigned long>("airplane_id", "airplane", "id"),
|
make_fk_column<unsigned long>("airplane_id", "airplane", "id"),
|
||||||
|
|
@ -78,13 +79,13 @@ TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement with fore
|
||||||
|
|
||||||
REQUIRE(db.exists("flight"));
|
REQUIRE(db.exists("flight"));
|
||||||
|
|
||||||
db.drop()
|
db.query().drop()
|
||||||
.table("flight")
|
.table("flight")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
REQUIRE(!db.exists("flight"));
|
REQUIRE(!db.exists("flight"));
|
||||||
|
|
||||||
db.drop()
|
db.query().drop()
|
||||||
.table("airplane")
|
.table("airplane")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
|
@ -93,7 +94,7 @@ TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement with fore
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement", "[session][record]")
|
TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement", "[session][record]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("person", {
|
.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),
|
||||||
|
|
@ -101,14 +102,14 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement", "[sessi
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
auto res = db.insert()
|
auto res = db.query().insert()
|
||||||
.into("person", {"id", "name", "age"})
|
.into("person", {"id", "name", "age"})
|
||||||
.values({7, "george", 45})
|
.values({7, "george", 45})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
auto result = db.select({"id", "name", "age"})
|
auto result = db.query().select({"id", "name", "age"})
|
||||||
.from("person")
|
.from("person")
|
||||||
.fetch_all();
|
.fetch_all();
|
||||||
|
|
||||||
|
|
@ -125,14 +126,14 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement", "[sessi
|
||||||
REQUIRE(i.at(2).template as<int>() == 45);
|
REQUIRE(i.at(2).template as<int>() == 45);
|
||||||
}
|
}
|
||||||
|
|
||||||
db.drop()
|
db.query().drop()
|
||||||
.table("person")
|
.table("person")
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement with foreign key", "[session][record]")
|
TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement with foreign key", "[session][record]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("airplane", {
|
.table("airplane", {
|
||||||
make_pk_column<unsigned long>("id"),
|
make_pk_column<unsigned long>("id"),
|
||||||
make_column<std::string>("brand", 255),
|
make_column<std::string>("brand", 255),
|
||||||
|
|
@ -140,7 +141,7 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement with fore
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("flight", {
|
.table("flight", {
|
||||||
make_pk_column<unsigned long>("id"),
|
make_pk_column<unsigned long>("id"),
|
||||||
make_fk_column<unsigned long>("airplane_id", "airplane", "id"),
|
make_fk_column<unsigned long>("airplane_id", "airplane", "id"),
|
||||||
|
|
@ -148,23 +149,23 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement with fore
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
auto res = db.insert().into("airplane", {"id", "brand", "model"}).values({1, "Airbus", "A380"}).execute();
|
auto res = db.query().insert().into("airplane", {"id", "brand", "model"}).values({1, "Airbus", "A380"}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
res = db.insert().into("airplane", {"id", "brand", "model"}).values({2, "Boeing", "707"}).execute();
|
res = db.query().insert().into("airplane", {"id", "brand", "model"}).values({2, "Boeing", "707"}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
res = db.insert().into("airplane", {"id", "brand", "model"}).values({3, "Boeing", "747"}).execute();
|
res = db.query().insert().into("airplane", {"id", "brand", "model"}).values({3, "Boeing", "747"}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
auto count = db.select({count_all()}).from("airplane").fetch_value<int>();
|
auto count = db.query().select({count_all()}).from("airplane").fetch_value<int>();
|
||||||
REQUIRE(count == 3);
|
REQUIRE(count == 3);
|
||||||
|
|
||||||
res = db.insert().into("flight", {"id", "airplane_id", "pilot_name"}).values({4, 1, "George"}).execute();
|
res = db.query().insert().into("flight", {"id", "airplane_id", "pilot_name"}).values({4, 1, "George"}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
db.drop().table("flight").execute();
|
db.query().drop().table("flight").execute();
|
||||||
db.drop().table("airplane").execute();
|
db.query().drop().table("airplane").execute();
|
||||||
|
|
||||||
REQUIRE(!db.exists("flight"));
|
REQUIRE(!db.exists("flight"));
|
||||||
REQUIRE(!db.exists("airplane"));
|
REQUIRE(!db.exists("airplane"));
|
||||||
|
|
@ -172,7 +173,7 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement with fore
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryRecordFixture, " Execute update record statement", "[session][record]")
|
TEST_CASE_METHOD(QueryRecordFixture, " Execute update record statement", "[session][record]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("person", {
|
.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),
|
||||||
|
|
@ -180,14 +181,14 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute update record statement", "[sessi
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
auto res = db.insert()
|
auto res = db.query().insert()
|
||||||
.into("person", {"id", "name", "age"})
|
.into("person", {"id", "name", "age"})
|
||||||
.values({7, "george", 45})
|
.values({7, "george", 45})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
res = db.update("person")
|
res = db.query().update("person")
|
||||||
.set({{"id", 7},
|
.set({{"id", 7},
|
||||||
{"name", "jane"},
|
{"name", "jane"},
|
||||||
{"age", 35}})
|
{"age", 35}})
|
||||||
|
|
@ -196,7 +197,7 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute update record statement", "[sessi
|
||||||
|
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
auto result = db.select({"id", "name", "age"})
|
auto result = db.query().select({"id", "name", "age"})
|
||||||
.from("person")
|
.from("person")
|
||||||
.fetch_all();
|
.fetch_all();
|
||||||
|
|
||||||
|
|
@ -213,12 +214,12 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute update record statement", "[sessi
|
||||||
REQUIRE(i.at(2).as<int>() == 35);
|
REQUIRE(i.at(2).as<int>() == 35);
|
||||||
}
|
}
|
||||||
|
|
||||||
db.drop().table("person").execute();
|
db.query().drop().table("person").execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement", "[session][record]")
|
TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement", "[session][record]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("person", {
|
.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),
|
||||||
|
|
@ -226,16 +227,16 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement", "[session][rec
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
auto res = db.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
auto res = db.query().insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
res = db.insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute();
|
res = db.query().insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
res = db.insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute();
|
res = db.query().insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
res = db.insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
res = db.query().insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
auto result = db.select({"id", "name", "age"})
|
auto result = db.query().select({"id", "name", "age"})
|
||||||
.from("person")
|
.from("person")
|
||||||
.fetch_all();
|
.fetch_all();
|
||||||
|
|
||||||
|
|
@ -246,22 +247,22 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement", "[session][rec
|
||||||
}
|
}
|
||||||
REQUIRE(expected_names.empty());
|
REQUIRE(expected_names.empty());
|
||||||
|
|
||||||
auto rec = db.select({"id", "name", "age"})
|
auto rec = db.query().select({"id", "name", "age"})
|
||||||
.from("person")
|
.from("person")
|
||||||
.fetch_one();
|
.fetch_one();
|
||||||
REQUIRE(rec.at(1).str() == "george");
|
REQUIRE(rec.at(1).str() == "george");
|
||||||
|
|
||||||
auto name = db.select({"name"})
|
auto name = db.query().select({"name"})
|
||||||
.from("person")
|
.from("person")
|
||||||
.fetch_value<std::string>();
|
.fetch_value<std::string>();
|
||||||
REQUIRE(name == "george");
|
REQUIRE(name == "george");
|
||||||
|
|
||||||
db.drop().table("person").execute();
|
db.query().drop().table("person").execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with order by", "[session][record]")
|
TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with order by", "[session][record]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("person", {
|
.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),
|
||||||
|
|
@ -269,16 +270,16 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with order by",
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
auto res = db.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
auto res = db.query().insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
res = db.insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute();
|
res = db.query().insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
res = db.insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute();
|
res = db.query().insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
res = db.insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
res = db.query().insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
auto result = db.select({"id", "name", "age"})
|
auto result = db.query().select({"id", "name", "age"})
|
||||||
.from("person")
|
.from("person")
|
||||||
.order_by("name").asc()
|
.order_by("name").asc()
|
||||||
.fetch_all();
|
.fetch_all();
|
||||||
|
|
@ -290,12 +291,12 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with order by",
|
||||||
}
|
}
|
||||||
REQUIRE(expected_names.empty());
|
REQUIRE(expected_names.empty());
|
||||||
|
|
||||||
db.drop().table("person").execute();
|
db.query().drop().table("person").execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with group by and order by", "[session][record]")
|
TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with group by and order by", "[session][record]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("person", {
|
.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),
|
||||||
|
|
@ -303,18 +304,18 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with group by an
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
auto res = db.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
auto res = db.query().insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
res = db.insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute();
|
res = db.query().insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
res = db.insert().into("person", {"id", "name", "age"}).values({3, "michael", 13}).execute();
|
res = db.query().insert().into("person", {"id", "name", "age"}).values({3, "michael", 13}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
res = db.insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
res = db.query().insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
res = db.insert().into("person", {"id", "name", "age"}).values({5, "charlie", 67}).execute();
|
res = db.query().insert().into("person", {"id", "name", "age"}).values({5, "charlie", 67}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
auto result = db.select({alias(count("age"), "age_count"), "age"})
|
auto result = db.query().select({alias(count("age"), "age_count"), "age"})
|
||||||
.from("person")
|
.from("person")
|
||||||
.group_by("age")
|
.group_by("age")
|
||||||
.order_by("age_count").desc()
|
.order_by("age_count").desc()
|
||||||
|
|
@ -329,41 +330,41 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with group by an
|
||||||
expected_values.pop_front();
|
expected_values.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
db.drop().table("person").execute();
|
db.query().drop().table("person").execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryRecordFixture, " Execute delete statement", "[session][record]")
|
TEST_CASE_METHOD(QueryRecordFixture, " Execute delete statement", "[session][record]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("person", {
|
.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")
|
||||||
}).execute();
|
}).execute();
|
||||||
|
|
||||||
auto res = db.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
auto res = db.query().insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
res = db.insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute();
|
res = db.query().insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
auto count = db.select({count_all()}).from("person").fetch_value<int>();
|
auto count = db.query().select({count_all()}).from("person").fetch_value<int>();
|
||||||
REQUIRE(count == 2);
|
REQUIRE(count == 2);
|
||||||
|
|
||||||
res = db.remove()
|
res = db.query().remove()
|
||||||
.from("person")
|
.from("person")
|
||||||
.where("id"_col == 1)
|
.where("id"_col == 1)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
count = db.select({count_all()}).from("person").fetch_value<int>();
|
count = db.query().select({count_all()}).from("person").fetch_value<int>();
|
||||||
REQUIRE(count == 1);
|
REQUIRE(count == 1);
|
||||||
|
|
||||||
db.drop().table("person").execute();
|
db.query().drop().table("person").execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryRecordFixture, " Test quoted identifier", "[session][record]") {
|
TEST_CASE_METHOD(QueryRecordFixture, " Test quoted identifier", "[session][record]") {
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("quotes", {
|
.table("quotes", {
|
||||||
make_column<std::string>("from", 255),
|
make_column<std::string>("from", 255),
|
||||||
make_column<std::string>("to", 255)
|
make_column<std::string>("to", 255)
|
||||||
|
|
@ -379,19 +380,19 @@ TEST_CASE_METHOD(QueryRecordFixture, " Test quoted identifier", "[session][recor
|
||||||
REQUIRE(field.type() == types[field.index()]);
|
REQUIRE(field.type() == types[field.index()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
db.insert().into("quotes", {"from", "to"}).values({"Berlin", "London"}).execute();
|
db.query().insert().into("quotes", {"from", "to"}).values({"Berlin", "London"}).execute();
|
||||||
|
|
||||||
auto res = db.select({"from", "to"}).from("quotes").fetch_one();
|
auto res = db.query().select({"from", "to"}).from("quotes").fetch_one();
|
||||||
|
|
||||||
REQUIRE("Berlin" == res.at("from").str());
|
REQUIRE("Berlin" == res.at("from").str());
|
||||||
REQUIRE("London" == res.at("to").str());
|
REQUIRE("London" == res.at("to").str());
|
||||||
|
|
||||||
db.update("quotes").set({{"from", "Hamburg"}, {"to", "New York"}}).where("from"_col == "Berlin").execute();
|
db.query().update("quotes").set({{"from", "Hamburg"}, {"to", "New York"}}).where("from"_col == "Berlin").execute();
|
||||||
|
|
||||||
res = db.select({"from", "to"}).from("quotes").fetch_one();
|
res = db.query().select({"from", "to"}).from("quotes").fetch_one();
|
||||||
|
|
||||||
REQUIRE("Hamburg" == res.at("from").str());
|
REQUIRE("Hamburg" == res.at("from").str());
|
||||||
REQUIRE("New York" == res.at("to").str());
|
REQUIRE("New York" == res.at("to").str());
|
||||||
|
|
||||||
db.drop().table("quotes").execute();
|
db.query().drop().table("quotes").execute();
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
#include "catch2/catch_test_macros.hpp"
|
#include "catch2/catch_test_macros.hpp"
|
||||||
|
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column_definition.hpp"
|
||||||
#include "matador/sql/condition.hpp"
|
#include "matador/sql/condition.hpp"
|
||||||
|
#include "matador/sql/query_builder.hpp"
|
||||||
#include "matador/sql/session.hpp"
|
#include "matador/sql/session.hpp"
|
||||||
|
|
||||||
#include "connection.hpp"
|
#include "connection.hpp"
|
||||||
|
|
@ -36,27 +37,27 @@ private:
|
||||||
void drop_table_if_exists(const std::string &table_name)
|
void drop_table_if_exists(const std::string &table_name)
|
||||||
{
|
{
|
||||||
if (db.exists(table_name)) {
|
if (db.exists(table_name)) {
|
||||||
db.drop().table(table_name).execute();
|
db.query().drop().table(table_name).execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryFixture, " Create table with foreign key relation", "[session]")
|
TEST_CASE_METHOD(QueryFixture, " Create table with foreign key relation", "[session]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table<airplane>("airplane")
|
.table<airplane>("airplane")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
REQUIRE(db.exists("airplane"));
|
REQUIRE(db.exists("airplane"));
|
||||||
|
|
||||||
db.create()
|
db.query().create()
|
||||||
.table<flight>("flight")
|
.table<flight>("flight")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
REQUIRE(db.exists("flight"));
|
REQUIRE(db.exists("flight"));
|
||||||
|
|
||||||
db.drop().table("flight").execute();
|
db.query().drop().table("flight").execute();
|
||||||
db.drop().table("airplane").execute();
|
db.query().drop().table("airplane").execute();
|
||||||
|
|
||||||
REQUIRE(!db.exists("flight"));
|
REQUIRE(!db.exists("flight"));
|
||||||
REQUIRE(!db.exists("airplane"));
|
REQUIRE(!db.exists("airplane"));
|
||||||
|
|
@ -64,20 +65,20 @@ TEST_CASE_METHOD(QueryFixture, " Create table with foreign key relation", "[sess
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryFixture, " Execute select statement with where clause", "[session]")
|
TEST_CASE_METHOD(QueryFixture, " Execute select statement with where clause", "[session]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table<person>("person")
|
.table<person>("person")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
person george{7, "george", 45};
|
person george{7, "george", 45};
|
||||||
george.image.push_back(37);
|
george.image.push_back(37);
|
||||||
|
|
||||||
auto res = db.insert()
|
auto res = db.query().insert()
|
||||||
.into("person", george)
|
.into("person", george)
|
||||||
.execute();
|
.execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
// fetch person as record
|
// fetch person as record
|
||||||
auto result_record = db.select<person>()
|
auto result_record = db.query().select<person>()
|
||||||
.from("person")
|
.from("person")
|
||||||
.where("id"_col == 7)
|
.where("id"_col == 7)
|
||||||
.fetch_all();
|
.fetch_all();
|
||||||
|
|
@ -96,7 +97,7 @@ TEST_CASE_METHOD(QueryFixture, " Execute select statement with where clause", "[
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch person as person
|
// fetch person as person
|
||||||
auto result_person = db.select<person>()
|
auto result_person = db.query().select<person>()
|
||||||
.from("person")
|
.from("person")
|
||||||
.where("id"_col == 7)
|
.where("id"_col == 7)
|
||||||
.fetch_all<person>();
|
.fetch_all<person>();
|
||||||
|
|
@ -107,12 +108,12 @@ TEST_CASE_METHOD(QueryFixture, " Execute select statement with where clause", "[
|
||||||
REQUIRE(i.age == 45);
|
REQUIRE(i.age == 45);
|
||||||
}
|
}
|
||||||
|
|
||||||
db.drop().table("person").execute();
|
db.query().drop().table("person").execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryFixture, " Execute insert statement", "[session]")
|
TEST_CASE_METHOD(QueryFixture, " Execute insert statement", "[session]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table("person", {
|
.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),
|
||||||
|
|
@ -120,7 +121,7 @@ TEST_CASE_METHOD(QueryFixture, " Execute insert statement", "[session]")
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
auto res = db.insert()
|
auto res = db.query().insert()
|
||||||
.into("person", {{"", "id", ""}, {"", "name", ""}, {"", "color", ""}})
|
.into("person", {{"", "id", ""}, {"", "name", ""}, {"", "color", ""}})
|
||||||
.values({7, "george", "green"})
|
.values({7, "george", "green"})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
@ -128,7 +129,7 @@ TEST_CASE_METHOD(QueryFixture, " Execute insert statement", "[session]")
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
// fetch person as record
|
// fetch person as record
|
||||||
auto result_record = db.select({"id", "name", "color"})
|
auto result_record = db.query().select({"id", "name", "color"})
|
||||||
.from("person")
|
.from("person")
|
||||||
.where("id"_col == 7)
|
.where("id"_col == 7)
|
||||||
.fetch_all();
|
.fetch_all();
|
||||||
|
|
@ -146,16 +147,16 @@ TEST_CASE_METHOD(QueryFixture, " Execute insert statement", "[session]")
|
||||||
REQUIRE(i.at(2).as<std::string>() == "green");
|
REQUIRE(i.at(2).as<std::string>() == "green");
|
||||||
}
|
}
|
||||||
|
|
||||||
db.drop().table("person").execute();
|
db.query().drop().table("person").execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key", "[session]")
|
TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key", "[session]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table<airplane>("airplane")
|
.table<airplane>("airplane")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
db.create()
|
db.query().create()
|
||||||
.table<flight>("flight")
|
.table<flight>("flight")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
|
@ -166,35 +167,35 @@ TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key", "[session]"
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &plane: planes) {
|
for (const auto &plane: planes) {
|
||||||
auto res = db.insert().into<airplane>("airplane").values(*plane).execute();
|
auto res = db.query().insert().into<airplane>("airplane").values(*plane).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto count = db.select({count_all()}).from("airplane").fetch_value<int>();
|
auto count = db.query().select({count_all()}).from("airplane").fetch_value<int>();
|
||||||
REQUIRE(count == 3);
|
REQUIRE(count == 3);
|
||||||
|
|
||||||
flight f4711{4, planes.at(1), "hans"};
|
flight f4711{4, planes.at(1), "hans"};
|
||||||
|
|
||||||
auto res = db.insert().into<flight>("flight").values(f4711).execute();
|
auto res = db.query().insert().into<flight>("flight").values(f4711).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
auto f = *db.select<flight>().from("flight").fetch_all<flight>().begin();
|
auto f = *db.query().select<flight>().from("flight").fetch_all<flight>().begin();
|
||||||
REQUIRE(f.id == 4);
|
REQUIRE(f.id == 4);
|
||||||
REQUIRE(f.pilot_name == "hans");
|
REQUIRE(f.pilot_name == "hans");
|
||||||
REQUIRE(f.airplane.get() != nullptr);
|
REQUIRE(f.airplane.get() != nullptr);
|
||||||
REQUIRE(f.airplane->id == 2);
|
REQUIRE(f.airplane->id == 2);
|
||||||
|
|
||||||
db.drop().table("flight").execute();
|
db.query().drop().table("flight").execute();
|
||||||
db.drop().table("airplane").execute();
|
db.query().drop().table("airplane").execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key and join", "[session][join]")
|
TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key and join_left", "[session][join_left]")
|
||||||
{
|
{
|
||||||
db.create()
|
db.query().create()
|
||||||
.table<airplane>("airplane")
|
.table<airplane>("airplane")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
db.create()
|
db.query().create()
|
||||||
.table<flight>("flight")
|
.table<flight>("flight")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
|
@ -205,11 +206,11 @@ TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key and join", "[
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &plane: planes) {
|
for (const auto &plane: planes) {
|
||||||
auto res = db.insert().into<airplane>("airplane").values(*plane).execute();
|
auto res = db.query().insert().into<airplane>("airplane").values(*plane).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto count = db.select({count_all()}).from("airplane").fetch_value<int>();
|
auto count = db.query().select({count_all()}).from("airplane").fetch_value<int>();
|
||||||
REQUIRE(count == 3);
|
REQUIRE(count == 3);
|
||||||
|
|
||||||
std::vector<entity<flight>> flights{
|
std::vector<entity<flight>> flights{
|
||||||
|
|
@ -220,20 +221,20 @@ TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key and join", "[
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &f: flights) {
|
for (const auto &f: flights) {
|
||||||
auto res = db.insert().into<flight>("flight").values(*f).execute();
|
auto res = db.query().insert().into<flight>("flight").values(*f).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto f = *db.select<flight>().from("flight").fetch_all<flight>().begin();
|
auto f = *db.query().select<flight>().from("flight").fetch_all<flight>().begin();
|
||||||
REQUIRE(f.id == 4);
|
REQUIRE(f.id == 4);
|
||||||
REQUIRE(f.pilot_name == "hans");
|
REQUIRE(f.pilot_name == "hans");
|
||||||
REQUIRE(f.airplane.get() != nullptr);
|
REQUIRE(f.airplane.get() != nullptr);
|
||||||
REQUIRE(f.airplane->id == 1);
|
REQUIRE(f.airplane->id == 1);
|
||||||
|
|
||||||
auto result = db.select({"f.id", "ap.brand", "ap.model", "f.pilot_name"})
|
auto result = db.query().select({"f.id", "ap.brand", "ap.model", "f.pilot_name"})
|
||||||
.from("flight", "f")
|
.from("flight", "f")
|
||||||
.join("airplane", "ap")
|
.join_left("airplane", "ap")
|
||||||
.on("f.airplane_id", "ap.id")
|
.on("f.airplane_id"_col == "ap.id"_col)
|
||||||
.order_by("f.id").asc()
|
.order_by("f.id").asc()
|
||||||
.fetch_all();
|
.fetch_all();
|
||||||
|
|
||||||
|
|
@ -250,7 +251,7 @@ TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key and join", "[
|
||||||
REQUIRE(r.at(3).as<std::string>() == expected_result[index++].second);
|
REQUIRE(r.at(3).as<std::string>() == expected_result[index++].second);
|
||||||
}
|
}
|
||||||
|
|
||||||
db.drop().table("flight").execute();
|
db.query().drop().table("flight").execute();
|
||||||
db.drop().table("airplane").execute();
|
db.query().drop().table("airplane").execute();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column_definition.hpp"
|
||||||
#include "matador/sql/condition.hpp"
|
#include "matador/sql/condition.hpp"
|
||||||
#include "matador/sql/connection.hpp"
|
#include "matador/sql/connection.hpp"
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@ public:
|
||||||
: db(matador::test::connection::dns)
|
: db(matador::test::connection::dns)
|
||||||
{
|
{
|
||||||
db.open();
|
db.open();
|
||||||
db.create().table<airplane>("airplane").execute();
|
db.query().create().table<airplane>("airplane").execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
~StatementTestFixture()
|
~StatementTestFixture()
|
||||||
|
|
@ -38,7 +38,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
void drop_table_if_exists(const std::string &table_name) {
|
void drop_table_if_exists(const std::string &table_name) {
|
||||||
if (db.exists(table_name)) {
|
if (db.exists(table_name)) {
|
||||||
db.drop().table(table_name).execute();
|
db.query().drop().table(table_name).execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ private:
|
||||||
TEST_CASE_METHOD(StatementTestFixture, " Create prepared statement", "[statement]")
|
TEST_CASE_METHOD(StatementTestFixture, " Create prepared statement", "[statement]")
|
||||||
{
|
{
|
||||||
SECTION("Insert with prepared statement and placeholder") {
|
SECTION("Insert with prepared statement and placeholder") {
|
||||||
auto stmt = db.insert()
|
auto stmt = db.query().insert()
|
||||||
.into<airplane>("airplane")
|
.into<airplane>("airplane")
|
||||||
.values<airplane>().prepare();
|
.values<airplane>().prepare();
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ TEST_CASE_METHOD(StatementTestFixture, " Create prepared statement", "[statement
|
||||||
stmt.reset();
|
stmt.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = db.select<airplane>().from("airplane").fetch_all<airplane>();
|
auto result = db.query().select<airplane>().from("airplane").fetch_all<airplane>();
|
||||||
|
|
||||||
size_t index{0};
|
size_t index{0};
|
||||||
for (const auto &i: result) {
|
for (const auto &i: result) {
|
||||||
|
|
@ -69,11 +69,11 @@ TEST_CASE_METHOD(StatementTestFixture, " Create prepared statement", "[statement
|
||||||
|
|
||||||
SECTION("Select with prepared statement") {
|
SECTION("Select with prepared statement") {
|
||||||
for (const auto &plane: planes) {
|
for (const auto &plane: planes) {
|
||||||
auto res = db.insert().into<airplane>("airplane").values(*plane).execute();
|
auto res = db.query().insert().into<airplane>("airplane").values(*plane).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stmt = db.select<airplane>().from("airplane").where("brand"_col == _).prepare();
|
auto stmt = db.query().select<airplane>().from("airplane").where("brand"_col == _).prepare();
|
||||||
|
|
||||||
stmt.bind(0, "Airbus");
|
stmt.bind(0, "Airbus");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,14 @@ public:
|
||||||
: db(matador::test::connection::dns)
|
: db(matador::test::connection::dns)
|
||||||
{
|
{
|
||||||
db.open();
|
db.open();
|
||||||
db.create()
|
db.query().create()
|
||||||
.table<location>("location")
|
.table<location>("location")
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
~TypeTraitsTestFixture()
|
~TypeTraitsTestFixture()
|
||||||
{
|
{
|
||||||
db.drop().table("location").execute();
|
db.query().drop().table("location").execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -33,7 +33,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
void drop_table_if_exists(const std::string &table_name) {
|
void drop_table_if_exists(const std::string &table_name) {
|
||||||
if (db.exists(table_name)) {
|
if (db.exists(table_name)) {
|
||||||
db.drop().table(table_name).execute();
|
db.query().drop().table(table_name).execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -85,10 +85,10 @@ TEST_CASE_METHOD(TypeTraitsTestFixture, "Special handling of attributes with typ
|
||||||
SECTION("Insert and select with direct execution") {
|
SECTION("Insert and select with direct execution") {
|
||||||
location loc{1, "center", {1, 2, 3}, Color::Black};
|
location loc{1, "center", {1, 2, 3}, Color::Black};
|
||||||
|
|
||||||
auto res = db.insert().into<location>("location").values(loc).execute();
|
auto res = db.query().insert().into<location>("location").values(loc).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
auto result = db.select<location>().from("location").fetch_all<location>();
|
auto result = db.query().select<location>().from("location").fetch_all<location>();
|
||||||
|
|
||||||
for (const auto &l: result) {
|
for (const auto &l: result) {
|
||||||
REQUIRE(l.name == "center");
|
REQUIRE(l.name == "center");
|
||||||
|
|
@ -98,11 +98,11 @@ TEST_CASE_METHOD(TypeTraitsTestFixture, "Special handling of attributes with typ
|
||||||
SECTION("Insert and select with prepared statement") {
|
SECTION("Insert and select with prepared statement") {
|
||||||
location loc{1, "center", {1, 2, 3}, Color::Black};
|
location loc{1, "center", {1, 2, 3}, Color::Black};
|
||||||
|
|
||||||
auto stmt = db.insert().into<location>("location").values<location>().prepare();
|
auto stmt = db.query().insert().into<location>("location").values<location>().prepare();
|
||||||
auto res = stmt.bind(loc).execute();
|
auto res = stmt.bind(loc).execute();
|
||||||
REQUIRE(res == 1);
|
REQUIRE(res == 1);
|
||||||
|
|
||||||
auto result = db.select<location>().from("location").
|
auto result = db.query().select<location>().from("location").
|
||||||
template fetch_all<location>();
|
template fetch_all<location>();
|
||||||
|
|
||||||
for (const auto &l: result) {
|
for (const auto &l: result) {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,75 @@
|
||||||
#include <cstdlib>
|
#include "matador/sql/column.hpp"
|
||||||
#include <iostream>
|
#include "matador/sql/condition.hpp"
|
||||||
|
#include "matador/sql/schema.hpp"
|
||||||
|
#include "matador/sql/connection.hpp"
|
||||||
|
#include "matador/sql/entity.hpp"
|
||||||
|
|
||||||
|
#include "matador/utils/access.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
int main() {
|
struct author
|
||||||
|
{
|
||||||
|
unsigned long id{};
|
||||||
|
std::string first_name;
|
||||||
|
std::string last_name;
|
||||||
|
std::string date_of_birth;
|
||||||
|
unsigned short year_of_birth{};
|
||||||
|
bool distinguished{false};
|
||||||
|
|
||||||
|
template < typename Operator >
|
||||||
|
void process(Operator &op) {
|
||||||
|
namespace field = matador::utils::access;
|
||||||
|
field::primary_key(op, "id", id);
|
||||||
|
field::attribute(op, "first_name", first_name, 63);
|
||||||
|
field::attribute(op, "last_name", last_name, 63);
|
||||||
|
field::attribute(op, "date_of_birth", date_of_birth, 31);
|
||||||
|
field::attribute(op, "year_of_birth", year_of_birth);
|
||||||
|
field::attribute(op, "distinguished", distinguished);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct book
|
||||||
|
{
|
||||||
|
unsigned long id{};
|
||||||
|
matador::sql::entity<author> book_author;
|
||||||
|
std::string title;
|
||||||
|
unsigned short published_in{};
|
||||||
|
|
||||||
|
template < typename Operator >
|
||||||
|
void process(Operator &op) {
|
||||||
|
namespace field = matador::utils::access;
|
||||||
|
field::primary_key(op, "id", id);
|
||||||
|
field::attribute(op, "title", title, 511);
|
||||||
|
field::attribute(op, "published_in", published_in);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace matador::sql;
|
||||||
const std::string env_var{"MATADOR_BACKENDS_PATH"};
|
const std::string env_var{"MATADOR_BACKENDS_PATH"};
|
||||||
|
|
||||||
|
std::string dns;
|
||||||
|
auto s = std::make_shared<schema>();
|
||||||
|
connection c(dns, s);
|
||||||
|
|
||||||
|
auto books = c.query()
|
||||||
|
.select<book>({"author.name"})
|
||||||
|
.from("book")
|
||||||
|
.join_left("author")
|
||||||
|
.on("book.author_id"_col == "author.id"_col)
|
||||||
|
.where("book.published_in"_col < 2008 && "author.name"_col == "Michael Crichton")
|
||||||
|
.order_by("book.title").asc()
|
||||||
|
.fetch_all<book>();
|
||||||
|
|
||||||
|
// SELECT book.title, book.id, book.author_id, book.published_in, author.name
|
||||||
|
// FROM book
|
||||||
|
// INNER JOIN author ON book.author_id = author.id
|
||||||
|
// WHERE book.published_in < 2008 AND author.name = "Michael Crichton"
|
||||||
|
// ORDER BY "book.title" ASC
|
||||||
|
|
||||||
|
|
||||||
// char var[1024];
|
// char var[1024];
|
||||||
// size_t len{};
|
// size_t len{};
|
||||||
// const auto error = getenv_s(&len, var, 1024, env_var.c_str());
|
// const auto error = getenv_s(&len, var, 1024, env_var.c_str());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef QUERY_COLUMN_HPP
|
||||||
|
#define QUERY_COLUMN_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
class column {
|
||||||
|
public:
|
||||||
|
column(const char *name); // NOLINT(*-explicit-constructor)
|
||||||
|
column(std::string name); // NOLINT(*-explicit-constructor)
|
||||||
|
column(std::string table_name, std::string name, std::string as);
|
||||||
|
|
||||||
|
column& as(std::string a);
|
||||||
|
|
||||||
|
std::string table;
|
||||||
|
std::string name;
|
||||||
|
std::string alias;
|
||||||
|
};
|
||||||
|
|
||||||
|
column operator "" _col(const char *name, size_t len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QUERY_COLUMN_HPP
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef QUERY_QUERY_HPP
|
||||||
|
#define QUERY_QUERY_HPP
|
||||||
|
|
||||||
|
#include "matador/query/query_parts.hpp"
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
class connection;
|
||||||
|
class query
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query(connection &c);
|
||||||
|
|
||||||
|
query& select(const std::vector<column> &columns);
|
||||||
|
query& from(const std::string &table, const std::string &as = "");
|
||||||
|
|
||||||
|
private:
|
||||||
|
connection &connection_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_QUERY_HPP
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef QUERY_QUERY_BUILDER_HPP
|
||||||
|
#define QUERY_QUERY_BUILDER_HPP
|
||||||
|
|
||||||
|
#include "matador/query/column.hpp"
|
||||||
|
#include "matador/query/query_intermediates.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/schema.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
class query_builder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query_builder(const std::shared_ptr<sql::schema> &scm);
|
||||||
|
query_select_intermediate select(std::initializer_list<column> columns);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<sql::schema> schema_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_QUERY_BUILDER_HPP
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef QUERY_QUERY_COMPILER_HPP
|
||||||
|
#define QUERY_QUERY_COMPILER_HPP
|
||||||
|
|
||||||
|
#include "matador/query/query_part_visitor.hpp"
|
||||||
|
#include "matador/query/query_parts.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <typeindex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
class dialect;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
struct query_data;
|
||||||
|
|
||||||
|
class query_compiler : public query_part_visitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query_compiler(sql::dialect& d);
|
||||||
|
|
||||||
|
std::string compile(const query_data *data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void visit(query_select_part &select_part) override;
|
||||||
|
void visit(query_from_part &from_part) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
sql::dialect &dialect_;
|
||||||
|
std::string sql_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QUERY_QUERY_COMPILER_HPP
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef QUERY_QUERY_DATA_HPP
|
||||||
|
#define QUERY_QUERY_DATA_HPP
|
||||||
|
|
||||||
|
#include "matador/query/query_parts.hpp"
|
||||||
|
#include "matador/query/sql_commands.hpp"
|
||||||
|
#include "matador/query/table.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
struct query_data
|
||||||
|
{
|
||||||
|
SqlCommands command;
|
||||||
|
std::vector<std::unique_ptr<query_part>> parts;
|
||||||
|
std::vector<column> columns;
|
||||||
|
std::unordered_map<std::type_index, table_data> table_map_by_index;
|
||||||
|
using table_data_ref = std::reference_wrapper<table_data>;
|
||||||
|
std::unordered_map<std::string, table_data_ref> table_map_by_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_QUERY_DATA_HPP
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
#ifndef QUERY_QUERY_INTERMEDIATES_HPP
|
||||||
|
#define QUERY_QUERY_INTERMEDIATES_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/schema.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
class basic_condition;
|
||||||
|
}
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
class query_from_intermediate;
|
||||||
|
class query_join_intermediate;
|
||||||
|
class query_on_intermediate;
|
||||||
|
class query_where_intermediate;
|
||||||
|
class query_group_by_intermediate;
|
||||||
|
class query_order_by_intermediate;
|
||||||
|
class query_order_direction_intermediate;
|
||||||
|
class query_offset_intermediate;
|
||||||
|
class query_limit_intermediate;
|
||||||
|
|
||||||
|
class query_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query_intermediate(const std::shared_ptr<sql::schema> &scm);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
sql::schema& schema() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<sql::schema> schema_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_select_finish_intermediate : public query_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using query_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
void compile();
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_select_intermediate : public query_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using query_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
query_from_intermediate from(const std::string &table, const std::string &as = "");
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_from_intermediate : public query_select_finish_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using query_select_finish_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
query_join_intermediate join(const std::string &join_table_name, const std::string &as);
|
||||||
|
query_where_intermediate where(const sql::basic_condition &cond);
|
||||||
|
query_group_by_intermediate group_by(const std::string &name);
|
||||||
|
query_order_by_intermediate order_by(const std::string &name);
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_join_intermediate : public query_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using query_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
query_on_intermediate on(const std::string &column, const std::string &join_column);
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_on_intermediate : public query_select_finish_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using query_select_finish_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
query_join_intermediate join(const std::string &join_table_name, const std::string &as);
|
||||||
|
query_where_intermediate where(const sql::basic_condition &cond);
|
||||||
|
query_group_by_intermediate group_by(const std::string &name);
|
||||||
|
query_order_by_intermediate order_by(const std::string &name);
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_where_intermediate : public query_select_finish_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using query_select_finish_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
query_group_by_intermediate group_by(const std::string &name);
|
||||||
|
query_order_by_intermediate order_by(const std::string &name);
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_group_by_intermediate : public query_select_finish_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using query_select_finish_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
query_order_by_intermediate order_by(const std::string &name);
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_order_by_intermediate : public query_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using query_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
query_order_direction_intermediate asc();
|
||||||
|
query_order_direction_intermediate desc();
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_order_direction_intermediate : public query_select_finish_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using query_select_finish_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
query_offset_intermediate offset(size_t offset);
|
||||||
|
query_limit_intermediate limit(size_t limit);
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_offset_intermediate : public query_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using query_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
query_limit_intermediate limit(size_t limit);
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_limit_intermediate : public query_select_finish_intermediate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using query_select_finish_intermediate::query_intermediate;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_QUERY_INTERMEDIATES_HPP
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef QUERY_QUERY_PART_VISITOR_HPP
|
||||||
|
#define QUERY_QUERY_PART_VISITOR_HPP
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
class query_select_part;
|
||||||
|
class query_from_part;
|
||||||
|
|
||||||
|
class query_part_visitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~query_part_visitor() = default;
|
||||||
|
|
||||||
|
virtual void visit(query_select_part &select_part) = 0;
|
||||||
|
virtual void visit(query_from_part &from_part) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_QUERY_PART_VISITOR_HPP
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
#ifndef QUERY_QUERY_PARTS_HPP
|
||||||
|
#define QUERY_QUERY_PARTS_HPP
|
||||||
|
|
||||||
|
#include "matador/query/query_part_visitor.hpp"
|
||||||
|
#include "matador/query/column.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/dialect.hpp"
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
class query_part
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
explicit query_part(sql::dialect::token_t token);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~query_part() = default;
|
||||||
|
virtual void accept(query_part_visitor &visitor) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
sql::dialect::token_t token_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the SQL SELECT part
|
||||||
|
*/
|
||||||
|
class query_select_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query_select_part(std::vector<column> columns);
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<column> columns_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the SQL FROM part
|
||||||
|
*/
|
||||||
|
class query_from_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query_from_part(std::string table_name);
|
||||||
|
query_from_part(std::string table_name, std::string as);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string table_;
|
||||||
|
std::string alias_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_QUERY_PARTS_HPP
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef QUERY_SQL_COMMANDS_HPP
|
||||||
|
#define QUERY_SQL_COMMANDS_HPP
|
||||||
|
|
||||||
|
#include "matador/utils/enum_mapper.hpp"
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
enum class SqlCommands
|
||||||
|
{
|
||||||
|
UNKNOWN, /**< Unknown query command */
|
||||||
|
CREATE, /**< Create query command */
|
||||||
|
DROP, /**< Drop query command */
|
||||||
|
SELECT, /**< Select query command */
|
||||||
|
INSERT, /**< Insert query command */
|
||||||
|
UPDATE, /**< Update query command */
|
||||||
|
REMOVE /**< Remove query command */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const utils::enum_mapper<SqlCommands> sql_command_enum({
|
||||||
|
{SqlCommands::UNKNOWN, "unknown"},
|
||||||
|
{SqlCommands::CREATE, "create"},
|
||||||
|
{SqlCommands::DROP, "drop"},
|
||||||
|
{SqlCommands::SELECT, "select"},
|
||||||
|
{SqlCommands::INSERT, "insert"},
|
||||||
|
{SqlCommands::UPDATE, "update"},
|
||||||
|
{SqlCommands::REMOVE, "delete"}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QUERY_SQL_COMMANDS_HPP
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef QUERY_TABLE_HPP
|
||||||
|
#define QUERY_TABLE_HPP
|
||||||
|
|
||||||
|
#include <typeindex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
struct table_data
|
||||||
|
{
|
||||||
|
std::type_index index;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_TABLE_HPP
|
||||||
|
|
@ -1,174 +1,45 @@
|
||||||
#ifndef QUERY_COLUMN_HPP
|
#ifndef QUERY_COLUMN_HPP
|
||||||
#define QUERY_COLUMN_HPP
|
#define QUERY_COLUMN_HPP
|
||||||
|
|
||||||
#include "matador/sql/any_type.hpp"
|
#include <string>
|
||||||
#include "matador/sql/any_type_to_visitor.hpp"
|
|
||||||
#include "matador/sql/data_type_traits.hpp"
|
|
||||||
|
|
||||||
#include "matador/utils/field_attributes.hpp"
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
enum class null_option : uint8_t {
|
enum class sql_function_t {
|
||||||
NULLABLE, NOT_NULL
|
NONE,
|
||||||
|
COUNT,
|
||||||
|
AVG,
|
||||||
|
SUM,
|
||||||
|
MIN,
|
||||||
|
MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
class column {
|
struct column
|
||||||
public:
|
|
||||||
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;
|
|
||||||
column(column&&) noexcept = default;
|
|
||||||
column& operator=(column&&) noexcept = default;
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
explicit column(std::string name, utils::field_attributes attr)
|
|
||||||
: column(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), attr)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
column(std::string name, const Type &, utils::field_attributes attr, null_option null_opt)
|
|
||||||
: column(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), attr, null_opt)
|
|
||||||
{}
|
|
||||||
|
|
||||||
column(std::string name, data_type_t type, utils::field_attributes attr, null_option null_opt, size_t index = 0);
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
column(std::string name, std::string ref_table, std::string ref_column, utils::field_attributes attr, null_option null_opt)
|
|
||||||
: column(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), ref_table, ref_column, attr, null_opt)
|
|
||||||
{}
|
|
||||||
|
|
||||||
column(std::string name, data_type_t type, size_t index, std::string ref_table, std::string ref_column, utils::field_attributes attr, null_option null_opt);
|
|
||||||
|
|
||||||
[[nodiscard]] const std::string& name() const;
|
|
||||||
[[nodiscard]] size_t index() const;
|
|
||||||
[[nodiscard]] const utils::field_attributes& attributes() const;
|
|
||||||
[[nodiscard]] bool is_nullable() 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 type(data_type_t type);
|
|
||||||
void alias(const std::string &as);
|
|
||||||
|
|
||||||
template< typename Type >
|
|
||||||
[[nodiscard]] bool is_type_of() const {
|
|
||||||
return std::holds_alternative<Type>(value_);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string str() const;
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
void set(const Type &value, const utils::field_attributes &attr = utils::null_attributes)
|
|
||||||
{
|
{
|
||||||
type_ = data_type_traits<Type>::builtin_type(attr.size());
|
column(const char *name) : name(name) {} // NOLINT(*-explicit-constructor)
|
||||||
attributes_ = attr;
|
column(std::string name) : name(std::move(name)) {} // NOLINT(*-explicit-constructor)
|
||||||
value_ = value;
|
column(sql_function_t func, std::string name) : name(std::move(name)), function_(func) {} // NOLINT(*-explicit-constructor)
|
||||||
|
column(std::string table_name, std::string name, std::string as)
|
||||||
|
: table(std::move(table_name))
|
||||||
|
, name(std::move(name))
|
||||||
|
, alias(std::move(as)) {} // NOLINT(*-explicit-constructor)
|
||||||
|
|
||||||
|
column& as(std::string a) {
|
||||||
|
alias = std::move(a);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(const std::string &value, const utils::field_attributes &attr)
|
[[nodiscard]] bool is_function() const {
|
||||||
{
|
return function_ != sql_function_t::NONE;
|
||||||
type_ = data_type_traits<std::string>::builtin_type(attr.size());
|
|
||||||
attributes_ = attr;
|
|
||||||
value_ = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(const char *value, const utils::field_attributes &attr)
|
std::string table;
|
||||||
{
|
std::string name;
|
||||||
type_ = data_type_traits<std::string>::builtin_type(attr.size());
|
std::string alias;
|
||||||
attributes_ = attr;
|
|
||||||
value_ = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
Type as() const
|
|
||||||
{
|
|
||||||
const Type* ptr= std::get_if<Type>(&value_);
|
|
||||||
if (ptr) {
|
|
||||||
return *ptr;
|
|
||||||
}
|
|
||||||
any_type_to_visitor<Type> visitor;
|
|
||||||
std::visit(visitor, const_cast<any_type&>(value_));
|
|
||||||
return visitor.result;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool is_function() const;
|
|
||||||
[[nodiscard]] sql_function_t function() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
template<class Operator>
|
|
||||||
void process(Operator &op)
|
|
||||||
{
|
|
||||||
op.on_attribute(name_.c_str(), value_, type_, attributes_);
|
|
||||||
}
|
|
||||||
|
|
||||||
using data_type_index = std::vector<data_type_t>;
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class record;
|
|
||||||
|
|
||||||
static const data_type_index data_type_index_;
|
|
||||||
|
|
||||||
std::string name_;
|
|
||||||
size_t index_{};
|
|
||||||
utils::field_attributes attributes_;
|
|
||||||
null_option null_option_{null_option::NOT_NULL};
|
|
||||||
data_type_t type_{data_type_t::type_unknown};
|
|
||||||
any_type value_;
|
|
||||||
sql_function_t function_{sql_function_t::NONE};
|
sql_function_t function_{sql_function_t::NONE};
|
||||||
std::string alias_;
|
|
||||||
std::string ref_table_;
|
|
||||||
std::string ref_column_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* User defined literal to have a shortcut creating a column object
|
|
||||||
* @param name Name of the column
|
|
||||||
* @param len Length of the column name
|
|
||||||
* @return A column object with given name
|
|
||||||
*/
|
|
||||||
column operator "" _col(const char *name, size_t len);
|
column operator "" _col(const char *name, size_t len);
|
||||||
|
|
||||||
column make_column(const std::string &name, data_type_t type, utils::field_attributes attr = utils::null_attributes, null_option null_opt = null_option::NOT_NULL);
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
column make_column(const std::string &name, utils::field_attributes attr = utils::null_attributes, null_option null_opt = null_option::NOT_NULL)
|
|
||||||
{
|
|
||||||
return make_column(name, data_type_traits<Type>::builtin_type(0), attr, null_opt);
|
|
||||||
}
|
|
||||||
template <>
|
|
||||||
column make_column<std::string>(const std::string &name, utils::field_attributes attr, null_option null_opt);
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
column make_pk_column(const std::string &name, size_t size = 0)
|
|
||||||
{
|
|
||||||
return make_column<Type>(name, { size, utils::constraints::PRIMARY_KEY });
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
column make_pk_column<std::string>(const std::string &name, size_t size);
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
column make_fk_column(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column)
|
|
||||||
{
|
|
||||||
return {name, data_type_traits<Type>::builtin_type(size), ref_table, ref_column, { size, utils::constraints::FOREIGN_KEY }};
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
[[maybe_unused]] column make_fk_column(const std::string &name, const std::string &ref_table, const std::string &ref_column)
|
|
||||||
{
|
|
||||||
return {name, data_type_traits<Type>::builtin_type(0), 0, ref_table, ref_column, { 0, utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
column make_fk_column<std::string>(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //QUERY_COLUMN_HPP
|
#endif //QUERY_COLUMN_HPP
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
#ifndef QUERY_COLUMN_DEFINITION_HPP
|
||||||
|
#define QUERY_COLUMN_DEFINITION_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/any_type.hpp"
|
||||||
|
#include "matador/sql/any_type_to_visitor.hpp"
|
||||||
|
#include "matador/sql/data_type_traits.hpp"
|
||||||
|
|
||||||
|
#include "matador/utils/field_attributes.hpp"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
enum class null_option : uint8_t {
|
||||||
|
NULLABLE, NOT_NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
class column_definition {
|
||||||
|
public:
|
||||||
|
explicit column_definition(const char *name); // NOLINT(*-explicit-constructor)
|
||||||
|
explicit column_definition(std::string name); // NOLINT(*-explicit-constructor)
|
||||||
|
|
||||||
|
column_definition(const column_definition&) = default;
|
||||||
|
column_definition& operator=(const column_definition&) = default;
|
||||||
|
column_definition(column_definition&&) noexcept = default;
|
||||||
|
column_definition& operator=(column_definition&&) noexcept = default;
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
explicit column_definition(std::string name, utils::field_attributes attr)
|
||||||
|
: column_definition(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), attr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
column_definition(std::string name, const Type &, utils::field_attributes attr, null_option null_opt)
|
||||||
|
: column_definition(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), attr, null_opt)
|
||||||
|
{}
|
||||||
|
|
||||||
|
column_definition(std::string name, data_type_t type, utils::field_attributes attr, null_option null_opt, size_t index = 0);
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
column_definition(std::string name, std::string ref_table, std::string ref_column, utils::field_attributes attr, null_option null_opt)
|
||||||
|
: column_definition(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), ref_table, ref_column, attr, null_opt)
|
||||||
|
{}
|
||||||
|
|
||||||
|
column_definition(std::string name, data_type_t type, size_t index, std::string ref_table, std::string ref_column, utils::field_attributes attr, null_option null_opt);
|
||||||
|
|
||||||
|
[[nodiscard]] const std::string& name() const;
|
||||||
|
[[nodiscard]] size_t index() const;
|
||||||
|
[[nodiscard]] const utils::field_attributes& attributes() const;
|
||||||
|
[[nodiscard]] bool is_nullable() const;
|
||||||
|
[[nodiscard]] data_type_t type() const;
|
||||||
|
[[nodiscard]] const std::string& ref_table() const;
|
||||||
|
[[nodiscard]] const std::string& ref_column() const;
|
||||||
|
|
||||||
|
void type(data_type_t type);
|
||||||
|
|
||||||
|
template< typename Type >
|
||||||
|
[[nodiscard]] bool is_type_of() const {
|
||||||
|
return std::holds_alternative<Type>(value_);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::string str() const;
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
void set(const Type &value, const utils::field_attributes &attr = utils::null_attributes)
|
||||||
|
{
|
||||||
|
type_ = data_type_traits<Type>::builtin_type(attr.size());
|
||||||
|
attributes_ = attr;
|
||||||
|
value_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(const std::string &value, const utils::field_attributes &attr)
|
||||||
|
{
|
||||||
|
type_ = data_type_traits<std::string>::builtin_type(attr.size());
|
||||||
|
attributes_ = attr;
|
||||||
|
value_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(const char *value, const utils::field_attributes &attr)
|
||||||
|
{
|
||||||
|
type_ = data_type_traits<std::string>::builtin_type(attr.size());
|
||||||
|
attributes_ = attr;
|
||||||
|
value_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
Type as() const
|
||||||
|
{
|
||||||
|
const Type* ptr= std::get_if<Type>(&value_);
|
||||||
|
if (ptr) {
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
any_type_to_visitor<Type> visitor;
|
||||||
|
std::visit(visitor, const_cast<any_type&>(value_));
|
||||||
|
return visitor.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<class Operator>
|
||||||
|
void process(Operator &op)
|
||||||
|
{
|
||||||
|
op.on_attribute(name_.c_str(), value_, type_, attributes_);
|
||||||
|
}
|
||||||
|
|
||||||
|
using data_type_index = std::vector<data_type_t>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class record;
|
||||||
|
|
||||||
|
static const data_type_index data_type_index_;
|
||||||
|
|
||||||
|
std::string name_;
|
||||||
|
size_t index_{};
|
||||||
|
utils::field_attributes attributes_;
|
||||||
|
null_option null_option_{null_option::NOT_NULL};
|
||||||
|
data_type_t type_{data_type_t::type_unknown};
|
||||||
|
any_type value_;
|
||||||
|
std::string ref_table_;
|
||||||
|
std::string ref_column_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User defined literal to have a shortcut creating a column object
|
||||||
|
* @param name Name of the column
|
||||||
|
* @param len Length of the column name
|
||||||
|
* @return A column object with given name
|
||||||
|
*/
|
||||||
|
column_definition make_column(const std::string &name, data_type_t type, utils::field_attributes attr = utils::null_attributes, null_option null_opt = null_option::NOT_NULL);
|
||||||
|
|
||||||
|
template < typename Type >
|
||||||
|
column_definition make_column(const std::string &name, utils::field_attributes attr = utils::null_attributes, null_option null_opt = null_option::NOT_NULL)
|
||||||
|
{
|
||||||
|
return make_column(name, data_type_traits<Type>::builtin_type(0), attr, null_opt);
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
column_definition make_column<std::string>(const std::string &name, utils::field_attributes attr, null_option null_opt);
|
||||||
|
|
||||||
|
template < typename Type >
|
||||||
|
column_definition make_pk_column(const std::string &name, size_t size = 0)
|
||||||
|
{
|
||||||
|
return make_column<Type>(name, { size, utils::constraints::PRIMARY_KEY });
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
column_definition make_pk_column<std::string>(const std::string &name, size_t size);
|
||||||
|
|
||||||
|
template < typename Type >
|
||||||
|
column_definition make_fk_column(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column)
|
||||||
|
{
|
||||||
|
return {name, data_type_traits<Type>::builtin_type(size), ref_table, ref_column, { size, utils::constraints::FOREIGN_KEY }};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename Type >
|
||||||
|
[[maybe_unused]] column_definition make_fk_column(const std::string &name, const std::string &ref_table, const std::string &ref_column)
|
||||||
|
{
|
||||||
|
return {name, data_type_traits<Type>::builtin_type(0), 0, ref_table, ref_column, { 0, utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
column_definition make_fk_column<std::string>(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_COLUMN_DEFINITION_HPP
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef QUERY_COLUMN_GENERATOR_HPP
|
#ifndef QUERY_COLUMN_GENERATOR_HPP
|
||||||
#define QUERY_COLUMN_GENERATOR_HPP
|
#define QUERY_COLUMN_GENERATOR_HPP
|
||||||
|
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column_definition.hpp"
|
||||||
#include "matador/sql/data_type_traits.hpp"
|
#include "matador/sql/data_type_traits.hpp"
|
||||||
|
|
||||||
#include "matador/utils/access.hpp"
|
#include "matador/utils/access.hpp"
|
||||||
|
|
@ -21,10 +21,10 @@ public:
|
||||||
fk_column_generator() = default;
|
fk_column_generator() = default;
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
column generate(const char *id, Type &x, const std::string &ref_table, const std::string &ref_column)
|
column_definition generate(const char *id, Type &x, const std::string &ref_table, const std::string &ref_column)
|
||||||
{
|
{
|
||||||
utils::access::process(*this, x);
|
utils::access::process(*this, x);
|
||||||
return column{id, type_, 0, ref_table, ref_column, { utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL};
|
return column_definition{id, type_, 0, ref_table, ref_column, {utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
|
|
@ -53,15 +53,15 @@ private:
|
||||||
class column_generator
|
class column_generator
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
column_generator(std::vector<column> &columns, const schema &repo);
|
column_generator(std::vector<column_definition> &columns, const schema &repo);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~column_generator() = default;
|
~column_generator() = default;
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
static std::vector<column> generate(const schema &repo)
|
static std::vector<column_definition> generate(const schema &repo)
|
||||||
{
|
{
|
||||||
std::vector<column> columns;
|
std::vector<column_definition> columns;
|
||||||
column_generator gen(columns, repo);
|
column_generator gen(columns, repo);
|
||||||
Type obj;
|
Type obj;
|
||||||
matador::utils::access::process(gen, obj);
|
matador::utils::access::process(gen, obj);
|
||||||
|
|
@ -101,7 +101,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t index_ = 0;
|
size_t index_ = 0;
|
||||||
std::vector<column> &columns_;
|
std::vector<column_definition> &columns_;
|
||||||
const schema &repo_;
|
const schema &repo_;
|
||||||
|
|
||||||
fk_column_generator fk_column_generator_;
|
fk_column_generator fk_column_generator_;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "matador/utils/field_attributes.hpp"
|
#include "matador/utils/field_attributes.hpp"
|
||||||
#include "matador/utils/foreign_attributes.hpp"
|
#include "matador/utils/foreign_attributes.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/column.hpp"
|
||||||
#include "matador/sql/schema.hpp"
|
#include "matador/sql/schema.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -13,29 +14,22 @@
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
struct column_info
|
|
||||||
{
|
|
||||||
std::string table;
|
|
||||||
std::string name;
|
|
||||||
std::string alias;
|
|
||||||
};
|
|
||||||
|
|
||||||
class column_name_generator
|
class column_name_generator
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
column_name_generator(std::vector<column_info> &column_infos, const sql::schema &ts, const std::string &table_name);
|
column_name_generator(std::vector<column> &column_infos, const sql::schema &ts, const std::string &table_name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~column_name_generator() = default;
|
~column_name_generator() = default;
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
static std::vector<column_info> generate(const sql::schema &ts)
|
static std::vector<column> generate(const sql::schema &ts)
|
||||||
{
|
{
|
||||||
const auto info = ts.info<Type>();
|
const auto info = ts.info<Type>();
|
||||||
if (!info) {
|
if (!info) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
std::vector<column_info> columns;
|
std::vector<column> columns;
|
||||||
column_name_generator gen(columns, ts, info.value().name);
|
column_name_generator gen(columns, ts, info.value().name);
|
||||||
Type obj;
|
Type obj;
|
||||||
matador::utils::access::process(gen, obj);
|
matador::utils::access::process(gen, obj);
|
||||||
|
|
@ -93,7 +87,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::stack<std::string> table_name_stack_;
|
std::stack<std::string> table_name_stack_;
|
||||||
std::vector<column_info> &column_infos_;
|
std::vector<column> &column_infos_;
|
||||||
const sql::schema &table_schema_;
|
const sql::schema &table_schema_;
|
||||||
int column_index{0};
|
int column_index{0};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "matador/sql/query_context.hpp"
|
#include "matador/sql/query_context.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
|
|
@ -55,8 +56,8 @@ public:
|
||||||
|
|
||||||
std::string evaluate(dialect &d, query_context &query) const override
|
std::string evaluate(dialect &d, query_context &query) const override
|
||||||
{
|
{
|
||||||
query.bind_vars.emplace_back(field_.name());
|
query.bind_vars.emplace_back(field_.name);
|
||||||
return d.prepare_identifier(field_.name()) + " " + operand + " " + std::to_string(value);
|
return d.prepare_identifier(field_.name) + " " + operand + " " + std::to_string(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -75,8 +76,8 @@ public:
|
||||||
|
|
||||||
std::string evaluate(dialect &d, query_context &query) const override
|
std::string evaluate(dialect &d, query_context &query) const override
|
||||||
{
|
{
|
||||||
query.bind_vars.emplace_back(field_.name());
|
query.bind_vars.emplace_back(field_.name);
|
||||||
return d.prepare_identifier(field_.name()) + " " + operand + " '" + value + "'";
|
return d.prepare_identifier(field_.name) + " " + operand + " '" + value + "'";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -96,7 +97,7 @@ public:
|
||||||
|
|
||||||
std::string evaluate(dialect &d, query_context &query) const override
|
std::string evaluate(dialect &d, query_context &query) const override
|
||||||
{
|
{
|
||||||
return std::to_string(value) + " " + operand + " " + d.prepare_identifier(field_.name());
|
return std::to_string(value) + " " + operand + " " + d.prepare_identifier(field_.name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -115,7 +116,7 @@ public:
|
||||||
|
|
||||||
std::string evaluate(dialect &d, query_context &query) const override
|
std::string evaluate(dialect &d, query_context &query) const override
|
||||||
{
|
{
|
||||||
return "'" + std::to_string(value) + "' " + operand + " " + d.prepare_identifier(field_.name());
|
return "'" + std::to_string(value) + "' " + operand + " " + d.prepare_identifier(field_.name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -158,10 +159,10 @@ public:
|
||||||
std::string evaluate(dialect &d, query_context &query) const override {
|
std::string evaluate(dialect &d, query_context &query) const override {
|
||||||
auto count = size();
|
auto count = size();
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < count; ++i) {
|
||||||
query.bind_vars.emplace_back(field_.name());
|
query.bind_vars.emplace_back(field_.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string result = d.prepare_identifier(field_.name()) + " IN (";
|
std::string result = d.prepare_identifier(field_.name) + " IN (";
|
||||||
if (args_.size() < 2) {
|
if (args_.size() < 2) {
|
||||||
for (const auto &val : args_) {
|
for (const auto &val : args_) {
|
||||||
result.append(std::to_string(val));
|
result.append(std::to_string(val));
|
||||||
|
|
@ -261,9 +262,9 @@ public:
|
||||||
* @return A condition BETWEEN part of the query
|
* @return A condition BETWEEN part of the query
|
||||||
*/
|
*/
|
||||||
std::string evaluate(dialect &d, query_context &query) const override {
|
std::string evaluate(dialect &d, query_context &query) const override {
|
||||||
query.bind_vars.emplace_back(field_.name());
|
query.bind_vars.emplace_back(field_.name);
|
||||||
query.bind_vars.emplace_back(field_.name());
|
query.bind_vars.emplace_back(field_.name);
|
||||||
return d.prepare_identifier(field_.name()) + " BETWEEN " + std::to_string(range_.first) + " AND " + std::to_string(range_.second);
|
return d.prepare_identifier(field_.name) + " BETWEEN " + std::to_string(range_.first) + " AND " + std::to_string(range_.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -355,6 +356,28 @@ private:
|
||||||
std::string operand;
|
std::string operand;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class condition<column, column> : public basic_column_condition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
condition(const column &a, basic_condition::operand_t op, column b)
|
||||||
|
: basic_column_condition(a, op)
|
||||||
|
, other_column_(std::move(b)) {}
|
||||||
|
/**
|
||||||
|
* @brief Evaluates the condition
|
||||||
|
*
|
||||||
|
* @param d The d used to evaluate
|
||||||
|
* @return The evaluated string based on the compile type
|
||||||
|
*/
|
||||||
|
std::string evaluate(dialect &d, query_context &query) const override
|
||||||
|
{
|
||||||
|
return d.prepare_identifier(field_.name) + " " + operand + " " + d.prepare_identifier(other_column_.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
column other_column_;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file condition.hpp
|
* @file condition.hpp
|
||||||
* @brief Contains functions to create query conditions
|
* @brief Contains functions to create query conditions
|
||||||
|
|
@ -441,6 +464,8 @@ condition<column, T> operator==(const column &col, T val)
|
||||||
return condition<column, T>(col, basic_condition::operand_t::EQUAL, val);
|
return condition<column, T>(col, basic_condition::operand_t::EQUAL, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
condition<column, column> operator==(const column &a, const column &b);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Condition equality method for a column and a query
|
* @brief Condition equality method for a column and a query
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,12 @@
|
||||||
#include "matador/sql/connection_info.hpp"
|
#include "matador/sql/connection_info.hpp"
|
||||||
#include "matador/sql/connection_impl.hpp"
|
#include "matador/sql/connection_impl.hpp"
|
||||||
#include "matador/sql/dialect.hpp"
|
#include "matador/sql/dialect.hpp"
|
||||||
#include "matador/sql/query_intermediates.hpp"
|
#include "matador/sql/query.hpp"
|
||||||
#include "matador/sql/query_context.hpp"
|
#include "matador/sql/query_context.hpp"
|
||||||
#include "matador/sql/query_result.hpp"
|
#include "matador/sql/query_result.hpp"
|
||||||
#include "matador/sql/record.hpp"
|
#include "matador/sql/record.hpp"
|
||||||
#include "matador/sql/statement.hpp"
|
#include "matador/sql/statement.hpp"
|
||||||
|
#include "matador/sql/schema.hpp"
|
||||||
|
|
||||||
#include "matador/utils/logger.hpp"
|
#include "matador/utils/logger.hpp"
|
||||||
|
|
||||||
|
|
@ -19,8 +20,8 @@ namespace matador::sql {
|
||||||
class connection
|
class connection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit connection(connection_info info, const std::shared_ptr<schema> &repo = std::make_shared<schema>());
|
explicit connection(connection_info info, const std::shared_ptr<schema> &repo = std::make_shared<sql::schema>());
|
||||||
explicit connection(const std::string& dns, const std::shared_ptr<schema> &repo = std::make_shared<schema>());
|
explicit connection(const std::string& dns, const std::shared_ptr<schema> &repo = std::make_shared<sql::schema>());
|
||||||
connection(const connection &x);
|
connection(const connection &x);
|
||||||
connection& operator=(const connection &x);
|
connection& operator=(const connection &x);
|
||||||
connection(connection &&x) noexcept = default;
|
connection(connection &&x) noexcept = default;
|
||||||
|
|
@ -31,19 +32,12 @@ public:
|
||||||
[[nodiscard]] bool is_open() const;
|
[[nodiscard]] bool is_open() const;
|
||||||
[[nodiscard]] const connection_info& info() const;
|
[[nodiscard]] const connection_info& info() const;
|
||||||
|
|
||||||
query_create_intermediate create();
|
|
||||||
query_drop_intermediate drop();
|
|
||||||
template < class Type >
|
|
||||||
query_select_intermediate select();
|
|
||||||
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();
|
|
||||||
|
|
||||||
[[nodiscard]] record describe(const std::string &table_name) const;
|
[[nodiscard]] record describe(const std::string &table_name) const;
|
||||||
[[nodiscard]] bool exists(const std::string &schema_name, const std::string &table_name) const;
|
[[nodiscard]] bool exists(const std::string &schema_name, const std::string &table_name) const;
|
||||||
[[nodiscard]] bool exists(const std::string &table_name) const;
|
[[nodiscard]] bool exists(const std::string &table_name) const;
|
||||||
|
|
||||||
|
sql::query query() const;
|
||||||
|
|
||||||
query_result<record> fetch(const query_context &q) const;
|
query_result<record> fetch(const query_context &q) const;
|
||||||
[[nodiscard]] std::unique_ptr<query_result_impl> fetch(const std::string &sql) const;
|
[[nodiscard]] std::unique_ptr<query_result_impl> fetch(const std::string &sql) const;
|
||||||
[[nodiscard]] size_t execute(const std::string &sql) const;
|
[[nodiscard]] size_t execute(const std::string &sql) const;
|
||||||
|
|
@ -51,21 +45,15 @@ public:
|
||||||
statement prepare(query_context &&query) const;
|
statement prepare(query_context &&query) const;
|
||||||
|
|
||||||
const class dialect& dialect() const;
|
const class dialect& dialect() const;
|
||||||
std::shared_ptr<schema> tables() const;
|
std::shared_ptr<sql::schema> schema() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
connection_info connection_info_;
|
connection_info connection_info_;
|
||||||
std::unique_ptr<connection_impl> connection_;
|
std::unique_ptr<connection_impl> connection_;
|
||||||
utils::logger logger_;
|
utils::logger logger_;
|
||||||
const class dialect &dialect_;
|
const class dialect &dialect_;
|
||||||
std::shared_ptr<schema> schema_;
|
std::shared_ptr<sql::schema> schema_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
query_select_intermediate connection::select()
|
|
||||||
{
|
|
||||||
return query_select_intermediate{*this, column_generator::generate<Type>(*schema_)};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //QUERY_CONNECTION_HPP
|
#endif //QUERY_CONNECTION_HPP
|
||||||
|
|
|
||||||
|
|
@ -41,16 +41,6 @@ enum class data_type_t : uint8_t {
|
||||||
type_unknown /*!< Data type unknown */
|
type_unknown /*!< Data type unknown */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class sql_function_t {
|
|
||||||
NONE,
|
|
||||||
COUNT,
|
|
||||||
AVG,
|
|
||||||
SUM,
|
|
||||||
MIN,
|
|
||||||
MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @tparam T The type of the traits
|
* @tparam T The type of the traits
|
||||||
* @brief Type traits for database types
|
* @brief Type traits for database types
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef QUERY_DIALECT_HPP
|
#ifndef QUERY_DIALECT_HPP
|
||||||
#define QUERY_DIALECT_HPP
|
#define QUERY_DIALECT_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/column.hpp"
|
||||||
#include "matador/sql/data_type_traits.hpp"
|
#include "matador/sql/data_type_traits.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
@ -11,8 +12,6 @@
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
class column;
|
|
||||||
|
|
||||||
class dialect final
|
class dialect final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef QUERY_QUERY_HPP
|
||||||
|
#define QUERY_QUERY_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/query_intermediates.hpp"
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
class connection;
|
||||||
|
|
||||||
|
class query
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query(connection &c);
|
||||||
|
query(const query &) = delete;
|
||||||
|
query& operator=(const query &) = delete;
|
||||||
|
|
||||||
|
query_create_intermediate create();
|
||||||
|
query_drop_intermediate drop();
|
||||||
|
template < class Type >
|
||||||
|
query_select_intermediate select();
|
||||||
|
template < class Type >
|
||||||
|
query_select_intermediate select(std::initializer_list<column> columns);
|
||||||
|
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();
|
||||||
|
|
||||||
|
private:
|
||||||
|
[[nodiscard]] const sql::schema& schema() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
connection &connection_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
query_select_intermediate query::select()
|
||||||
|
{
|
||||||
|
return query_select_intermediate{connection_, column_name_generator::generate<Type>(this->schema())};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
query_select_intermediate query::select(std::initializer_list<column> columns)
|
||||||
|
{
|
||||||
|
return query_select_intermediate{connection_, column_name_generator::generate<Type>(this->schema())};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_QUERY_HPP
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define QUERY_QUERY_BUILDER_HPP
|
#define QUERY_QUERY_BUILDER_HPP
|
||||||
|
|
||||||
#include "matador/sql/basic_condition.hpp"
|
#include "matador/sql/basic_condition.hpp"
|
||||||
|
#include "matador/sql/column_definition.hpp"
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column.hpp"
|
||||||
#include "matador/sql/dialect.hpp"
|
#include "matador/sql/dialect.hpp"
|
||||||
#include "matador/sql/key_value_pair.hpp"
|
#include "matador/sql/key_value_pair.hpp"
|
||||||
|
|
@ -123,11 +124,11 @@ public:
|
||||||
query_builder& update(const std::string &table);
|
query_builder& update(const std::string &table);
|
||||||
query_builder& remove();
|
query_builder& remove();
|
||||||
|
|
||||||
query_builder& table(const std::string &table, std::initializer_list<column> columns);
|
query_builder& table(const std::string &table, std::initializer_list<column_definition> columns);
|
||||||
query_builder& table(const std::string &table, const std::vector<column> &columns);
|
query_builder& table(const std::string &table, const std::vector<column_definition> &columns);
|
||||||
query_builder& table(const std::string &table);
|
query_builder& table(const std::string &table);
|
||||||
query_builder& into(const std::string &table, std::initializer_list<column_info> column_names);
|
query_builder& into(const std::string &table, std::initializer_list<column> column_names);
|
||||||
query_builder& into(const std::string &table, const std::vector<column_info> &column_names);
|
query_builder& into(const std::string &table, const std::vector<column> &column_names);
|
||||||
query_builder& values(std::initializer_list<any_type> values);
|
query_builder& values(std::initializer_list<any_type> values);
|
||||||
query_builder& values(const std::vector<any_type> &values);
|
query_builder& values(const std::vector<any_type> &values);
|
||||||
query_builder& from(const std::string &table, const std::string &as = "");
|
query_builder& from(const std::string &table, const std::string &as = "");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef QUERY_QUERY_COMPILER_HPP
|
||||||
|
#define QUERY_QUERY_COMPILER_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/query_part_visitor.hpp"
|
||||||
|
#include "matador/sql/query_parts.hpp"
|
||||||
|
#include "matador/sql/query_context.hpp"
|
||||||
|
|
||||||
|
#include <typeindex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
class dialect;
|
||||||
|
|
||||||
|
struct query_data;
|
||||||
|
|
||||||
|
class query_compiler : public query_part_visitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query_compiler(const sql::dialect& d);
|
||||||
|
|
||||||
|
query_context compile(const query_data *data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void visit(query_select_part &select_part) override;
|
||||||
|
void visit(query_from_part &from_part) override;
|
||||||
|
void visit(query_where_part &where_part) override;
|
||||||
|
void visit(query_group_by_part &group_by_part) override;
|
||||||
|
void visit(query_order_by_part &order_by_part) override;
|
||||||
|
void visit(query_order_by_asc_part &order_by_asc_part) override;
|
||||||
|
void visit(query_order_by_desc_part &order_by_desc_part) override;
|
||||||
|
|
||||||
|
void visit(query_insert_part &insert_part) override;
|
||||||
|
void visit(query_values_part &values_part) override;
|
||||||
|
|
||||||
|
void visit(query_update_part &update_part) override;
|
||||||
|
|
||||||
|
void visit(query_delete_part &delete_part) override;
|
||||||
|
|
||||||
|
void visit(query_create_part &create_part) override;
|
||||||
|
|
||||||
|
void visit(query_drop_part &drop_part) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const sql::dialect &dialect_;
|
||||||
|
query_context query_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QUERY_QUERY_COMPILER_HPP
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef QUERY_QUERY_DATA_HPP
|
||||||
|
#define QUERY_QUERY_DATA_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/query_parts.hpp"
|
||||||
|
#include "matador/sql/table.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
struct query_data
|
||||||
|
{
|
||||||
|
// SqlCommands command;
|
||||||
|
std::vector<std::unique_ptr<query_part>> parts;
|
||||||
|
std::vector<column_definition> columns;
|
||||||
|
std::unordered_map<std::type_index, table> table_map_by_index;
|
||||||
|
using table_ref = std::reference_wrapper<table>;
|
||||||
|
std::unordered_map<std::string, table_ref> table_map_by_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QUERY_QUERY_DATA_HPP
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
#ifndef QUERY_QUERY_INTERMEDIATES_HPP
|
#ifndef QUERY_QUERY_INTERMEDIATES_HPP
|
||||||
#define QUERY_QUERY_INTERMEDIATES_HPP
|
#define QUERY_QUERY_INTERMEDIATES_HPP
|
||||||
|
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column_definition.hpp"
|
||||||
#include "matador/sql/column_generator.hpp"
|
#include "matador/sql/column_generator.hpp"
|
||||||
#include "matador/sql/column_name_generator.hpp"
|
#include "matador/sql/column_name_generator.hpp"
|
||||||
#include "matador/sql/key_value_generator.hpp"
|
#include "matador/sql/key_value_generator.hpp"
|
||||||
#include "matador/sql/key_value_pair.hpp"
|
#include "matador/sql/key_value_pair.hpp"
|
||||||
#include "matador/sql/placeholder_generator.hpp"
|
#include "matador/sql/placeholder_generator.hpp"
|
||||||
#include "matador/sql/query_builder.hpp"
|
|
||||||
#include "matador/sql/query_result.hpp"
|
#include "matador/sql/query_result.hpp"
|
||||||
|
#include "matador/sql/query_data.hpp"
|
||||||
#include "matador/sql/record.hpp"
|
#include "matador/sql/record.hpp"
|
||||||
#include "matador/sql/statement.hpp"
|
#include "matador/sql/statement.hpp"
|
||||||
#include "matador/sql/schema.hpp"
|
#include "matador/sql/schema.hpp"
|
||||||
|
|
@ -36,10 +36,10 @@ protected:
|
||||||
class query_intermediate : public basic_query_intermediate
|
class query_intermediate : public basic_query_intermediate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
query_intermediate(connection &db, query_builder &query);
|
query_intermediate(connection &db, query_data &data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
query_builder &builder_;
|
query_data &data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class query_execute_finish : public query_intermediate
|
class query_execute_finish : public query_intermediate
|
||||||
|
|
@ -146,7 +146,7 @@ class query_join_intermediate : public query_intermediate
|
||||||
public:
|
public:
|
||||||
using query_intermediate::query_intermediate;
|
using query_intermediate::query_intermediate;
|
||||||
|
|
||||||
query_on_intermediate on(const std::string &column, const std::string &join_column);
|
query_on_intermediate on(const basic_condition &cond);
|
||||||
};
|
};
|
||||||
|
|
||||||
class query_from_intermediate : public query_select_finish
|
class query_from_intermediate : public query_select_finish
|
||||||
|
|
@ -154,7 +154,7 @@ class query_from_intermediate : public query_select_finish
|
||||||
public:
|
public:
|
||||||
using query_select_finish::query_select_finish;
|
using query_select_finish::query_select_finish;
|
||||||
|
|
||||||
query_join_intermediate join(const std::string &join_table_name, const std::string &as);
|
query_join_intermediate join_left(const std::string &join_table_name, const std::string &as = "");
|
||||||
query_where_intermediate where(const basic_condition &cond);
|
query_where_intermediate where(const basic_condition &cond);
|
||||||
query_group_by_intermediate group_by(const std::string &name);
|
query_group_by_intermediate group_by(const std::string &name);
|
||||||
query_order_by_intermediate order_by(const std::string &name);
|
query_order_by_intermediate order_by(const std::string &name);
|
||||||
|
|
@ -163,10 +163,10 @@ public:
|
||||||
class query_start_intermediate : public basic_query_intermediate
|
class query_start_intermediate : public basic_query_intermediate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit query_start_intermediate(connection &s);
|
explicit query_start_intermediate(connection &db);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
query_builder builder_;
|
query_data data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class query_select_intermediate : public query_start_intermediate
|
class query_select_intermediate : public query_start_intermediate
|
||||||
|
|
@ -192,16 +192,19 @@ public:
|
||||||
using query_intermediate::query_intermediate;
|
using query_intermediate::query_intermediate;
|
||||||
|
|
||||||
query_execute_finish values(std::initializer_list<any_type> values);
|
query_execute_finish values(std::initializer_list<any_type> values);
|
||||||
|
query_execute_finish values(const std::vector<any_type>& values);
|
||||||
template<class Type>
|
template<class Type>
|
||||||
query_execute_finish values()
|
query_execute_finish values()
|
||||||
{
|
{
|
||||||
Type obj;
|
Type obj;
|
||||||
return {connection_, builder_.values(as_placeholder(obj))};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.values(as_placeholder(obj))};
|
||||||
}
|
}
|
||||||
template<class Type>
|
template<class Type>
|
||||||
query_execute_finish values(const Type &obj)
|
query_execute_finish values(const Type &obj)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.values(value_extractor::extract(obj))};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.values(value_extractor::extract(obj))};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -210,15 +213,16 @@ class query_create_intermediate : public query_start_intermediate
|
||||||
public:
|
public:
|
||||||
explicit query_create_intermediate(connection &db);
|
explicit query_create_intermediate(connection &db);
|
||||||
|
|
||||||
query_execute_finish table(const std::string &table_name, std::initializer_list<column> columns);
|
query_execute_finish table(const std::string &table_name, std::initializer_list<column_definition> columns);
|
||||||
query_execute_finish table(const std::string &table_name, const std::vector<column> &columns);
|
query_execute_finish table(const std::string &table_name, const std::vector<column_definition> &columns);
|
||||||
template<class Type>
|
template<class Type>
|
||||||
query_execute_finish table(const std::string &table_name)
|
query_execute_finish table(const std::string &table_name)
|
||||||
{
|
{
|
||||||
if (!tables()->exists<Type>()) {
|
if (!tables()->exists<Type>()) {
|
||||||
tables()->attach<Type>(table_name);
|
tables()->attach<Type>(table_name);
|
||||||
}
|
}
|
||||||
return {connection_, builder_.table(table_name, column_generator::generate<Type>(*tables()))};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.table(table_name, column_generator::generate<Type>(*tables()))};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -235,17 +239,19 @@ class query_insert_intermediate : public query_start_intermediate
|
||||||
public:
|
public:
|
||||||
explicit query_insert_intermediate(connection &s);
|
explicit query_insert_intermediate(connection &s);
|
||||||
|
|
||||||
query_into_intermediate into(const std::string &table, std::initializer_list<column_info> column_names);
|
query_into_intermediate into(const std::string &table, std::initializer_list<column> column_names);
|
||||||
template<class Type>
|
template<class Type>
|
||||||
query_into_intermediate into(const std::string &table)
|
query_into_intermediate into(const std::string &table)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))};
|
||||||
}
|
}
|
||||||
template<class Type>
|
template<class Type>
|
||||||
query_execute_finish into(const std::string &table, const Type &obj)
|
query_execute_finish into(const std::string &table, const Type &obj)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))
|
return {connection_, data_};
|
||||||
.values(value_extractor::extract(obj))};
|
// return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))
|
||||||
|
// .values(value_extractor::extract(obj))};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -274,7 +280,8 @@ public:
|
||||||
template<class Type>
|
template<class Type>
|
||||||
query_set_intermediate set(const Type &obj)
|
query_set_intermediate set(const Type &obj)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.set(key_value_generator::generate(obj))};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.set(key_value_generator::generate(obj))};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
#ifndef QUERY_QUERY_PART_VISITOR_HPP
|
||||||
|
#define QUERY_QUERY_PART_VISITOR_HPP
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
class query_select_part;
|
||||||
|
class query_from_part;
|
||||||
|
class query_where_part;
|
||||||
|
class query_group_by_part;
|
||||||
|
class query_order_by_part;
|
||||||
|
class query_order_by_asc_part;
|
||||||
|
class query_order_by_desc_part;
|
||||||
|
class query_insert_part;
|
||||||
|
class query_values_part;
|
||||||
|
class query_update_part;
|
||||||
|
class query_delete_part;
|
||||||
|
class query_create_part;
|
||||||
|
class query_drop_part;
|
||||||
|
|
||||||
|
class query_part_visitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~query_part_visitor() = default;
|
||||||
|
|
||||||
|
virtual void visit(query_select_part &select_part) = 0;
|
||||||
|
virtual void visit(query_from_part &from_part) = 0;
|
||||||
|
virtual void visit(query_where_part &where_part) = 0;
|
||||||
|
virtual void visit(query_group_by_part &group_by_part) = 0;
|
||||||
|
virtual void visit(query_order_by_part &order_by_part) = 0;
|
||||||
|
virtual void visit(query_order_by_asc_part &order_by_asc_part) = 0;
|
||||||
|
virtual void visit(query_order_by_desc_part &order_by_desc_part) = 0;
|
||||||
|
|
||||||
|
virtual void visit(query_insert_part &insert_part) = 0;
|
||||||
|
virtual void visit(query_values_part &values_part) = 0;
|
||||||
|
|
||||||
|
virtual void visit(query_update_part &update_part) = 0;
|
||||||
|
|
||||||
|
virtual void visit(query_delete_part &delete_part) = 0;
|
||||||
|
|
||||||
|
virtual void visit(query_create_part &create_part) = 0;
|
||||||
|
virtual void visit(query_drop_part &drop_part) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QUERY_QUERY_PART_VISITOR_HPP
|
||||||
|
|
@ -0,0 +1,181 @@
|
||||||
|
#ifndef QUERY_QUERY_PARTS_HPP
|
||||||
|
#define QUERY_QUERY_PARTS_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/query_part_visitor.hpp"
|
||||||
|
#include "matador/sql/column.hpp"
|
||||||
|
#include "matador/sql/column_definition.hpp"
|
||||||
|
#include "matador/sql/dialect.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
class basic_condition;
|
||||||
|
|
||||||
|
class query_part
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
explicit query_part(sql::dialect::token_t token);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~query_part() = default;
|
||||||
|
virtual void accept(query_part_visitor &visitor) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
sql::dialect::token_t token_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the SQL SELECT part
|
||||||
|
*/
|
||||||
|
class query_select_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query_select_part(std::vector<column> columns);
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
||||||
|
[[nodiscard]] const std::vector<column>& columns() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<column> columns_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the SQL FROM part
|
||||||
|
*/
|
||||||
|
class query_from_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query_from_part(std::string table_name);
|
||||||
|
query_from_part(std::string table_name, std::string as);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string table_;
|
||||||
|
std::string alias_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_where_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template < class Condition >
|
||||||
|
explicit query_where_part(const Condition &cond)
|
||||||
|
: query_part(dialect::token_t::WHERE)
|
||||||
|
, condition_(new Condition(cond)) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<basic_condition> condition_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_table_name_part : public query_part
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
explicit query_table_name_part(sql::dialect::token_t token, std::string table_name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string table_name_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_group_by_part : public query_table_name_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query_group_by_part(const std::string &table_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_order_by_part : public query_table_name_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query_order_by_part(const std::string &table_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_order_by_asc_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
query_order_by_asc_part();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_order_by_desc_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
query_order_by_desc_part();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_insert_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
query_insert_part();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the SQL VALUES part
|
||||||
|
*/
|
||||||
|
class query_values_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
query_values_part(std::initializer_list<any_type> values);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<any_type> values_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_update_part : public query_table_name_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit query_update_part(const std::string &table_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_delete_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
query_delete_part();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_create_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
query_create_part();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_drop_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
query_drop_part();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_QUERY_PARTS_HPP
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "matador/utils/access.hpp"
|
#include "matador/utils/access.hpp"
|
||||||
|
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column_definition.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
@ -13,8 +13,8 @@ namespace matador::sql {
|
||||||
class record
|
class record
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using column_by_index = std::vector<column>;
|
using column_by_index = std::vector<column_definition>;
|
||||||
using column_index_pair = std::pair<std::reference_wrapper<column>, size_t>;
|
using column_index_pair = std::pair<std::reference_wrapper<column_definition>, size_t>;
|
||||||
using column_by_name_map = std::unordered_map<std::string, column_index_pair>;
|
using column_by_name_map = std::unordered_map<std::string, column_index_pair>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -22,8 +22,8 @@ public:
|
||||||
using const_iterator = column_by_index::const_iterator;
|
using const_iterator = column_by_index::const_iterator;
|
||||||
|
|
||||||
record() = default;
|
record() = default;
|
||||||
record(std::initializer_list<column> columns);
|
record(std::initializer_list<column_definition> columns);
|
||||||
explicit record(const std::vector<column> &columns);
|
explicit record(const std::vector<column_definition> &columns);
|
||||||
record(const record &x);
|
record(const record &x);
|
||||||
record& operator=(const record &x);
|
record& operator=(const record &x);
|
||||||
record(record&&) noexcept = default;
|
record(record&&) noexcept = default;
|
||||||
|
|
@ -43,15 +43,15 @@ public:
|
||||||
append(make_column<Type>(name, size));
|
append(make_column<Type>(name, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(column col);
|
void append(column_definition col);
|
||||||
|
|
||||||
[[nodiscard]] bool has_primary_key() const;
|
[[nodiscard]] bool has_primary_key() const;
|
||||||
[[nodiscard]] const column& primary_key() const;
|
[[nodiscard]] const column_definition& primary_key() const;
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<column>& columns() const;
|
[[nodiscard]] const std::vector<column_definition>& columns() const;
|
||||||
|
|
||||||
[[nodiscard]] const column& at(const std::string &name) const;
|
[[nodiscard]] const column_definition& at(const std::string &name) const;
|
||||||
[[nodiscard]] const column& at(size_t index) const;
|
[[nodiscard]] const column_definition& at(size_t index) const;
|
||||||
|
|
||||||
iterator find(const std::string &column_name);
|
iterator find(const std::string &column_name);
|
||||||
[[nodiscard]] const_iterator find(const std::string &column_name) const;
|
[[nodiscard]] const_iterator find(const std::string &column_name) const;
|
||||||
|
|
@ -72,7 +72,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
void add_to_map(column &col, size_t index);
|
void add_to_map(column_definition &col, size_t index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
column_by_index columns_;
|
column_by_index columns_;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ public:
|
||||||
using iterator = repository::iterator;
|
using iterator = repository::iterator;
|
||||||
using const_iterator = repository::const_iterator;
|
using const_iterator = repository::const_iterator;
|
||||||
|
|
||||||
|
std::string name() const;
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
const table_info& attach(const std::string &table_name)
|
const table_info& attach(const std::string &table_name)
|
||||||
{
|
{
|
||||||
|
|
@ -68,6 +70,7 @@ public:
|
||||||
[[nodiscard]] bool empty() const;
|
[[nodiscard]] bool empty() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::string name_;
|
||||||
repository repository_;
|
repository repository_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ entity<Type> session::insert(Type *obj)
|
||||||
if (!info) {
|
if (!info) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
c->insert().into<Type>(info->name).values(*obj).execute();
|
c->query().insert().into<Type>(info->name).values(*obj).execute();
|
||||||
|
|
||||||
return entity{obj};
|
return entity{obj};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef QUERY_TABLE_HPP
|
||||||
|
#define QUERY_TABLE_HPP
|
||||||
|
|
||||||
|
#include <typeindex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
struct table
|
||||||
|
{
|
||||||
|
std::type_index index;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QUERY_TABLE_HPP
|
||||||
|
|
@ -38,7 +38,7 @@ std::string to_string(const blob &data);
|
||||||
* given stream
|
* given stream
|
||||||
*
|
*
|
||||||
* @tparam R Type og the range (e.g. map, list, vector, etc)
|
* @tparam R Type og the range (e.g. map, list, vector, etc)
|
||||||
* @param range The range with the elements to join
|
* @param range The range with the elements to join_left
|
||||||
* @param delim The delimiter for the elements
|
* @param delim The delimiter for the elements
|
||||||
* @return The ostream reference
|
* @return The ostream reference
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
set(SQL_SOURCES
|
set(SQL_SOURCES
|
||||||
sql/dialect.cpp
|
sql/dialect.cpp
|
||||||
sql/query_builder.cpp
|
sql/query_builder.cpp
|
||||||
sql/column.cpp
|
sql/column_definition.cpp
|
||||||
sql/key_value_pair.cpp
|
sql/key_value_pair.cpp
|
||||||
sql/basic_condition.cpp
|
sql/basic_condition.cpp
|
||||||
sql/connection.cpp
|
sql/connection.cpp
|
||||||
|
|
@ -28,12 +28,16 @@ set(SQL_SOURCES
|
||||||
sql/result_parameter_binder.cpp
|
sql/result_parameter_binder.cpp
|
||||||
sql/statement.cpp
|
sql/statement.cpp
|
||||||
sql/convert.cpp
|
sql/convert.cpp
|
||||||
|
sql/column.cpp
|
||||||
|
sql/query.cpp
|
||||||
|
sql/query_parts.cpp
|
||||||
|
sql/query_compiler.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SQL_HEADER
|
set(SQL_HEADER
|
||||||
../include/matador/sql/dialect.hpp
|
../include/matador/sql/dialect.hpp
|
||||||
../include/matador/sql/query_builder.hpp
|
../include/matador/sql/query_builder.hpp
|
||||||
../include/matador/sql/column.hpp
|
../include/matador/sql/column_definition.hpp
|
||||||
../include/matador/sql/data_type_traits.hpp
|
../include/matador/sql/data_type_traits.hpp
|
||||||
../include/matador/sql/key_value_pair.hpp
|
../include/matador/sql/key_value_pair.hpp
|
||||||
../include/matador/sql/basic_condition.hpp
|
../include/matador/sql/basic_condition.hpp
|
||||||
|
|
@ -69,6 +73,34 @@ set(SQL_HEADER
|
||||||
../include/matador/sql/placeholder_generator.hpp
|
../include/matador/sql/placeholder_generator.hpp
|
||||||
../include/matador/sql/result_parameter_binder.hpp
|
../include/matador/sql/result_parameter_binder.hpp
|
||||||
../include/matador/sql/convert.hpp
|
../include/matador/sql/convert.hpp
|
||||||
|
../include/matador/sql/query.hpp
|
||||||
|
../include/matador/sql/query_parts.hpp
|
||||||
|
../include/matador/sql/query_part_visitor.hpp
|
||||||
|
../include/matador/sql/query_compiler.hpp
|
||||||
|
../include/matador/sql/query_data.hpp
|
||||||
|
../include/matador/sql/table.hpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(QUERY_SOURCES
|
||||||
|
query/query.cpp
|
||||||
|
query/query_compiler.cpp
|
||||||
|
query/query_parts.cpp
|
||||||
|
query/column.cpp
|
||||||
|
query/query_builder.cpp
|
||||||
|
query/query_intermediates.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(QUERY_HEADER
|
||||||
|
../include/matador/query/query.hpp
|
||||||
|
../include/matador/query/query_part_visitor.hpp
|
||||||
|
../include/matador/query/query_compiler.hpp
|
||||||
|
../include/matador/query/query_parts.hpp
|
||||||
|
../include/matador/query/column.hpp
|
||||||
|
../include/matador/query/query_builder.hpp
|
||||||
|
../include/matador/query/query_intermediates.hpp
|
||||||
|
../include/matador/query/sql_commands.hpp
|
||||||
|
../include/matador/query/query_data.hpp
|
||||||
|
../include/matador/query/table.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(UTILS_HEADER
|
set(UTILS_HEADER
|
||||||
|
|
@ -84,7 +116,8 @@ set(UTILS_HEADER
|
||||||
../include/matador/utils/enum_mapper.hpp
|
../include/matador/utils/enum_mapper.hpp
|
||||||
../include/matador/utils/types.hpp
|
../include/matador/utils/types.hpp
|
||||||
../include/matador/utils/foreign_attributes.hpp
|
../include/matador/utils/foreign_attributes.hpp
|
||||||
../include/matador/utils/fetch_type.hpp)
|
../include/matador/utils/fetch_type.hpp
|
||||||
|
)
|
||||||
|
|
||||||
set(UTILS_SOURCES
|
set(UTILS_SOURCES
|
||||||
utils/field_attributes.cpp
|
utils/field_attributes.cpp
|
||||||
|
|
@ -95,8 +128,14 @@ set(UTILS_SOURCES
|
||||||
utils/identifier.cpp
|
utils/identifier.cpp
|
||||||
sql/value_extractor.cpp
|
sql/value_extractor.cpp
|
||||||
utils/logger.cpp
|
utils/logger.cpp
|
||||||
utils/foreign_attributes.cpp)
|
utils/foreign_attributes.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(matador STATIC
|
||||||
|
${SQL_SOURCES} ${SQL_HEADER}
|
||||||
|
# ${QUERY_SOURCES} ${QUERY_HEADER}
|
||||||
|
${UTILS_SOURCES} ${UTILS_HEADER}
|
||||||
|
)
|
||||||
|
|
||||||
add_library(matador STATIC ${SQL_SOURCES} ${SQL_HEADER} ${UTILS_SOURCES} ${UTILS_HEADER})
|
|
||||||
target_include_directories(matador PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
target_include_directories(matador PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||||
#set_target_properties(matador PROPERTIES LINKER_LANGUAGE CXX)
|
#set_target_properties(matador PROPERTIES LINKER_LANGUAGE CXX)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
#include "matador/query/column.hpp"
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
column::column(const char *name)
|
||||||
|
: name(name) {}
|
||||||
|
|
||||||
|
column::column(std::string name)
|
||||||
|
: name(std::move(name)) {}
|
||||||
|
|
||||||
|
column::column(std::string table_name, std::string name, std::string as)
|
||||||
|
: table(std::move(table_name))
|
||||||
|
, name(std::move(name))
|
||||||
|
, alias(std::move(as)) {}
|
||||||
|
|
||||||
|
column& column::as(std::string a) {
|
||||||
|
alias = std::move(a);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include "matador/query/query.hpp"
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "matador/query/query_builder.hpp"
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
query_builder::query_builder(const std::shared_ptr<sql::schema> &scm)
|
||||||
|
: schema_(scm) {}
|
||||||
|
|
||||||
|
query_select_intermediate query_builder::select(std::initializer_list<column> columns)
|
||||||
|
{
|
||||||
|
return query_select_intermediate{schema_};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include "matador/query/query_compiler.hpp"
|
||||||
|
#include "matador/query/query_data.hpp"
|
||||||
|
#include "matador/query/column.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/dialect.hpp"
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
query_compiler::query_compiler(sql::dialect &d)
|
||||||
|
: dialect_(d)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string query_compiler::compile(const query_data *data)
|
||||||
|
{
|
||||||
|
sql_.clear();
|
||||||
|
for (const auto &part : data->parts) {
|
||||||
|
part->accept(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sql_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_select_part &select_part)
|
||||||
|
{
|
||||||
|
auto ci = "name"_col.as("c01");
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_from_part &from_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "matador/query/query_intermediates.hpp"
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
query_intermediate::query_intermediate(const std::shared_ptr<sql::schema> &scm)
|
||||||
|
: schema_(scm) {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include "matador/query/query_parts.hpp"
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
|
||||||
|
query_part::query_part(sql::dialect::token_t token)
|
||||||
|
: token_(token) {}
|
||||||
|
|
||||||
|
query_select_part::query_select_part(std::vector<column> columns)
|
||||||
|
: query_part(sql::dialect::token_t::SELECT)
|
||||||
|
, columns_(std::move(columns)) {}
|
||||||
|
|
||||||
|
void query_select_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_from_part::query_from_part(std::string table_name)
|
||||||
|
: query_part(sql::dialect::token_t::FROM)
|
||||||
|
, table_(std::move(table_name)) {}
|
||||||
|
|
||||||
|
query_from_part::query_from_part(std::string table_name, std::string as)
|
||||||
|
: query_part(sql::dialect::token_t::FROM)
|
||||||
|
, table_(std::move(table_name))
|
||||||
|
, alias_(std::move(as)) {}
|
||||||
|
|
||||||
|
void query_from_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,129 +1,10 @@
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column.hpp"
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
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, null_option null_opt, size_t index)
|
|
||||||
: name_(std::move(name)), index_(index), type_(type), attributes_(attr), null_option_(null_opt)
|
|
||||||
{}
|
|
||||||
|
|
||||||
column::column(std::string name, data_type_t type, size_t index, std::string ref_table, std::string ref_column,
|
|
||||||
utils::field_attributes attr, null_option null_opt)
|
|
||||||
: name_(std::move(name))
|
|
||||||
, index_(index)
|
|
||||||
, type_(type)
|
|
||||||
, attributes_(attr)
|
|
||||||
, null_option_(null_opt)
|
|
||||||
, ref_table_(std::move(ref_table))
|
|
||||||
, ref_column_(std::move(ref_column))
|
|
||||||
{}
|
|
||||||
|
|
||||||
const std::string &column::name() const
|
|
||||||
{
|
|
||||||
return name_;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t column::index() const
|
|
||||||
{
|
|
||||||
return index_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const utils::field_attributes &column::attributes() const
|
|
||||||
{
|
|
||||||
return attributes_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool column::is_nullable() const
|
|
||||||
{
|
|
||||||
return null_option_ == null_option::NULLABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &column::ref_column() const
|
|
||||||
{
|
|
||||||
return ref_column_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void column::type(data_type_t type)
|
|
||||||
{
|
|
||||||
type_ = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void column::alias(const std::string &as)
|
|
||||||
{
|
|
||||||
alias_ = as;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string column::str() const
|
|
||||||
{
|
|
||||||
any_type_to_visitor<std::string> visitor;
|
|
||||||
std::visit(visitor, const_cast<any_type &>(value_));
|
|
||||||
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)
|
column operator ""_col(const char *name, size_t len)
|
||||||
{
|
{
|
||||||
return {std::string(name, len)};
|
return {{name, len}};
|
||||||
}
|
}
|
||||||
|
|
||||||
column make_column(const std::string &name, data_type_t type, utils::field_attributes attr, null_option null_opt)
|
|
||||||
{
|
|
||||||
return {name, type, attr, null_opt};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
column make_column<std::string>(const std::string &name, utils::field_attributes attr, null_option null_opt)
|
|
||||||
{
|
|
||||||
return make_column(name, data_type_traits<std::string>::builtin_type(attr.size()), attr, null_opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
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<>
|
|
||||||
[[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), 0, ref_table, ref_column, {size, utils::constraints::FOREIGN_KEY}, null_option::NOT_NULL};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
#include "matador/sql/column_definition.hpp"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
column_definition::column_definition(const char *name)
|
||||||
|
: name_(name), attributes_(utils::null_attributes)
|
||||||
|
{}
|
||||||
|
|
||||||
|
column_definition::column_definition(std::string name)
|
||||||
|
: name_(std::move(name)), attributes_(utils::null_attributes)
|
||||||
|
{}
|
||||||
|
|
||||||
|
column_definition::column_definition(std::string name, data_type_t type, utils::field_attributes attr, null_option null_opt, size_t index)
|
||||||
|
: name_(std::move(name)), index_(index), type_(type), attributes_(attr), null_option_(null_opt)
|
||||||
|
{}
|
||||||
|
|
||||||
|
column_definition::column_definition(std::string name, data_type_t type, size_t index, std::string ref_table, std::string ref_column,
|
||||||
|
utils::field_attributes attr, null_option null_opt)
|
||||||
|
: name_(std::move(name))
|
||||||
|
, index_(index)
|
||||||
|
, type_(type)
|
||||||
|
, attributes_(attr)
|
||||||
|
, null_option_(null_opt)
|
||||||
|
, ref_table_(std::move(ref_table))
|
||||||
|
, ref_column_(std::move(ref_column))
|
||||||
|
{}
|
||||||
|
|
||||||
|
const std::string &column_definition::name() const
|
||||||
|
{
|
||||||
|
return name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t column_definition::index() const
|
||||||
|
{
|
||||||
|
return index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const utils::field_attributes &column_definition::attributes() const
|
||||||
|
{
|
||||||
|
return attributes_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool column_definition::is_nullable() const
|
||||||
|
{
|
||||||
|
return null_option_ == null_option::NULLABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_type_t column_definition::type() const
|
||||||
|
{
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &column_definition::ref_table() const
|
||||||
|
{
|
||||||
|
return ref_table_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &column_definition::ref_column() const
|
||||||
|
{
|
||||||
|
return ref_column_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void column_definition::type(data_type_t type)
|
||||||
|
{
|
||||||
|
type_ = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string column_definition::str() const
|
||||||
|
{
|
||||||
|
any_type_to_visitor<std::string> visitor;
|
||||||
|
std::visit(visitor, const_cast<any_type &>(value_));
|
||||||
|
return visitor.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
column_definition make_column(const std::string &name, data_type_t type, utils::field_attributes attr, null_option null_opt)
|
||||||
|
{
|
||||||
|
return {name, type, attr, null_opt};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
column_definition make_column<std::string>(const std::string &name, utils::field_attributes attr, null_option null_opt)
|
||||||
|
{
|
||||||
|
return make_column(name, data_type_traits<std::string>::builtin_type(attr.size()), attr, null_opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
column_definition make_pk_column<std::string>(const std::string &name, size_t size)
|
||||||
|
{
|
||||||
|
return make_column<std::string>(name, {size, utils::constraints::FOREIGN_KEY});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
[[maybe_unused]] column_definition make_fk_column<std::string>(const std::string &name, size_t size, const std::string &ref_table,
|
||||||
|
const std::string &ref_column)
|
||||||
|
{
|
||||||
|
return {name, data_type_traits<std::string>::builtin_type(size), 0, ref_table, ref_column, {size, utils::constraints::FOREIGN_KEY}, null_option::NOT_NULL};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
column_generator::column_generator(std::vector<column> &columns, const schema &repo)
|
column_generator::column_generator(std::vector<column_definition> &columns, const schema &repo)
|
||||||
: columns_(columns)
|
: columns_(columns)
|
||||||
, repo_(repo)
|
, repo_(repo)
|
||||||
{}
|
{}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
column_name_generator::column_name_generator(std::vector<column_info> &column_infos,
|
column_name_generator::column_name_generator(std::vector<column> &column_infos,
|
||||||
const sql::schema &ts,
|
const sql::schema &ts,
|
||||||
const std::string &table_name)
|
const std::string &table_name)
|
||||||
: column_infos_(column_infos)
|
: column_infos_(column_infos)
|
||||||
|
|
@ -25,7 +25,7 @@ void column_name_generator::push(const std::string &column_name)
|
||||||
{
|
{
|
||||||
char str[4];
|
char str[4];
|
||||||
snprintf(str, 4, "c%02d", ++column_index);
|
snprintf(str, 4, "c%02d", ++column_index);
|
||||||
column_infos_.emplace_back(column_info{table_name_stack_.top(), column_name, str});
|
column_infos_.emplace_back(table_name_stack_.top(), column_name, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -8,8 +8,8 @@ condition<column, placeholder, std::enable_if<true>::type>::condition(const colu
|
||||||
|
|
||||||
std::string condition<column, placeholder, std::enable_if<true>::type>::evaluate(dialect &d, query_context &query) const
|
std::string condition<column, placeholder, std::enable_if<true>::type>::evaluate(dialect &d, query_context &query) const
|
||||||
{
|
{
|
||||||
query.bind_vars.emplace_back(field_.name());
|
query.bind_vars.emplace_back(field_.name);
|
||||||
return d.prepare_identifier(field_.name()) + " " + operand + " " + d.next_placeholder(query.bind_vars);
|
return d.prepare_identifier(field_.name) + " " + operand + " " + d.next_placeholder(query.bind_vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
condition<column, query_context>::condition(column col, basic_condition::operand_t op, query_context &q)
|
condition<column, query_context>::condition(column col, basic_condition::operand_t op, query_context &q)
|
||||||
|
|
@ -18,9 +18,13 @@ condition<column, query_context>::condition(column col, basic_condition::operand
|
||||||
|
|
||||||
std::string condition<column, query_context>::evaluate(dialect &d, query_context &query) const
|
std::string condition<column, query_context>::evaluate(dialect &d, query_context &query) const
|
||||||
{
|
{
|
||||||
std::string result(d.prepare_identifier(field_.name()) + " " + operand + " (");
|
std::string result(d.prepare_identifier(field_.name) + " " + operand + " (");
|
||||||
result += (")");
|
result += (")");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
condition<column, column> operator==(const column &a, const column &b)
|
||||||
|
{
|
||||||
|
return {a, basic_condition::operand_t::EQUAL, b};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
connection::connection(connection_info info, const std::shared_ptr<schema> &repo)
|
connection::connection(connection_info info, const std::shared_ptr<sql::schema> &repo)
|
||||||
: connection_info_(std::move(info))
|
: connection_info_(std::move(info))
|
||||||
, logger_(stdout, "SQL")
|
, logger_(stdout, "SQL")
|
||||||
, dialect_(backend_provider::instance().connection_dialect(connection_info_.type))
|
, dialect_(backend_provider::instance().connection_dialect(connection_info_.type))
|
||||||
|
|
@ -17,7 +17,7 @@ connection::connection(connection_info info, const std::shared_ptr<schema> &repo
|
||||||
connection_.reset(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, const std::shared_ptr<schema> &repo)
|
connection::connection(const std::string& dns, const std::shared_ptr<sql::schema> &repo)
|
||||||
: connection(connection_info::parse(dns), repo)
|
: connection(connection_info::parse(dns), repo)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
@ -69,36 +69,6 @@ const connection_info &connection::info() const
|
||||||
return connection_info_;
|
return connection_info_;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_create_intermediate connection::create()
|
|
||||||
{
|
|
||||||
return query_create_intermediate(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
query_drop_intermediate connection::drop()
|
|
||||||
{
|
|
||||||
return query_drop_intermediate{*this};
|
|
||||||
}
|
|
||||||
|
|
||||||
query_select_intermediate connection::select(std::initializer_list<column> columns)
|
|
||||||
{
|
|
||||||
return {*this, columns};
|
|
||||||
}
|
|
||||||
|
|
||||||
query_insert_intermediate connection::insert()
|
|
||||||
{
|
|
||||||
return query_insert_intermediate{*this};
|
|
||||||
}
|
|
||||||
|
|
||||||
query_update_intermediate connection::update(const std::string &table)
|
|
||||||
{
|
|
||||||
return query_update_intermediate{*this, table};
|
|
||||||
}
|
|
||||||
|
|
||||||
query_delete_intermediate connection::remove()
|
|
||||||
{
|
|
||||||
return query_delete_intermediate{*this};
|
|
||||||
}
|
|
||||||
|
|
||||||
record connection::describe(const std::string &table_name) const
|
record connection::describe(const std::string &table_name) const
|
||||||
{
|
{
|
||||||
return std::move(connection_->describe(table_name));
|
return std::move(connection_->describe(table_name));
|
||||||
|
|
@ -120,13 +90,18 @@ size_t connection::execute(const std::string &sql) const
|
||||||
return connection_->execute(sql);
|
return connection_->execute(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sql::query connection::query() const
|
||||||
|
{
|
||||||
|
return sql::query(*const_cast<connection*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
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&>(col).type(rit->type());
|
const_cast<column_definition&>(col).type(rit->type());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +135,7 @@ const class dialect &connection::dialect() const
|
||||||
return dialect_;
|
return dialect_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<schema> connection::tables() const
|
std::shared_ptr<schema> connection::schema() const
|
||||||
{
|
{
|
||||||
return schema_;
|
return schema_;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "matador/sql/dialect.hpp"
|
#include "matador/sql/dialect.hpp"
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column_definition.hpp"
|
||||||
|
|
||||||
#include "matador/utils/string.hpp"
|
#include "matador/utils/string.hpp"
|
||||||
|
|
||||||
|
|
@ -19,12 +19,12 @@ std::string dialect::prepare_identifier(const column &col) const
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
if (!col.is_function()) {
|
if (!col.is_function()) {
|
||||||
result = prepare_identifier_string(col.name());
|
result = prepare_identifier_string(col.name);
|
||||||
} else {
|
} else {
|
||||||
result = sql_func_map_.at(col.function()) + "(" + col.name() + ")";
|
result = sql_func_map_.at(col.function_) + "(" + col.name + ")";
|
||||||
}
|
}
|
||||||
if (!col.alias().empty()) {
|
if (!col.alias.empty()) {
|
||||||
result += " AS " + col.alias();
|
result += " AS " + col.alias;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include "matador/sql/query.hpp"
|
||||||
|
#include "matador/sql/connection.hpp"
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
query::query(connection &c)
|
||||||
|
: connection_(c)
|
||||||
|
{}
|
||||||
|
|
||||||
|
query_create_intermediate query::create()
|
||||||
|
{
|
||||||
|
return query_create_intermediate(connection_);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_drop_intermediate query::drop()
|
||||||
|
{
|
||||||
|
return query_drop_intermediate{connection_};
|
||||||
|
}
|
||||||
|
|
||||||
|
query_select_intermediate query::select(std::initializer_list<column> columns)
|
||||||
|
{
|
||||||
|
return {connection_, columns};
|
||||||
|
}
|
||||||
|
|
||||||
|
query_insert_intermediate query::insert()
|
||||||
|
{
|
||||||
|
return query_insert_intermediate{connection_};
|
||||||
|
}
|
||||||
|
|
||||||
|
query_update_intermediate query::update(const std::string &table)
|
||||||
|
{
|
||||||
|
return query_update_intermediate{connection_, table};
|
||||||
|
}
|
||||||
|
|
||||||
|
query_delete_intermediate query::remove()
|
||||||
|
{
|
||||||
|
return query_delete_intermediate{connection_};
|
||||||
|
}
|
||||||
|
|
||||||
|
const sql::schema& query::schema() const
|
||||||
|
{
|
||||||
|
return *connection_.schema();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "matador/sql/query_builder.hpp"
|
#include "matador/sql/query_builder.hpp"
|
||||||
#include "matador/sql/column_name_generator.hpp"
|
#include "matador/sql/column_name_generator.hpp"
|
||||||
|
#include "matador/sql/column.hpp"
|
||||||
#include "matador/sql/dialect.hpp"
|
#include "matador/sql/dialect.hpp"
|
||||||
|
|
||||||
#include "matador/utils/string.hpp"
|
#include "matador/utils/string.hpp"
|
||||||
|
|
@ -139,19 +140,19 @@ query_builder &query_builder::select(const std::vector<column> &columns)
|
||||||
if (columns.size() < 2) {
|
if (columns.size() < 2) {
|
||||||
for (const auto &col: columns) {
|
for (const auto &col: columns) {
|
||||||
result.append(dialect_.prepare_identifier(col));
|
result.append(dialect_.prepare_identifier(col));
|
||||||
query_.result_vars.emplace_back(col.name());
|
query_.result_vars.emplace_back(col.name);
|
||||||
query_.prototype.append(col);
|
query_.prototype.append(column_definition{col.name});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
auto it = columns.begin();
|
auto it = columns.begin();
|
||||||
result.append(dialect_.prepare_identifier(*it));
|
result.append(dialect_.prepare_identifier(*it));
|
||||||
query_.result_vars.emplace_back(it->name());
|
query_.result_vars.emplace_back(it->name);
|
||||||
query_.prototype.append(column{*it++});
|
query_.prototype.append(column_definition{(*it++).name});
|
||||||
for (; it != columns.end(); ++it) {
|
for (; it != columns.end(); ++it) {
|
||||||
result.append(", ");
|
result.append(", ");
|
||||||
result.append(dialect_.prepare_identifier(*it));
|
result.append(dialect_.prepare_identifier(*it));
|
||||||
query_.result_vars.emplace_back(it->name());
|
query_.result_vars.emplace_back(it->name);
|
||||||
query_.prototype.append(column{*it});
|
query_.prototype.append(column_definition{(*it).name});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,9 +188,9 @@ query_builder &query_builder::remove()
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_builder &query_builder::table(const std::string &table, std::initializer_list<column> columns)
|
query_builder &query_builder::table(const std::string &table, std::initializer_list<column_definition> columns)
|
||||||
{
|
{
|
||||||
return this->table(table, std::vector<column>{columns});
|
return this->table(table, std::vector<column_definition>{columns});
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fk_context
|
struct fk_context
|
||||||
|
|
@ -205,9 +206,9 @@ struct column_context
|
||||||
std::vector<fk_context> foreign_contexts;
|
std::vector<fk_context> foreign_contexts;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string build_create_column(const column &col, const dialect &d, column_context &context);
|
std::string build_create_column(const column_definition &col, const dialect &d, column_context &context);
|
||||||
|
|
||||||
query_builder &query_builder::table(const std::string &table, const std::vector<column> &columns)
|
query_builder &query_builder::table(const std::string &table, const std::vector<column_definition> &columns)
|
||||||
{
|
{
|
||||||
transition_to(state_t::QUERY_TABLE_CREATE);
|
transition_to(state_t::QUERY_TABLE_CREATE);
|
||||||
|
|
||||||
|
|
@ -256,12 +257,12 @@ query_builder &query_builder::table(const std::string &table)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_builder &query_builder::into(const std::string &table, std::initializer_list<column_info> column_names)
|
query_builder &query_builder::into(const std::string &table, std::initializer_list<column> column_names)
|
||||||
{
|
{
|
||||||
return into(table, std::vector<column_info>{column_names});
|
return into(table, std::vector<column>{column_names});
|
||||||
}
|
}
|
||||||
|
|
||||||
query_builder &query_builder::into(const std::string &table, const std::vector<column_info> &column_names)
|
query_builder &query_builder::into(const std::string &table, const std::vector<column> &column_names)
|
||||||
{
|
{
|
||||||
transition_to(state_t::QUERY_INTO);
|
transition_to(state_t::QUERY_INTO);
|
||||||
|
|
||||||
|
|
@ -490,7 +491,7 @@ void query_builder::initialize(query_builder::command_t cmd, query_builder::stat
|
||||||
query_parts_.clear();
|
query_parts_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string build_create_column(const column &col, const dialect &d, column_context &context)
|
std::string build_create_column(const column_definition &col, const dialect &d, column_context &context)
|
||||||
{
|
{
|
||||||
std::string result = d.prepare_identifier(col.name()) + " " + d.data_type_at(col.type());
|
std::string result = d.prepare_identifier(col.name()) + " " + d.data_type_at(col.type());
|
||||||
if (col.attributes().size() > 0) {
|
if (col.attributes().size() > 0) {
|
||||||
|
|
@ -514,12 +515,12 @@ std::string build_create_column(const column &col, const dialect &d, column_cont
|
||||||
|
|
||||||
column alias(const std::string &column, const std::string &as)
|
column alias(const std::string &column, const std::string &as)
|
||||||
{
|
{
|
||||||
return {column, as};
|
return {"", column, as};
|
||||||
}
|
}
|
||||||
|
|
||||||
column alias(column &&col, const std::string &as)
|
column alias(column &&col, const std::string &as)
|
||||||
{
|
{
|
||||||
col.alias(as);
|
col.as(as);
|
||||||
return std::move(col);
|
return std::move(col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
#include "matador/sql/query_compiler.hpp"
|
||||||
|
#include "matador/sql/query_data.hpp"
|
||||||
|
#include "matador/sql/column_definition.hpp"
|
||||||
|
#include "matador/sql/dialect.hpp"
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
query_compiler::query_compiler(const sql::dialect &d)
|
||||||
|
: dialect_(d)
|
||||||
|
{}
|
||||||
|
|
||||||
|
query_context query_compiler::compile(const query_data *data)
|
||||||
|
{
|
||||||
|
for (const auto &part : data->parts) {
|
||||||
|
part->accept(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_select_part &select_part)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
const auto &columns = select_part.columns();
|
||||||
|
if (columns.size() < 2) {
|
||||||
|
for (const auto &col: columns) {
|
||||||
|
result.append(dialect_.prepare_identifier(col));
|
||||||
|
query_.result_vars.emplace_back(col.name);
|
||||||
|
query_.prototype.append(column_definition{col.name});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto it = columns.begin();
|
||||||
|
result.append(dialect_.prepare_identifier(*it));
|
||||||
|
query_.result_vars.emplace_back(it->name);
|
||||||
|
query_.prototype.append(column_definition{(*it++).name});
|
||||||
|
for (; it != columns.end(); ++it) {
|
||||||
|
result.append(", ");
|
||||||
|
result.append(dialect_.prepare_identifier(*it));
|
||||||
|
query_.result_vars.emplace_back(it->name);
|
||||||
|
query_.prototype.append(column_definition{(*it).name});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_from_part &from_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_where_part &where_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_group_by_part &group_by_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_order_by_part &order_by_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_order_by_asc_part &order_by_asc_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_order_by_desc_part &order_by_desc_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_insert_part &insert_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_values_part &values_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_update_part &update_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_delete_part &delete_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_create_part &create_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_drop_part &drop_part)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "matador/sql/query_intermediates.hpp"
|
#include "matador/sql/query_intermediates.hpp"
|
||||||
#include "matador/sql/session.hpp"
|
#include "matador/sql/session.hpp"
|
||||||
|
#include "matador/sql/query_compiler.hpp"
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
basic_query_intermediate::basic_query_intermediate(connection &db)
|
basic_query_intermediate::basic_query_intermediate(connection &db)
|
||||||
|
|
@ -7,219 +8,252 @@ basic_query_intermediate::basic_query_intermediate(connection &db)
|
||||||
|
|
||||||
std::shared_ptr<schema> basic_query_intermediate::tables() const
|
std::shared_ptr<schema> basic_query_intermediate::tables() const
|
||||||
{
|
{
|
||||||
return connection_.tables();
|
return connection_.schema();
|
||||||
}
|
}
|
||||||
|
|
||||||
query_result<record> query_select_finish::fetch_all()
|
query_result<record> query_select_finish::fetch_all()
|
||||||
{
|
{
|
||||||
return connection_.fetch(builder_.compile());
|
query_compiler compiler(connection_.dialect());
|
||||||
|
return connection_.fetch(compiler.compile(&data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
record query_select_finish::fetch_one()
|
record query_select_finish::fetch_one()
|
||||||
{
|
{
|
||||||
return *connection_.fetch(builder_.compile()).begin().get();
|
query_compiler compiler(connection_.dialect());
|
||||||
|
return *connection_.fetch(compiler.compile(&data_)).begin().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<query_result_impl> query_select_finish::fetch()
|
std::unique_ptr<query_result_impl> query_select_finish::fetch()
|
||||||
{
|
{
|
||||||
return connection_.fetch(builder_.compile().sql);
|
query_compiler compiler(connection_.dialect());
|
||||||
|
return connection_.fetch(compiler.compile(&data_).sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
statement query_select_finish::prepare()
|
statement query_select_finish::prepare()
|
||||||
{
|
{
|
||||||
return connection_.prepare(builder_.compile());
|
query_compiler compiler(connection_.dialect());
|
||||||
|
return connection_.prepare(compiler.compile(&data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
query_intermediate::query_intermediate(connection &db, query_builder &query)
|
query_intermediate::query_intermediate(connection &db, query_data &data)
|
||||||
: basic_query_intermediate(db), builder_(query) {}
|
: basic_query_intermediate(db), data_(data) {}
|
||||||
|
|
||||||
query_offset_intermediate query_order_direction_intermediate::offset(size_t offset)
|
query_offset_intermediate query_order_direction_intermediate::offset(size_t offset)
|
||||||
{
|
{
|
||||||
return {connection_, builder_};
|
return {connection_, data_};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_limit_intermediate query_offset_intermediate::limit(size_t limit)
|
query_limit_intermediate query_offset_intermediate::limit(size_t limit)
|
||||||
{
|
{
|
||||||
return {connection_, builder_};
|
return {connection_, data_};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_limit_intermediate query_order_direction_intermediate::limit(size_t limit)
|
query_limit_intermediate query_order_direction_intermediate::limit(size_t limit)
|
||||||
{
|
{
|
||||||
return {connection_, builder_};
|
return {connection_, data_};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_order_by_intermediate query_group_by_intermediate::order_by(const std::string &name)
|
query_order_by_intermediate query_group_by_intermediate::order_by(const std::string &name)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.order_by(name)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.order_by(name)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_order_direction_intermediate query_order_by_intermediate::asc()
|
query_order_direction_intermediate query_order_by_intermediate::asc()
|
||||||
{
|
{
|
||||||
return {connection_, builder_.asc()};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.asc()};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_order_direction_intermediate query_order_by_intermediate::desc()
|
query_order_direction_intermediate query_order_by_intermediate::desc()
|
||||||
{
|
{
|
||||||
return {connection_, builder_.desc()};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.desc()};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_group_by_intermediate query_from_intermediate::group_by(const std::string &name)
|
query_group_by_intermediate query_from_intermediate::group_by(const std::string &name)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.group_by(name)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.group_by(name)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_order_by_intermediate query_from_intermediate::order_by(const std::string &name)
|
query_order_by_intermediate query_from_intermediate::order_by(const std::string &name)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.order_by(name)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.order_by(name)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_group_by_intermediate query_where_intermediate::group_by(const std::string &name)
|
query_group_by_intermediate query_where_intermediate::group_by(const std::string &name)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.group_by(name)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.group_by(name)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_order_by_intermediate query_where_intermediate::order_by(const std::string &name)
|
query_order_by_intermediate query_where_intermediate::order_by(const std::string &name)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.order_by(name)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.order_by(name)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_join_intermediate query_on_intermediate::join(const std::string &join_table_name, const std::string &as)
|
query_join_intermediate query_on_intermediate::join(const std::string &join_table_name, const std::string &as)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.join(join_table_name, join_type_t::INNER, as)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.join(join_table_name, join_type_t::INNER, as)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_where_intermediate query_on_intermediate::where(const basic_condition &cond)
|
query_where_intermediate query_on_intermediate::where(const basic_condition &cond)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.where(cond)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.where(cond)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_group_by_intermediate query_on_intermediate::group_by(const std::string &name)
|
query_group_by_intermediate query_on_intermediate::group_by(const std::string &name)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.group_by(name)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.group_by(name)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_order_by_intermediate query_on_intermediate::order_by(const std::string &name)
|
query_order_by_intermediate query_on_intermediate::order_by(const std::string &name)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.order_by(name)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.order_by(name)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_on_intermediate query_join_intermediate::on(const std::string &column, const std::string &join_column)
|
query_on_intermediate query_join_intermediate::on(const basic_condition &cond)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.on(column, join_column)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.on(column, join_column)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_join_intermediate query_from_intermediate::join(const std::string &join_table_name, const std::string &as)
|
query_join_intermediate query_from_intermediate::join_left(const std::string &join_table_name, const std::string &as)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.join(join_table_name, join_type_t::INNER, as)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.join(join_table_name, join_type_t::INNER, as)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_where_intermediate query_from_intermediate::where(const basic_condition &cond)
|
query_where_intermediate query_from_intermediate::where(const basic_condition &cond)
|
||||||
{
|
{
|
||||||
return query_where_intermediate{connection_, builder_.where(cond)};
|
return query_where_intermediate{connection_, data_};
|
||||||
|
// return query_where_intermediate{connection_, builder_.where(cond)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_select_intermediate::query_select_intermediate(connection &s, const std::vector<column>& columns)
|
query_select_intermediate::query_select_intermediate(connection &db, const std::vector<column>& columns)
|
||||||
: query_start_intermediate(s)
|
: query_start_intermediate(db)
|
||||||
{
|
{
|
||||||
builder_.select(columns);
|
data_.parts.push_back(std::make_unique<query_select_part>(columns));
|
||||||
}
|
}
|
||||||
|
|
||||||
query_from_intermediate query_select_intermediate::from(const std::string &table, const std::string &as)
|
query_from_intermediate query_select_intermediate::from(const std::string &table, const std::string &as)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.from(table, as)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.from(table, as)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_insert_intermediate::query_insert_intermediate(connection &s)
|
query_insert_intermediate::query_insert_intermediate(connection &s)
|
||||||
: query_start_intermediate(s)
|
: query_start_intermediate(s)
|
||||||
{
|
{
|
||||||
builder_.insert();
|
data_.parts.push_back(std::make_unique<query_insert_part>());
|
||||||
}
|
}
|
||||||
|
|
||||||
query_into_intermediate query_insert_intermediate::into(const std::string &table, std::initializer_list<column_info> column_names)
|
query_into_intermediate query_insert_intermediate::into(const std::string &table, std::initializer_list<column> column_names)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.into(table, column_names)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.into(table, column_names)};
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t query_execute_finish::execute()
|
size_t query_execute_finish::execute()
|
||||||
{
|
{
|
||||||
return connection_.execute(builder_.compile().sql);
|
query_compiler compiler(connection_.dialect());
|
||||||
|
return connection_.execute(compiler.compile(&data_).sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
statement query_execute_finish::prepare()
|
statement query_execute_finish::prepare()
|
||||||
{
|
{
|
||||||
return connection_.prepare(builder_.compile());
|
query_compiler compiler(connection_.dialect());
|
||||||
|
return connection_.prepare(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)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.values(values)};
|
return this->values(std::vector<any_type>(values));
|
||||||
|
}
|
||||||
|
|
||||||
|
query_execute_finish query_into_intermediate::values(const std::vector<any_type> &values)
|
||||||
|
{
|
||||||
|
return {connection_, data_};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_create_intermediate::query_create_intermediate(connection &db)
|
query_create_intermediate::query_create_intermediate(connection &db)
|
||||||
: query_start_intermediate(db) {
|
: query_start_intermediate(db) {
|
||||||
builder_.create();
|
data_.parts.push_back(std::make_unique<query_create_part>());
|
||||||
}
|
}
|
||||||
|
|
||||||
query_execute_finish query_create_intermediate::table(const std::string &table_name, std::initializer_list<column> columns)
|
query_execute_finish query_create_intermediate::table(const std::string &table_name, std::initializer_list<column_definition> columns)
|
||||||
{
|
{
|
||||||
return table(table_name, std::vector<column>{columns});
|
return table(table_name, std::vector<column_definition>{columns});
|
||||||
}
|
}
|
||||||
|
|
||||||
query_execute_finish query_create_intermediate::table(const std::string &table_name, const std::vector<column> &columns)
|
query_execute_finish query_create_intermediate::table(const std::string &table_name, const std::vector<column_definition> &columns)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.table(table_name, columns)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.table(table_name, columns)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_drop_intermediate::query_drop_intermediate(connection &s)
|
query_drop_intermediate::query_drop_intermediate(connection &s)
|
||||||
: query_start_intermediate(s)
|
: query_start_intermediate(s)
|
||||||
{
|
{
|
||||||
builder_.drop();
|
data_.parts.push_back(std::make_unique<query_drop_part>());
|
||||||
}
|
}
|
||||||
|
|
||||||
query_execute_finish query_drop_intermediate::table(const std::string &table)
|
query_execute_finish query_drop_intermediate::table(const std::string &table)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.table(table)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.table(table)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_execute_finish query_execute_where_intermediate::limit(int limit)
|
query_execute_finish query_execute_where_intermediate::limit(int limit)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.limit(limit)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.limit(limit)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_execute_where_intermediate query_set_intermediate::where(const basic_condition &cond)
|
query_execute_where_intermediate query_set_intermediate::where(const basic_condition &cond)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.where(cond)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.where(cond)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_update_intermediate::query_update_intermediate(connection &s, const std::string& table_name)
|
query_update_intermediate::query_update_intermediate(connection &s, const std::string& table_name)
|
||||||
: query_start_intermediate(s)
|
: query_start_intermediate(s)
|
||||||
{
|
{
|
||||||
builder_.update(table_name);
|
data_.parts.push_back(std::make_unique<query_update_part>(table_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
query_set_intermediate query_update_intermediate::set(std::initializer_list<key_value_pair> columns)
|
query_set_intermediate query_update_intermediate::set(std::initializer_list<key_value_pair> columns)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.set(columns)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.set(columns)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_execute_where_intermediate query_delete_from_intermediate::where(const basic_condition &cond)
|
query_execute_where_intermediate query_delete_from_intermediate::where(const basic_condition &cond)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.where(cond)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.where(cond)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_delete_intermediate::query_delete_intermediate(connection &s)
|
query_delete_intermediate::query_delete_intermediate(connection &s)
|
||||||
: query_start_intermediate(s)
|
: query_start_intermediate(s)
|
||||||
{
|
{
|
||||||
builder_.remove();
|
data_.parts.push_back(std::make_unique<query_delete_part>());
|
||||||
}
|
}
|
||||||
|
|
||||||
query_delete_from_intermediate query_delete_intermediate::from(const std::string &table)
|
query_delete_from_intermediate query_delete_intermediate::from(const std::string &table)
|
||||||
{
|
{
|
||||||
return {connection_, builder_.from(table)};
|
return {connection_, data_};
|
||||||
|
// return {connection_, builder_.from(table)};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_start_intermediate::query_start_intermediate(connection &s)
|
query_start_intermediate::query_start_intermediate(connection &db)
|
||||||
: basic_query_intermediate(s)
|
: basic_query_intermediate(db)
|
||||||
, builder_(s.dialect())
|
|
||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
#include "matador/sql/query_parts.hpp"
|
||||||
|
#include "matador/sql/basic_condition.hpp"
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
query_part::query_part(sql::dialect::token_t token)
|
||||||
|
: token_(token) {}
|
||||||
|
|
||||||
|
query_select_part::query_select_part(std::vector<column> columns)
|
||||||
|
: query_part(sql::dialect::token_t::SELECT)
|
||||||
|
, columns_(std::move(columns)) {}
|
||||||
|
|
||||||
|
void query_select_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<column>& query_select_part::columns() const
|
||||||
|
{
|
||||||
|
return columns_;
|
||||||
|
}
|
||||||
|
|
||||||
|
query_from_part::query_from_part(std::string table_name)
|
||||||
|
: query_part(sql::dialect::token_t::FROM)
|
||||||
|
, table_(std::move(table_name)) {}
|
||||||
|
|
||||||
|
query_from_part::query_from_part(std::string table_name, std::string as)
|
||||||
|
: query_part(sql::dialect::token_t::FROM)
|
||||||
|
, table_(std::move(table_name))
|
||||||
|
, alias_(std::move(as)) {}
|
||||||
|
|
||||||
|
void query_from_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_where_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_table_name_part::query_table_name_part(sql::dialect::token_t token, std::string table_name)
|
||||||
|
: query_part(token)
|
||||||
|
, table_name_(std::move(table_name)) {}
|
||||||
|
|
||||||
|
query_group_by_part::query_group_by_part(const std::string &table_name)
|
||||||
|
: query_table_name_part(dialect::token_t::GROUP_BY, table_name)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void query_group_by_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_order_by_part::query_order_by_part(const std::string &table_name)
|
||||||
|
: query_table_name_part(dialect::token_t::ORDER_BY, table_name)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void query_order_by_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_order_by_asc_part::query_order_by_asc_part()
|
||||||
|
: query_part(dialect::token_t::ASC)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void query_order_by_asc_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_order_by_desc_part::query_order_by_desc_part()
|
||||||
|
: query_part(dialect::token_t::DESC)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void query_order_by_desc_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_insert_part::query_insert_part()
|
||||||
|
: query_part(dialect::token_t::INSERT) {}
|
||||||
|
|
||||||
|
void query_insert_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_values_part::query_values_part(std::initializer_list<any_type> values)
|
||||||
|
: query_part(sql::dialect::token_t::VALUES)
|
||||||
|
, values_(values) {}
|
||||||
|
|
||||||
|
void query_values_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_update_part::query_update_part(const std::string &table_name)
|
||||||
|
: query_table_name_part(dialect::token_t::UPDATE, table_name) {}
|
||||||
|
|
||||||
|
void query_update_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_delete_part::query_delete_part()
|
||||||
|
: query_part(sql::dialect::token_t::REMOVE) {}
|
||||||
|
|
||||||
|
void query_delete_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_create_part::query_create_part()
|
||||||
|
: query_part(sql::dialect::token_t::CREATE) {}
|
||||||
|
|
||||||
|
void query_create_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_drop_part::query_drop_part()
|
||||||
|
: query_part(sql::dialect::token_t::DROP) {}
|
||||||
|
|
||||||
|
void query_drop_part::accept(query_part_visitor &visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -5,13 +5,13 @@
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
record::record(std::initializer_list<column> columns)
|
record::record(std::initializer_list<column_definition> columns)
|
||||||
: columns_(columns)
|
: columns_(columns)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
record::record(const std::vector<column> &columns)
|
record::record(const std::vector<column_definition> &columns)
|
||||||
: columns_(columns)
|
: columns_(columns)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
@ -41,7 +41,7 @@ record &record::operator=(const record &x)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<column> &record::columns() const
|
const std::vector<column_definition> &record::columns() const
|
||||||
{
|
{
|
||||||
return columns_;
|
return columns_;
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +51,7 @@ bool record::has_primary_key() const
|
||||||
return pk_index_ > -1;
|
return pk_index_ > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const column &record::primary_key() const
|
const column_definition &record::primary_key() const
|
||||||
{
|
{
|
||||||
if (!has_primary_key()) {
|
if (!has_primary_key()) {
|
||||||
throw std::logic_error("record has no primary key");
|
throw std::logic_error("record has no primary key");
|
||||||
|
|
@ -60,13 +60,13 @@ const column &record::primary_key() const
|
||||||
return columns_[pk_index_];
|
return columns_[pk_index_];
|
||||||
}
|
}
|
||||||
|
|
||||||
const column &record::at(const std::string &name) const
|
const column_definition &record::at(const std::string &name) const
|
||||||
{
|
{
|
||||||
auto ref = columns_by_name_.at(name).first;
|
auto ref = columns_by_name_.at(name).first;
|
||||||
return columns_by_name_.at(name).first;
|
return columns_by_name_.at(name).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
const column &record::at(size_t index) const
|
const column_definition &record::at(size_t index) const
|
||||||
{
|
{
|
||||||
return columns_.at(index);
|
return columns_.at(index);
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +82,7 @@ record::const_iterator record::find(const std::string &column_name) const {
|
||||||
return it != columns_by_name_.end() ? columns_.begin() + it->second.second : columns_.end();
|
return it != columns_by_name_.end() ? columns_.begin() + it->second.second : columns_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void record::append(column col)
|
void record::append(column_definition col)
|
||||||
{
|
{
|
||||||
auto &ref = columns_.emplace_back(std::move(col));
|
auto &ref = columns_.emplace_back(std::move(col));
|
||||||
add_to_map(ref, columns_.size()-1);
|
add_to_map(ref, columns_.size()-1);
|
||||||
|
|
@ -149,7 +149,7 @@ void record::init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void record::add_to_map(column &col, size_t index)
|
void record::add_to_map(column_definition &col, size_t index)
|
||||||
{
|
{
|
||||||
columns_by_name_.emplace(col.name(), column_index_pair {std::ref(col), index});
|
columns_by_name_.emplace(col.name(), column_index_pair {std::ref(col), index});
|
||||||
if (utils::is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) {
|
if (utils::is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) {
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,17 @@ namespace matador::sql {
|
||||||
|
|
||||||
void table_info::create(connection &conn) const
|
void table_info::create(connection &conn) const
|
||||||
{
|
{
|
||||||
conn.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) const
|
||||||
{
|
{
|
||||||
conn.drop().table(name).execute();
|
conn.query().drop().table(name).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string schema::name() const
|
||||||
|
{
|
||||||
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const table_info& schema::attach(const std::type_index ti, const table_info& table)
|
const table_info& schema::attach(const std::type_index ti, const table_info& table)
|
||||||
|
|
@ -71,4 +76,5 @@ bool schema::empty() const
|
||||||
{
|
{
|
||||||
return repository_.empty();
|
return repository_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -25,7 +25,7 @@ void session::drop_table(const std::string &table_name)
|
||||||
throw std::logic_error("no database connection available");
|
throw std::logic_error("no database connection available");
|
||||||
}
|
}
|
||||||
|
|
||||||
c->drop().table(table_name).execute();
|
c->query().drop().table(table_name).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
query_result<record> session::fetch(const query_context &q) const
|
query_result<record> session::fetch(const query_context &q) const
|
||||||
|
|
@ -41,7 +41,7 @@ query_result<record> session::fetch(const query_context &q) const
|
||||||
// adjust columns from given query
|
// adjust columns from given query
|
||||||
for (auto &col : q.prototype) {
|
for (auto &col : q.prototype) {
|
||||||
if (const auto rit = it->second.find(col.name()); col.type() == data_type_t::type_unknown && rit != it->second.end()) {
|
if (const auto rit = it->second.find(col.name()); col.type() == data_type_t::type_unknown && rit != it->second.end()) {
|
||||||
const_cast<column&>(col).type(rit->type());
|
const_cast<column_definition&>(col).type(rit->type());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto res = c->fetch(q.sql);
|
auto res = c->fetch(q.sql);
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,16 @@ TEST_CASE("Generate columns from object", "[column generator]") {
|
||||||
|
|
||||||
auto columns = column_generator::generate<matador::test::product>(repo);
|
auto columns = column_generator::generate<matador::test::product>(repo);
|
||||||
|
|
||||||
const std::vector<column> expected_columns = {
|
const std::vector<column_definition> expected_columns = {
|
||||||
column{ "product_name", data_type_t::type_varchar, constraints::PRIMARY_KEY, null_option::NOT_NULL },
|
column_definition{"product_name", data_type_t::type_varchar, constraints::PRIMARY_KEY, null_option::NOT_NULL },
|
||||||
column{ "supplier_id", data_type_t::type_unsigned_long, constraints::FOREIGN_KEY, null_option::NOT_NULL },
|
column_definition{"supplier_id", data_type_t::type_unsigned_long, constraints::FOREIGN_KEY, null_option::NOT_NULL },
|
||||||
column{ "category_id", data_type_t::type_unsigned_long, constraints::FOREIGN_KEY, null_option::NOT_NULL },
|
column_definition{"category_id", data_type_t::type_unsigned_long, constraints::FOREIGN_KEY, null_option::NOT_NULL },
|
||||||
column{ "quantity_per_unit", data_type_t::type_varchar, null_attributes, null_option::NOT_NULL },
|
column_definition{"quantity_per_unit", data_type_t::type_varchar, null_attributes, null_option::NOT_NULL },
|
||||||
column{ "unit_price", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL },
|
column_definition{"unit_price", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL },
|
||||||
column{ "units_in_stock", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL },
|
column_definition{"units_in_stock", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL },
|
||||||
column{ "units_in_order", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL },
|
column_definition{"units_in_order", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL },
|
||||||
column{ "reorder_level", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL },
|
column_definition{"reorder_level", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL },
|
||||||
column{ "discontinued", data_type_t::type_bool, null_attributes, null_option::NOT_NULL }
|
column_definition{"discontinued", data_type_t::type_bool, null_attributes, null_option::NOT_NULL }
|
||||||
};
|
};
|
||||||
REQUIRE(!columns.empty());
|
REQUIRE(!columns.empty());
|
||||||
REQUIRE(columns.size() == expected_columns.size());
|
REQUIRE(columns.size() == expected_columns.size());
|
||||||
|
|
@ -40,10 +40,10 @@ TEST_CASE("Generate columns from object with nullable columns", "[column generat
|
||||||
|
|
||||||
auto columns = column_generator::generate<matador::test::optional>(repo);
|
auto columns = column_generator::generate<matador::test::optional>(repo);
|
||||||
|
|
||||||
const std::vector<column> expected_columns = {
|
const std::vector<column_definition> expected_columns = {
|
||||||
column{ "id", data_type_t::type_unsigned_long, constraints::PRIMARY_KEY, null_option::NOT_NULL },
|
column_definition{"id", data_type_t::type_unsigned_long, constraints::PRIMARY_KEY, null_option::NOT_NULL },
|
||||||
column{ "name", data_type_t::type_varchar, null_attributes, null_option::NOT_NULL },
|
column_definition{"name", data_type_t::type_varchar, null_attributes, null_option::NOT_NULL },
|
||||||
column{ "age", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL }
|
column_definition{"age", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL }
|
||||||
};
|
};
|
||||||
REQUIRE(!columns.empty());
|
REQUIRE(!columns.empty());
|
||||||
REQUIRE(columns.size() == expected_columns.size());
|
REQUIRE(columns.size() == expected_columns.size());
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column_definition.hpp"
|
||||||
|
|
||||||
using namespace matador::sql;
|
using namespace matador::sql;
|
||||||
|
|
||||||
TEST_CASE("Create empty column", "[column]") {
|
TEST_CASE("Create empty column", "[column]") {
|
||||||
column c("name");
|
column_definition c("name");
|
||||||
|
|
||||||
REQUIRE(c.name() == "name");
|
REQUIRE(c.name() == "name");
|
||||||
REQUIRE(c.index() == 0);
|
REQUIRE(c.index() == 0);
|
||||||
|
|
@ -25,7 +25,7 @@ TEST_CASE("Create empty column", "[column]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Copy and move column", "[column]") {
|
TEST_CASE("Copy and move column", "[column]") {
|
||||||
column c("name");
|
column_definition c("name");
|
||||||
c.set(std::string{"george"}, 255);
|
c.set(std::string{"george"}, 255);
|
||||||
REQUIRE(c.name() == "name");
|
REQUIRE(c.name() == "name");
|
||||||
REQUIRE(c.index() == 0);
|
REQUIRE(c.index() == 0);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
#include <matador/sql/column.hpp>
|
#include <matador/sql/column_definition.hpp>
|
||||||
#include <matador/sql/condition.hpp>
|
#include <matador/sql/condition.hpp>
|
||||||
#include <matador/sql/dialect_builder.hpp>
|
#include <matador/sql/dialect_builder.hpp>
|
||||||
#include <matador/sql/query_builder.hpp>
|
#include <matador/sql/query_builder.hpp>
|
||||||
|
|
@ -164,7 +164,7 @@ TEST_CASE("Create, insert and select a blob column", "[query][blob]") {
|
||||||
REQUIRE(q.table_name == "person");
|
REQUIRE(q.table_name == "person");
|
||||||
|
|
||||||
q = query.insert().into("person", {
|
q = query.insert().into("person", {
|
||||||
{"", "id", ""}, {"", "name", ""}, {"", "data", ""}
|
{ "id", "name", "data" }
|
||||||
}).values({7UL, "george", blob{1, 'A', 3, 4}}).compile();
|
}).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.sql == R"(INSERT INTO "person" ("id", "name", "data") VALUES (7, 'george', X'01410304'))");
|
||||||
|
|
@ -176,7 +176,7 @@ TEST_CASE("Create, insert and select a blob column", "[query][blob]") {
|
||||||
REQUIRE(q.table_name == "person");
|
REQUIRE(q.table_name == "person");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Select statement with join", "[query][join]") {
|
TEST_CASE("Select statement with join_left", "[query][join_left]") {
|
||||||
dialect d = dialect_builder::builder().create().build();
|
dialect d = dialect_builder::builder().create().build();
|
||||||
query_builder query(d);
|
query_builder query(d);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue