query parts progress

This commit is contained in:
Sascha Kuehl 2024-02-24 18:16:23 +01:00
parent 0822332669
commit 6f5326941e
31 changed files with 887 additions and 381 deletions

View File

@ -14,6 +14,7 @@ class QueryRecordFixture
public: public:
QueryRecordFixture() QueryRecordFixture()
: db(matador::test::connection::dns) : db(matador::test::connection::dns)
, schema(std::make_shared<matador::sql::schema>(db.dialect().default_schema_name()))
{ {
db.open(); db.open();
} }
@ -26,11 +27,12 @@ public:
protected: protected:
matador::sql::connection db; matador::sql::connection db;
std::shared_ptr<matador::sql::schema> schema;
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.query().drop().table(table_name).execute(); db.query(schema).drop().table(table_name).execute();
} }
} }
}; };
@ -40,7 +42,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.query().create() db.query(schema).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),
@ -50,7 +52,7 @@ TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement", "[sessi
REQUIRE(db.exists("person")); REQUIRE(db.exists("person"));
db.query().drop() db.query(schema).drop()
.table("person") .table("person")
.execute(); .execute();
@ -59,7 +61,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.query().create() db.query(schema).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),
@ -69,7 +71,7 @@ TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement with fore
REQUIRE(db.exists("airplane")); REQUIRE(db.exists("airplane"));
db.query().create() db.query(schema).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"),
@ -79,13 +81,13 @@ TEST_CASE_METHOD(QueryRecordFixture, " Create and drop table statement with fore
REQUIRE(db.exists("flight")); REQUIRE(db.exists("flight"));
db.query().drop() db.query(schema).drop()
.table("flight") .table("flight")
.execute(); .execute();
REQUIRE(!db.exists("flight")); REQUIRE(!db.exists("flight"));
db.query().drop() db.query(schema).drop()
.table("airplane") .table("airplane")
.execute(); .execute();
@ -94,7 +96,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.query().create() db.query(schema).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),
@ -102,14 +104,14 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement", "[sessi
}) })
.execute(); .execute();
auto res = db.query().insert() auto res = db.query(schema).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.query().select({"id", "name", "age"}) auto result = db.query(schema).select({"id", "name", "age"})
.from("person") .from("person")
.fetch_all(); .fetch_all();
@ -126,14 +128,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.query().drop() db.query(schema).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.query().create() db.query(schema).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),
@ -141,7 +143,7 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement with fore
}) })
.execute(); .execute();
db.query().create() db.query(schema).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"),
@ -149,23 +151,23 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute insert record statement with fore
}) })
.execute(); .execute();
auto res = db.query().insert().into("airplane", {"id", "brand", "model"}).values({1, "Airbus", "A380"}).execute(); auto res = db.query(schema).insert().into("airplane", {"id", "brand", "model"}).values({1, "Airbus", "A380"}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("airplane", {"id", "brand", "model"}).values({2, "Boeing", "707"}).execute(); res = db.query(schema).insert().into("airplane", {"id", "brand", "model"}).values({2, "Boeing", "707"}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("airplane", {"id", "brand", "model"}).values({3, "Boeing", "747"}).execute(); res = db.query(schema).insert().into("airplane", {"id", "brand", "model"}).values({3, "Boeing", "747"}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
auto count = db.query().select({count_all()}).from("airplane").fetch_value<int>(); auto count = db.query(schema).select({count_all()}).from("airplane").fetch_value<int>();
REQUIRE(count == 3); REQUIRE(count == 3);
res = db.query().insert().into("flight", {"id", "airplane_id", "pilot_name"}).values({4, 1, "George"}).execute(); res = db.query(schema).insert().into("flight", {"id", "airplane_id", "pilot_name"}).values({4, 1, "George"}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
db.query().drop().table("flight").execute(); db.query(schema).drop().table("flight").execute();
db.query().drop().table("airplane").execute(); db.query(schema).drop().table("airplane").execute();
REQUIRE(!db.exists("flight")); REQUIRE(!db.exists("flight"));
REQUIRE(!db.exists("airplane")); REQUIRE(!db.exists("airplane"));
@ -173,7 +175,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.query().create() db.query(schema).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),
@ -181,14 +183,14 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute update record statement", "[sessi
}) })
.execute(); .execute();
auto res = db.query().insert() auto res = db.query(schema).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.query().update("person") res = db.query(schema).update("person")
.set({{"id", 7}, .set({{"id", 7},
{"name", "jane"}, {"name", "jane"},
{"age", 35}}) {"age", 35}})
@ -197,7 +199,7 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute update record statement", "[sessi
REQUIRE(res == 1); REQUIRE(res == 1);
auto result = db.query().select({"id", "name", "age"}) auto result = db.query(schema).select({"id", "name", "age"})
.from("person") .from("person")
.fetch_all(); .fetch_all();
@ -214,12 +216,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.query().drop().table("person").execute(); db.query(schema).drop().table("person").execute();
} }
TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement", "[session][record]") TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement", "[session][record]")
{ {
db.query().create() db.query(schema).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),
@ -227,16 +229,16 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement", "[session][rec
}) })
.execute(); .execute();
auto res = db.query().insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute(); auto res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute(); res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute(); res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute(); res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
auto result = db.query().select({"id", "name", "age"}) auto result = db.query(schema).select({"id", "name", "age"})
.from("person") .from("person")
.fetch_all(); .fetch_all();
@ -247,22 +249,22 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement", "[session][rec
} }
REQUIRE(expected_names.empty()); REQUIRE(expected_names.empty());
auto rec = db.query().select({"id", "name", "age"}) auto rec = db.query(schema).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.query().select({"name"}) auto name = db.query(schema).select({"name"})
.from("person") .from("person")
.fetch_value<std::string>(); .fetch_value<std::string>();
REQUIRE(name == "george"); REQUIRE(name == "george");
db.query().drop().table("person").execute(); db.query(schema).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.query().create() db.query(schema).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),
@ -270,16 +272,16 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with order by",
}) })
.execute(); .execute();
auto res = db.query().insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute(); auto res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute(); res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute(); res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute(); res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
auto result = db.query().select({"id", "name", "age"}) auto result = db.query(schema).select({"id", "name", "age"})
.from("person") .from("person")
.order_by("name").asc() .order_by("name").asc()
.fetch_all(); .fetch_all();
@ -291,12 +293,12 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with order by",
} }
REQUIRE(expected_names.empty()); REQUIRE(expected_names.empty());
db.query().drop().table("person").execute(); db.query(schema).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.query().create() db.query(schema).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),
@ -304,18 +306,18 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with group by an
}) })
.execute(); .execute();
auto res = db.query().insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute(); auto res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute(); res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("person", {"id", "name", "age"}).values({3, "michael", 13}).execute(); res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({3, "michael", 13}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute(); res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("person", {"id", "name", "age"}).values({5, "charlie", 67}).execute(); res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({5, "charlie", 67}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
auto result = db.query().select({alias(count("age"), "age_count"), "age"}) auto result = db.query(schema).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()
@ -330,41 +332,41 @@ TEST_CASE_METHOD(QueryRecordFixture, " Execute select statement with group by an
expected_values.pop_front(); expected_values.pop_front();
} }
db.query().drop().table("person").execute(); db.query(schema).drop().table("person").execute();
} }
TEST_CASE_METHOD(QueryRecordFixture, " Execute delete statement", "[session][record]") TEST_CASE_METHOD(QueryRecordFixture, " Execute delete statement", "[session][record]")
{ {
db.query().create() db.query(schema).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.query().insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute(); auto res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
res = db.query().insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute(); res = db.query(schema).insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
auto count = db.query().select({count_all()}).from("person").fetch_value<int>(); auto count = db.query(schema).select({count_all()}).from("person").fetch_value<int>();
REQUIRE(count == 2); REQUIRE(count == 2);
res = db.query().remove() res = db.query(schema).remove()
.from("person") .from("person")
.where("id"_col == 1) .where("id"_col == 1)
.execute(); .execute();
REQUIRE(res == 1); REQUIRE(res == 1);
count = db.query().select({count_all()}).from("person").fetch_value<int>(); count = db.query(schema).select({count_all()}).from("person").fetch_value<int>();
REQUIRE(count == 1); REQUIRE(count == 1);
db.query().drop().table("person").execute(); db.query(schema).drop().table("person").execute();
} }
TEST_CASE_METHOD(QueryRecordFixture, " Test quoted identifier", "[session][record]") { TEST_CASE_METHOD(QueryRecordFixture, " Test quoted identifier", "[session][record]") {
db.query().create() db.query(schema).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)
@ -380,19 +382,19 @@ TEST_CASE_METHOD(QueryRecordFixture, " Test quoted identifier", "[session][recor
REQUIRE(field.type() == types[field.index()]); REQUIRE(field.type() == types[field.index()]);
} }
db.query().insert().into("quotes", {"from", "to"}).values({"Berlin", "London"}).execute(); db.query(schema).insert().into("quotes", {"from", "to"}).values({"Berlin", "London"}).execute();
auto res = db.query().select({"from", "to"}).from("quotes").fetch_one(); auto res = db.query(schema).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.query().update("quotes").set({{"from", "Hamburg"}, {"to", "New York"}}).where("from"_col == "Berlin").execute(); db.query(schema).update("quotes").set({{"from", "Hamburg"}, {"to", "New York"}}).where("from"_col == "Berlin").execute();
res = db.query().select({"from", "to"}).from("quotes").fetch_one(); res = db.query(schema).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.query().drop().table("quotes").execute(); db.query(schema).drop().table("quotes").execute();
} }

View File

@ -19,6 +19,7 @@ class QueryFixture
public: public:
QueryFixture() QueryFixture()
: db(matador::test::connection::dns) : db(matador::test::connection::dns)
, schema(std::make_shared<matador::sql::schema>(db.dialect().default_schema_name()))
{ {
db.open(); db.open();
} }
@ -32,32 +33,33 @@ public:
protected: protected:
matador::sql::connection db; matador::sql::connection db;
std::shared_ptr<matador::sql::schema> schema;
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.query().drop().table(table_name).execute(); db.query(schema).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.query().create() db.query(schema).create()
.table<airplane>("airplane") .table<airplane>("airplane")
.execute(); .execute();
REQUIRE(db.exists("airplane")); REQUIRE(db.exists("airplane"));
db.query().create() db.query(schema).create()
.table<flight>("flight") .table<flight>("flight")
.execute(); .execute();
REQUIRE(db.exists("flight")); REQUIRE(db.exists("flight"));
db.query().drop().table("flight").execute(); db.query(schema).drop().table("flight").execute();
db.query().drop().table("airplane").execute(); db.query(schema).drop().table("airplane").execute();
REQUIRE(!db.exists("flight")); REQUIRE(!db.exists("flight"));
REQUIRE(!db.exists("airplane")); REQUIRE(!db.exists("airplane"));
@ -65,20 +67,22 @@ 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.query().create() db.query(schema).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.query().insert() auto res = db.query(schema)
.into("person", george) .insert()
.into<person>("person")
.values(george)
.execute(); .execute();
REQUIRE(res == 1); REQUIRE(res == 1);
// fetch person as record // fetch person as record
auto result_record = db.query().select<person>() auto result_record = db.query(schema).select<person>()
.from("person") .from("person")
.where("id"_col == 7) .where("id"_col == 7)
.fetch_all(); .fetch_all();
@ -97,7 +101,7 @@ TEST_CASE_METHOD(QueryFixture, " Execute select statement with where clause", "[
} }
// fetch person as person // fetch person as person
auto result_person = db.query().select<person>() auto result_person = db.query(schema).select<person>()
.from("person") .from("person")
.where("id"_col == 7) .where("id"_col == 7)
.fetch_all<person>(); .fetch_all<person>();
@ -108,12 +112,12 @@ TEST_CASE_METHOD(QueryFixture, " Execute select statement with where clause", "[
REQUIRE(i.age == 45); REQUIRE(i.age == 45);
} }
db.query().drop().table("person").execute(); db.query(schema).drop().table("person").execute();
} }
TEST_CASE_METHOD(QueryFixture, " Execute insert statement", "[session]") TEST_CASE_METHOD(QueryFixture, " Execute insert statement", "[session]")
{ {
db.query().create() db.query(schema).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),
@ -121,7 +125,7 @@ TEST_CASE_METHOD(QueryFixture, " Execute insert statement", "[session]")
}) })
.execute(); .execute();
auto res = db.query().insert() auto res = db.query(schema).insert()
.into("person", {{"", "id", ""}, {"", "name", ""}, {"", "color", ""}}) .into("person", {{"", "id", ""}, {"", "name", ""}, {"", "color", ""}})
.values({7, "george", "green"}) .values({7, "george", "green"})
.execute(); .execute();
@ -129,7 +133,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.query().select({"id", "name", "color"}) auto result_record = db.query(schema).select({"id", "name", "color"})
.from("person") .from("person")
.where("id"_col == 7) .where("id"_col == 7)
.fetch_all(); .fetch_all();
@ -147,16 +151,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.query().drop().table("person").execute(); db.query(schema).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.query().create() db.query(schema).create()
.table<airplane>("airplane") .table<airplane>("airplane")
.execute(); .execute();
db.query().create() db.query(schema).create()
.table<flight>("flight") .table<flight>("flight")
.execute(); .execute();
@ -167,35 +171,35 @@ TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key", "[session]"
}; };
for (const auto &plane: planes) { for (const auto &plane: planes) {
auto res = db.query().insert().into<airplane>("airplane").values(*plane).execute(); auto res = db.query(schema).insert().into<airplane>("airplane").values(*plane).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
} }
auto count = db.query().select({count_all()}).from("airplane").fetch_value<int>(); auto count = db.query(schema).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.query().insert().into<flight>("flight").values(f4711).execute(); auto res = db.query(schema).insert().into<flight>("flight").values(f4711).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
auto f = *db.query().select<flight>().from("flight").fetch_all<flight>().begin(); auto f = *db.query(schema).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.query().drop().table("flight").execute(); db.query(schema).drop().table("flight").execute();
db.query().drop().table("airplane").execute(); db.query(schema).drop().table("airplane").execute();
} }
TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key and join_left", "[session][join_left]") TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key and join_left", "[session][join_left]")
{ {
db.query().create() db.query(schema).create()
.table<airplane>("airplane") .table<airplane>("airplane")
.execute(); .execute();
db.query().create() db.query(schema).create()
.table<flight>("flight") .table<flight>("flight")
.execute(); .execute();
@ -206,11 +210,11 @@ TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key and join_left
}; };
for (const auto &plane: planes) { for (const auto &plane: planes) {
auto res = db.query().insert().into<airplane>("airplane").values(*plane).execute(); auto res = db.query(schema).insert().into<airplane>("airplane").values(*plane).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
} }
auto count = db.query().select({count_all()}).from("airplane").fetch_value<int>(); auto count = db.query(schema).select({count_all()}).from("airplane").fetch_value<int>();
REQUIRE(count == 3); REQUIRE(count == 3);
std::vector<entity<flight>> flights{ std::vector<entity<flight>> flights{
@ -221,17 +225,17 @@ TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key and join_left
}; };
for (const auto &f: flights) { for (const auto &f: flights) {
auto res = db.query().insert().into<flight>("flight").values(*f).execute(); auto res = db.query(schema).insert().into<flight>("flight").values(*f).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
} }
auto f = *db.query().select<flight>().from("flight").fetch_all<flight>().begin(); auto f = *db.query(schema).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.query().select({"f.id", "ap.brand", "ap.model", "f.pilot_name"}) auto result = db.query(schema).select({"f.id", "ap.brand", "ap.model", "f.pilot_name"})
.from({"flight", "f"}) .from({"flight", "f"})
.join_left({"airplane", "ap"}) .join_left({"airplane", "ap"})
.on("f.airplane_id"_col == "ap.id"_col) .on("f.airplane_id"_col == "ap.id"_col)
@ -251,7 +255,7 @@ TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key and join_left
REQUIRE(r.at(3).as<std::string>() == expected_result[index++].second); REQUIRE(r.at(3).as<std::string>() == expected_result[index++].second);
} }
db.query().drop().table("flight").execute(); db.query(schema).drop().table("flight").execute();
db.query().drop().table("airplane").execute(); db.query(schema).drop().table("airplane").execute();
} }

View File

@ -16,9 +16,10 @@ class StatementTestFixture
public: public:
StatementTestFixture() StatementTestFixture()
: db(matador::test::connection::dns) : db(matador::test::connection::dns)
, schema(std::make_shared<matador::sql::schema>(db.dialect().default_schema_name()))
{ {
db.open(); db.open();
db.query().create().table<airplane>("airplane").execute(); db.query(schema).create().table<airplane>("airplane").execute();
} }
~StatementTestFixture() ~StatementTestFixture()
@ -28,6 +29,7 @@ public:
protected: protected:
matador::sql::connection db; matador::sql::connection db;
std::shared_ptr<matador::sql::schema> schema;
std::vector<entity<airplane>> planes{ std::vector<entity<airplane>> planes{
make_entity<airplane>(1, "Airbus", "A380"), make_entity<airplane>(1, "Airbus", "A380"),
@ -38,7 +40,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.query().drop().table(table_name).execute(); db.query(schema).drop().table(table_name).execute();
} }
} }
@ -48,7 +50,7 @@ TEST_CASE_METHOD(StatementTestFixture, " Create prepared statement", "[statement
{ {
table ap{"airplane"}; table ap{"airplane"};
SECTION("Insert with prepared statement and placeholder") { SECTION("Insert with prepared statement and placeholder") {
auto stmt = db.query().insert() auto stmt = db.query(schema).insert()
.into<airplane>("airplane") .into<airplane>("airplane")
.values<airplane>().prepare(); .values<airplane>().prepare();
@ -58,7 +60,7 @@ TEST_CASE_METHOD(StatementTestFixture, " Create prepared statement", "[statement
stmt.reset(); stmt.reset();
} }
auto result = db.query().select<airplane>().from(ap).fetch_all<airplane>(); auto result = db.query(schema).select<airplane>().from(ap).fetch_all<airplane>();
size_t index{0}; size_t index{0};
for (const auto &i: result) { for (const auto &i: result) {
@ -70,11 +72,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.query().insert().into<airplane>("airplane").values(*plane).execute(); auto res = db.query(schema).insert().into<airplane>("airplane").values(*plane).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
} }
auto stmt = db.query().select<airplane>().from(ap).where("brand"_col == _).prepare(); auto stmt = db.query(schema).select<airplane>().from(ap).where("brand"_col == _).prepare();
stmt.bind(0, "Airbus"); stmt.bind(0, "Airbus");

View File

@ -15,25 +15,27 @@ class TypeTraitsTestFixture
public: public:
TypeTraitsTestFixture() TypeTraitsTestFixture()
: db(matador::test::connection::dns) : db(matador::test::connection::dns)
, schema(std::make_shared<matador::sql::schema>(db.dialect().default_schema_name()))
{ {
db.open(); db.open();
db.query().create() db.query(schema).create()
.table<location>("location") .table<location>("location")
.execute(); .execute();
} }
~TypeTraitsTestFixture() ~TypeTraitsTestFixture()
{ {
db.query().drop().table("location").execute(); db.query(schema).drop().table("location").execute();
} }
protected: protected:
matador::sql::connection db; matador::sql::connection db;
std::shared_ptr<matador::sql::schema> schema;
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.query().drop().table(table_name).execute(); db.query(schema).drop().table(table_name).execute();
} }
} }
}; };
@ -85,10 +87,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.query().insert().into<location>("location").values(loc).execute(); auto res = db.query(schema).insert().into<location>("location").values(loc).execute();
REQUIRE(res == 1); REQUIRE(res == 1);
auto result = db.query().select<location>().from("location").fetch_all<location>(); auto result = db.query(schema).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 +100,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.query().insert().into<location>("location").values<location>().prepare(); auto stmt = db.query(schema).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.query().select<location>().from("location"). auto result = db.query(schema).select<location>().from("location").
template fetch_all<location>(); template fetch_all<location>();
for (const auto &l: result) { for (const auto &l: result) {

View File

@ -61,26 +61,97 @@ int main()
std::string dns{"sqlite://demo.db"}; std::string dns{"sqlite://demo.db"};
// std::string dns{"memory://test"}; // std::string dns{"memory://test"};
auto s = std::make_shared<schema>(); auto s = std::make_shared<schema>("main");
s->attach<author>("authors"); s->attach<author>("authors");
s->attach<book>("books"); s->attach<book>("books");
connection c(dns, s); connection c(dns);
c.open();
auto books = c.query() auto create_authors_sql = c.query(s)
.select<book>({qh::authors.first_name}) .create()
.table<author>(qh::authors)
// .str();
.execute();
c.query(s).create().table<book>(qh::books).execute();
std::cout << "SQL: " << create_authors_sql << "\n";
auto mc = make_entity<author>();
mc->id = 1;
mc->first_name = "Michael";
mc->last_name = "Crichton";
mc->date_of_birth = "19.8.1954";
mc->year_of_birth = 1954;
mc->distinguished = true;
auto insert_authors_sql = c.query(s)
.insert()
.into<author>(qh::authors)
.values(*mc)
.execute();
// .str();
std::cout << "SQL: " << insert_authors_sql << "\n";
auto result = c.query(s)
.select<author>()
.from(qh::authors)
.fetch_all();
for (const auto &row : result) {
std::cout << "Author " << row.at(qh::authors.first_name) << "\n";
}
auto update_authors_sql = c.query(s)
.update(qh::authors)
.set({{qh::authors.first_name, "Stephen"}, {qh::authors.last_name, "King"}})
.where(qh::authors.last_name == "Crichton")
.execute();
// .str();
std::cout << "SQL: " << update_authors_sql << "\n";
auto authors = c.query(s)
.select<author>()
.from(qh::authors)
.fetch_all<author>();
for (const auto &a : authors) {
std::cout << "Author " << a.first_name << "\n";
}
c.query(s)
.insert()
.into<book>(qh::books)
.values({2, "It", mc->id, 1980})
.execute();
c.query(s)
.insert()
.into<book>(qh::books)
.values({3, "Misery", mc->id, 1984})
.execute();
auto select_books_sql = c.query(s)
.select<book>({qh::authors.last_name})
.from(qh::books) .from(qh::books)
.join_left(qh::authors) .join_left(qh::authors)
.on(qh::books.author_id == qh::authors.id) .on(qh::books.author_id == qh::authors.id)
.where(qh::books.published_in < 2008 && qh::authors.first_name == "Michael Crichton") .where(qh::books.published_in < 2008 && qh::authors.last_name == "King")
.group_by(qh::books.published_in)
.order_by(qh::books.title).asc() .order_by(qh::books.title).asc()
.offset(2) // .offset(2)
.limit(5) // .limit(5)
.str(); // .str();
.fetch_all();
// .fetch_all<book>(); // .fetch_all<book>();
std::cout << "SQL: " << books << "\n"; // std::cout << "SQL: " << select_books_sql << "\n";
for (const auto &r : select_books_sql) {
std::cout << "R: " << r.at(qh::books.title) << ", " << r.at(qh::authors.last_name) << "\n";
}
// SELECT book.title, book.id, book.author_id, book.published_in, author.name // SELECT book.title, book.id, book.author_id, book.published_in, author.name
// FROM book // FROM book
// INNER JOIN author ON book.author_id = author.id // INNER JOIN author ON book.author_id = author.id
@ -88,7 +159,6 @@ int main()
// ORDER BY "book.title" ASC // ORDER BY "book.title" ASC
// OFFSET 2 LIMIT 5 // OFFSET 2 LIMIT 5
// 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());
@ -97,5 +167,16 @@ int main()
// } else { // } else {
// std::cout << "env var: " << var << "\n"; // std::cout << "env var: " << var << "\n";
// } // }
c.query(s).drop().table(qh::books).execute();
auto drop_authors_sql = c.query(s)
.drop()
.table(qh::authors)
// .str();
.execute();
std::cout << "SQL: " << drop_authors_sql << "\n";
return 0; return 0;
} }

View File

@ -96,6 +96,8 @@ public:
return visitor.result; return visitor.result;
} }
friend std::ostream& operator<<(std::ostream &out, const column_definition &col);
private: private:
template<class Operator> template<class Operator>
void process(Operator &op) void process(Operator &op)

View File

@ -57,7 +57,7 @@ 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_) + " " + operand + " " + std::to_string(value);
} }
}; };
@ -77,7 +77,7 @@ 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_) + " " + operand + " '" + value + "'";
} }
}; };
@ -97,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_);
} }
}; };
@ -116,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_);
} }
}; };
@ -162,7 +162,7 @@ public:
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_) + " 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));
@ -264,7 +264,7 @@ 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);
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_) + " BETWEEN " + std::to_string(range_.first) + " AND " + std::to_string(range_.second);
} }
private: private:
@ -371,7 +371,7 @@ public:
*/ */
std::string evaluate(dialect &d, query_context &query) const override std::string evaluate(dialect &d, query_context &query) const override
{ {
return d.prepare_identifier(field_.name) + " " + operand + " " + d.prepare_identifier(other_column_.name); return d.prepare_identifier(field_) + " " + operand + " " + d.prepare_identifier(other_column_);
} }
private: private:

View File

@ -20,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<sql::schema>()); explicit connection(connection_info info);
explicit connection(const std::string& dns, const std::shared_ptr<schema> &repo = std::make_shared<sql::schema>()); explicit connection(const std::string& dns);
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;
@ -36,7 +36,7 @@ public:
[[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; sql::query query(const std::shared_ptr<sql::schema> &schema) 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;
@ -45,14 +45,12 @@ 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<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<sql::schema> schema_;
}; };
} }

View File

@ -2,13 +2,15 @@
#define QUERY_KEY_VALUE_PAIR_HPP #define QUERY_KEY_VALUE_PAIR_HPP
#include "matador/sql/any_type.hpp" #include "matador/sql/any_type.hpp"
#include "matador/sql/column.hpp"
namespace matador::sql { namespace matador::sql {
class key_value_pair class key_value_pair
{ {
public: public:
key_value_pair(const std::string &name, any_type value); key_value_pair(const sql::column &col, any_type value);
key_value_pair(std::string name, any_type value);
key_value_pair(const char *name, any_type value); key_value_pair(const char *name, any_type value);
[[nodiscard]] const std::string& name() const; [[nodiscard]] const std::string& name() const;

View File

@ -10,7 +10,7 @@ class connection;
class query class query
{ {
public: public:
explicit query(connection &c); explicit query(connection &db, const std::shared_ptr<sql::schema> &schema);
query(const query &) = delete; query(const query &) = delete;
query& operator=(const query &) = delete; query& operator=(const query &) = delete;
@ -22,28 +22,26 @@ public:
query_select_intermediate select(std::initializer_list<column> columns); query_select_intermediate select(std::initializer_list<column> columns);
query_select_intermediate select(std::initializer_list<column> columns); query_select_intermediate select(std::initializer_list<column> columns);
query_insert_intermediate insert(); query_insert_intermediate insert();
query_update_intermediate update(const std::string &table); query_update_intermediate update(const sql::table &table);
query_delete_intermediate remove(); query_delete_intermediate remove();
private:
[[nodiscard]] const sql::schema& schema() const;
private: private:
connection &connection_; connection &connection_;
std::shared_ptr<sql::schema> schema_;
}; };
template<class Type> template<class Type>
query_select_intermediate query::select() query_select_intermediate query::select()
{ {
return query_select_intermediate{connection_, column_name_generator::generate<Type>(this->schema())}; return query_select_intermediate{connection_, schema_, column_name_generator::generate<Type>(*schema_)};
} }
template<class Type> template<class Type>
query_select_intermediate query::select(std::initializer_list<column> columns) query_select_intermediate query::select(std::initializer_list<column> columns)
{ {
auto cols = column_name_generator::generate<Type>(this->schema()); auto cols = column_name_generator::generate<Type>(*schema_);
cols.insert(cols.end(), columns); cols.insert(cols.end(), columns);
return query_select_intermediate{connection_, cols}; return query_select_intermediate{connection_, schema_, cols};
} }
} }

View File

@ -31,17 +31,22 @@ private:
void visit(query_order_by_part &order_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_asc_part &order_by_asc_part) override;
void visit(query_order_by_desc_part &order_by_desc_part) override; void visit(query_order_by_desc_part &order_by_desc_part) override;
void visit(query_offset_part &offset_part) override;
void visit(query_limit_part &limit_part) override;
void visit(query_insert_part &insert_part) override; void visit(query_insert_part &insert_part) override;
void visit(query_into_part &into_part) override;
void visit(query_values_part &values_part) override; void visit(query_values_part &values_part) override;
void visit(query_update_part &update_part) override; void visit(query_update_part &update_part) override;
void visit(query_set_part &set_part) override;
void visit(query_delete_part &delete_part) override; void visit(query_delete_part &delete_part) override;
void visit(query_create_part &create_part) override; void visit(query_create_part &create_part) override;
void visit(query_create_table_part &create_table_part) override;
void visit(query_drop_part &drop_part) override; void visit(query_drop_part &drop_part) override;
void visit(query_drop_table_part &drop_table_part) override;
private: private:
const sql::dialect &dialect_; const sql::dialect &dialect_;

View File

@ -24,19 +24,17 @@ class connection;
class basic_query_intermediate class basic_query_intermediate
{ {
public: public:
explicit basic_query_intermediate(connection &db); explicit basic_query_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema);
protected:
[[nodiscard]] std::shared_ptr<schema> tables() const;
protected: protected:
connection &connection_; connection &connection_;
std::shared_ptr<sql::schema> schema_;
}; };
class query_intermediate : public basic_query_intermediate class query_intermediate : public basic_query_intermediate
{ {
public: public:
query_intermediate(connection &db, query_data &data); query_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema, query_data &data);
protected: protected:
query_data &data_; query_data &data_;
@ -49,6 +47,7 @@ public:
size_t execute(); size_t execute();
statement prepare(); statement prepare();
[[nodiscard]] std::string str() const;
}; };
class query_select_finish : public query_intermediate class query_select_finish : public query_intermediate
@ -109,7 +108,7 @@ class query_group_by_intermediate : public query_select_finish
public: public:
using query_select_finish::query_select_finish; using query_select_finish::query_select_finish;
query_order_by_intermediate order_by(const std::string &name); query_order_by_intermediate order_by(const column &col);
}; };
class query_order_by_intermediate : public query_intermediate class query_order_by_intermediate : public query_intermediate
@ -126,7 +125,7 @@ class query_where_intermediate : public query_select_finish
public: public:
using query_select_finish::query_select_finish; using query_select_finish::query_select_finish;
query_group_by_intermediate group_by(const std::string &name); query_group_by_intermediate group_by(const column &col);
query_order_by_intermediate order_by(const column &col); query_order_by_intermediate order_by(const column &col);
}; };
@ -137,14 +136,14 @@ class query_on_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 table &t);
template<class Condition> template<class Condition>
query_where_intermediate where(const Condition &cond) query_where_intermediate where(const Condition &cond)
{ {
data_.parts.push_back(std::make_unique<query_where_part>(cond)); data_.parts.push_back(std::make_unique<query_where_part>(cond));
return {connection_, data_}; return {connection_, schema_, data_};
} }
query_group_by_intermediate group_by(const std::string &name); query_group_by_intermediate group_by(const column &col);
query_order_by_intermediate order_by(const column &col); query_order_by_intermediate order_by(const column &col);
}; };
@ -157,7 +156,7 @@ public:
query_on_intermediate on(const Condition &cond) query_on_intermediate on(const Condition &cond)
{ {
data_.parts.push_back(std::make_unique<query_on_part>(cond)); data_.parts.push_back(std::make_unique<query_on_part>(cond));
return {connection_, data_}; return {connection_, schema_, data_};
} }
}; };
@ -167,15 +166,20 @@ public:
using query_select_finish::query_select_finish; using query_select_finish::query_select_finish;
query_join_intermediate join_left(const table &t); query_join_intermediate join_left(const table &t);
query_where_intermediate where(const basic_condition &cond); template<class Condition>
query_group_by_intermediate group_by(const std::string &name); query_where_intermediate where(const Condition &cond)
query_order_by_intermediate order_by(const std::string &name); {
data_.parts.push_back(std::make_unique<query_where_part>(cond));
return {connection_, schema_, data_};
}
query_group_by_intermediate group_by(const column &col);
query_order_by_intermediate order_by(const column &col);
}; };
class query_start_intermediate : public basic_query_intermediate class query_start_intermediate : public basic_query_intermediate
{ {
public: public:
explicit query_start_intermediate(connection &db); explicit query_start_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema);
protected: protected:
query_data data_; query_data data_;
@ -184,7 +188,7 @@ protected:
class query_select_intermediate : public query_start_intermediate class query_select_intermediate : public query_start_intermediate
{ {
public: public:
query_select_intermediate(connection &s, const std::vector<column>& columns); query_select_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema, const std::vector<column>& columns);
query_from_intermediate from(const table& t); query_from_intermediate from(const table& t);
}; };
@ -209,61 +213,54 @@ public:
query_execute_finish values() query_execute_finish values()
{ {
Type obj; Type obj;
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_values_part>(as_placeholder(obj)));
// return {connection_, builder_.values(as_placeholder(obj))}; return {connection_, schema_, data_};
} }
template<class Type> template<class Type>
query_execute_finish values(const Type &obj) query_execute_finish values(const Type &obj)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_values_part>(value_extractor::extract(obj)));
// return {connection_, builder_.values(value_extractor::extract(obj))}; return {connection_, schema_, data_};
} }
}; };
class query_create_intermediate : public query_start_intermediate class query_create_intermediate : public query_start_intermediate
{ {
public: public:
explicit query_create_intermediate(connection &db); explicit query_create_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema);
query_execute_finish table(const std::string &table_name, std::initializer_list<column_definition> columns); query_execute_finish table(const sql::table &table, std::initializer_list<column_definition> columns);
query_execute_finish table(const std::string &table_name, const std::vector<column_definition> &columns); query_execute_finish table(const sql::table &table, 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 sql::table &table)
{ {
if (!tables()->exists<Type>()) { if (!schema_->exists<Type>()) {
tables()->attach<Type>(table_name); schema_->attach<Type>(table.name);
} }
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_create_table_part>(table, column_generator::generate<Type>(*schema_)));
// return {connection_, builder_.table(table_name, column_generator::generate<Type>(*tables()))}; return {connection_, schema_, data_};
} }
}; };
class query_drop_intermediate : query_start_intermediate class query_drop_intermediate : query_start_intermediate
{ {
public: public:
explicit query_drop_intermediate(connection &s); explicit query_drop_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema);
query_execute_finish table(const std::string &table); query_execute_finish table(const sql::table &table);
}; };
class query_insert_intermediate : public query_start_intermediate class query_insert_intermediate : public query_start_intermediate
{ {
public: public:
explicit query_insert_intermediate(connection &s); explicit query_insert_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema);
query_into_intermediate into(const std::string &table, std::initializer_list<column> column_names); query_into_intermediate into(const sql::table &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 sql::table &table)
{ {;
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_into_part>(table, column_name_generator::generate<Type>(*schema_)));
// return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))}; return {connection_, schema_, data_};
}
template<class Type>
query_execute_finish into(const std::string &table, const Type &obj)
{
return {connection_, data_};
// return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))
// .values(value_extractor::extract(obj))};
} }
}; };
@ -280,20 +277,25 @@ class query_set_intermediate : public query_execute_finish
public: public:
using query_execute_finish::query_execute_finish; using query_execute_finish::query_execute_finish;
query_execute_where_intermediate where(const basic_condition &cond); template<class Condition>
query_execute_where_intermediate where(const Condition &cond)
{
data_.parts.push_back(std::make_unique<query_where_part>(cond));
return {connection_, schema_, data_};
}
}; };
class query_update_intermediate : public query_start_intermediate class query_update_intermediate : public query_start_intermediate
{ {
public: public:
query_update_intermediate(connection &s, const std::string& table_name); query_update_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema, const sql::table& table);
query_set_intermediate set(std::initializer_list<key_value_pair> columns); query_set_intermediate set(std::initializer_list<key_value_pair> columns);
template<class Type> template<class Type>
query_set_intermediate set(const Type &obj) query_set_intermediate set(const Type &obj)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_set_part>(key_value_generator::generate(obj)));
// return {connection_, builder_.set(key_value_generator::generate(obj))}; return {connection_, schema_, data_};
} }
}; };
@ -302,15 +304,20 @@ class query_delete_from_intermediate : public query_execute_finish
public: public:
using query_execute_finish::query_execute_finish; using query_execute_finish::query_execute_finish;
query_execute_where_intermediate where(const basic_condition &cond); template<class Condition>
query_execute_where_intermediate where(const Condition &cond)
{
data_.parts.push_back(std::make_unique<query_where_part>(cond));
return {connection_, schema_, data_};
}
}; };
class query_delete_intermediate : public query_start_intermediate class query_delete_intermediate : public query_start_intermediate
{ {
public: public:
explicit query_delete_intermediate(connection &s); explicit query_delete_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema);
query_delete_from_intermediate from(const std::string &table); query_delete_from_intermediate from(const sql::table &table);
}; };
} }

View File

@ -12,12 +12,18 @@ class query_group_by_part;
class query_order_by_part; class query_order_by_part;
class query_order_by_asc_part; class query_order_by_asc_part;
class query_order_by_desc_part; class query_order_by_desc_part;
class query_offset_part;
class query_limit_part;
class query_insert_part; class query_insert_part;
class query_into_part;
class query_values_part; class query_values_part;
class query_update_part; class query_update_part;
class query_set_part;
class query_delete_part; class query_delete_part;
class query_create_part; class query_create_part;
class query_create_table_part;
class query_drop_part; class query_drop_part;
class query_drop_table_part;
class query_part_visitor class query_part_visitor
{ {
@ -33,16 +39,23 @@ public:
virtual void visit(query_order_by_part &order_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_asc_part &order_by_asc_part) = 0;
virtual void visit(query_order_by_desc_part &order_by_desc_part) = 0; virtual void visit(query_order_by_desc_part &order_by_desc_part) = 0;
virtual void visit(query_offset_part &offset_part) = 0;
virtual void visit(query_limit_part &limit_part) = 0;
virtual void visit(query_insert_part &insert_part) = 0; virtual void visit(query_insert_part &insert_part) = 0;
virtual void visit(query_into_part &into_part) = 0;
virtual void visit(query_values_part &values_part) = 0; virtual void visit(query_values_part &values_part) = 0;
virtual void visit(query_update_part &update_part) = 0; virtual void visit(query_update_part &update_part) = 0;
virtual void visit(query_set_part &set_part) = 0;
virtual void visit(query_delete_part &delete_part) = 0; virtual void visit(query_delete_part &delete_part) = 0;
virtual void visit(query_create_part &create_part) = 0; virtual void visit(query_create_part &create_part) = 0;
virtual void visit(query_create_table_part &create_table_part) = 0;
virtual void visit(query_drop_part &drop_part) = 0; virtual void visit(query_drop_part &drop_part) = 0;
virtual void visit(query_drop_table_part &drop_table_part) = 0;
}; };
} }

View File

@ -6,6 +6,7 @@
#include "matador/sql/column.hpp" #include "matador/sql/column.hpp"
#include "matador/sql/column_definition.hpp" #include "matador/sql/column_definition.hpp"
#include "matador/sql/dialect.hpp" #include "matador/sql/dialect.hpp"
#include "matador/sql/key_value_pair.hpp"
#include "matador/sql/table.hpp" #include "matador/sql/table.hpp"
#include <memory> #include <memory>
@ -98,7 +99,7 @@ public:
: query_part(dialect::token_t::WHERE) : query_part(dialect::token_t::WHERE)
, condition_(new Condition(cond)) {} , condition_(new Condition(cond)) {}
const basic_condition& condition() const; [[nodiscard]] const basic_condition& condition() const;
private: private:
void accept(query_part_visitor &visitor) override; void accept(query_part_visitor &visitor) override;
@ -116,13 +117,18 @@ protected:
std::string table_name_; std::string table_name_;
}; };
class query_group_by_part : public query_table_name_part class query_group_by_part : public query_part
{ {
public: public:
explicit query_group_by_part(const std::string &table_name); explicit query_group_by_part(sql::column col);
[[nodiscard]] const sql::column& column() const;
private: private:
void accept(query_part_visitor &visitor) override; void accept(query_part_visitor &visitor) override;
private:
sql::column column_;
}; };
class query_order_by_part : public query_part class query_order_by_part : public query_part
@ -130,7 +136,7 @@ class query_order_by_part : public query_part
public: public:
explicit query_order_by_part(sql::column col); explicit query_order_by_part(sql::column col);
const sql::column& column() const; [[nodiscard]] const sql::column& column() const;
private: private:
void accept(query_part_visitor &visitor) override; void accept(query_part_visitor &visitor) override;
@ -157,6 +163,34 @@ private:
void accept(query_part_visitor &visitor) override; void accept(query_part_visitor &visitor) override;
}; };
class query_offset_part : public query_part
{
public:
explicit query_offset_part(size_t offset);
size_t offset() const;
private:
void accept(query_part_visitor &visitor) override;
private:
size_t offset_;
};
class query_limit_part : public query_part
{
public:
explicit query_limit_part(size_t limit);
size_t limit() const;
private:
void accept(query_part_visitor &visitor) override;
private:
size_t limit_;
};
class query_insert_part : public query_part class query_insert_part : public query_part
{ {
public: public:
@ -166,13 +200,30 @@ private:
void accept(query_part_visitor &visitor) override; void accept(query_part_visitor &visitor) override;
}; };
class query_into_part : public query_part
{
public:
query_into_part(sql::table t, std::vector<sql::column> columns);
[[nodiscard]] const sql::table& table() const;
[[nodiscard]] const std::vector<column>& columns() const;
private:
void accept(query_part_visitor &visitor) override;
private:
sql::table table_;
std::vector<column> columns_;
};
/** /**
* Represents the SQL VALUES part * Represents the SQL VALUES part
*/ */
class query_values_part : public query_part class query_values_part : public query_part
{ {
public: public:
query_values_part(std::initializer_list<any_type> values); query_values_part(std::vector<any_type> values);
[[nodiscard]] const std::vector<any_type>& values() const;
private: private:
void accept(query_part_visitor &visitor) override; void accept(query_part_visitor &visitor) override;
@ -181,13 +232,32 @@ private:
std::vector<any_type> values_; std::vector<any_type> values_;
}; };
class query_update_part : public query_table_name_part class query_update_part : public query_part
{ {
public: public:
explicit query_update_part(const std::string &table_name); explicit query_update_part(sql::table table);
[[nodiscard]] const sql::table& table() const;
private: private:
void accept(query_part_visitor &visitor) override; void accept(query_part_visitor &visitor) override;
private:
sql::table table_;
};
class query_set_part : public query_part
{
public:
explicit query_set_part(const std::vector<sql::key_value_pair>& key_value_pairs);
[[nodiscard]] const std::vector<sql::key_value_pair>& key_values() const;
private:
void accept(query_part_visitor &visitor) override;
private:
std::vector<sql::key_value_pair> key_value_pairs_;
}; };
class query_delete_part : public query_part class query_delete_part : public query_part
@ -208,6 +278,22 @@ private:
void accept(query_part_visitor &visitor) override; void accept(query_part_visitor &visitor) override;
}; };
class query_create_table_part : public query_part
{
public:
query_create_table_part(sql::table table, std::vector<sql::column_definition> columns);
[[nodiscard]] const sql::table& table() const;
const std::vector<sql::column_definition>& columns() const;
private:
void accept(query_part_visitor &visitor) override;
private:
sql::table table_;
std::vector<sql::column_definition> columns_;
};
class query_drop_part : public query_part class query_drop_part : public query_part
{ {
public: public:
@ -217,5 +303,19 @@ private:
void accept(query_part_visitor &visitor) override; void accept(query_part_visitor &visitor) override;
}; };
class query_drop_table_part : public query_part
{
public:
explicit query_drop_table_part(sql::table table);
[[nodiscard]] const sql::table& table() const;
private:
void accept(query_part_visitor &visitor) override;
private:
sql::table table_;
};
} }
#endif //QUERY_QUERY_PARTS_HPP #endif //QUERY_QUERY_PARTS_HPP

View File

@ -10,6 +10,8 @@
namespace matador::sql { namespace matador::sql {
struct column;
class record class record
{ {
private: private:
@ -50,7 +52,8 @@ public:
[[nodiscard]] const std::vector<column_definition>& columns() const; [[nodiscard]] const std::vector<column_definition>& columns() const;
[[nodiscard]] const column_definition& at(const std::string &name) const; [[nodiscard]] const column_definition& at(const column &col) const;
// [[nodiscard]] const column_definition& at(const std::string &name) const;
[[nodiscard]] const column_definition& 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);

View File

@ -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;
explicit schema(std::string name);
[[nodiscard]] std::string name() const; [[nodiscard]] std::string name() const;
template<typename Type> template<typename Type>

View File

@ -56,25 +56,25 @@ private:
connection_pool<connection> &pool_; connection_pool<connection> &pool_;
const class dialect &dialect_; const class dialect &dialect_;
schema schema_; std::shared_ptr<schema> schema_;
mutable std::unordered_map<std::string, record> prototypes_; mutable std::unordered_map<std::string, record> prototypes_;
}; };
template<typename Type> template<typename Type>
void session::attach(const std::string &table_name) void session::attach(const std::string &table_name)
{ {
schema_.attach<Type>(table_name); schema_->attach<Type>(table_name);
} }
template<typename Type> template<typename Type>
entity<Type> session::insert(Type *obj) entity<Type> session::insert(Type *obj)
{ {
auto c = pool_.acquire(); auto c = pool_.acquire();
auto info = schema_.info<Type>(); auto info = schema_->info<Type>();
if (!info) { if (!info) {
return {}; return {};
} }
c->query().insert().into<Type>(info->name).values(*obj).execute(); c->query(schema_).insert().into<Type>(info->name).values(*obj).execute();
return entity{obj}; return entity{obj};
} }
@ -82,7 +82,7 @@ entity<Type> session::insert(Type *obj)
template<typename Type> template<typename Type>
void session::drop_table() void session::drop_table()
{ {
auto info = schema_.info<Type>(); auto info = schema_->info<Type>();
if (info) { if (info) {
return drop_table(info.name); return drop_table(info.name);
} }

View File

@ -1,5 +1,6 @@
#include "matador/sql/column_definition.hpp" #include "matador/sql/column_definition.hpp"
#include <ostream>
#include <utility> #include <utility>
namespace matador::sql { namespace matador::sql {
@ -74,6 +75,12 @@ std::string column_definition::str() const
return visitor.result; return visitor.result;
} }
std::ostream& operator<<(std::ostream &out, const column_definition &col)
{
out << col.str();
return out;
}
column_definition make_column(const std::string &name, data_type_t type, utils::field_attributes attr, null_option null_opt) 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}; return {name, type, attr, null_opt};

View File

@ -9,7 +9,7 @@ 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_) + " " + 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,7 +18,7 @@ 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_) + " " + operand + " (");
result += (")"); result += (")");
return result; return result;
} }

View File

@ -8,17 +8,16 @@
namespace matador::sql { namespace matador::sql {
connection::connection(connection_info info, const std::shared_ptr<sql::schema> &repo) connection::connection(connection_info info)
: 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))
, 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<sql::schema> &repo) connection::connection(const std::string& dns)
: connection(connection_info::parse(dns), repo) : connection(connection_info::parse(dns))
{} {}
connection::connection(const connection &x) connection::connection(const connection &x)
@ -90,9 +89,9 @@ size_t connection::execute(const std::string &sql) const
return connection_->execute(sql); return connection_->execute(sql);
} }
sql::query connection::query() const sql::query connection::query(const std::shared_ptr<sql::schema> &schema) const
{ {
return sql::query(*const_cast<connection*>(this)); return sql::query(*const_cast<connection*>(this), schema);
} }
query_result<record> connection::fetch(const query_context &q) const query_result<record> connection::fetch(const query_context &q) const
@ -135,9 +134,4 @@ const class dialect &connection::dialect() const
return dialect_; return dialect_;
} }
std::shared_ptr<schema> connection::schema() const
{
return schema_;
}
} }

View File

@ -1,8 +1,16 @@
#include <utility>
#include "matador/sql/key_value_pair.hpp" #include "matador/sql/key_value_pair.hpp"
namespace matador::sql { namespace matador::sql {
key_value_pair::key_value_pair(const std::string &name, any_type value)
: name_(name) key_value_pair::key_value_pair(std::string name, any_type value)
: name_(std::move(name))
, value_(std::move(value)) {
}
key_value_pair::key_value_pair(const column &col, any_type value)
: name_(col.name)
, value_(std::move(value)) { , value_(std::move(value)) {
} }

View File

@ -3,43 +3,39 @@
namespace matador::sql { namespace matador::sql {
query::query(connection &c) query::query(connection &db, const std::shared_ptr<sql::schema> &schema)
: connection_(c) : connection_(db)
, schema_(schema)
{} {}
query_create_intermediate query::create() query_create_intermediate query::create()
{ {
return query_create_intermediate(connection_); return query_create_intermediate(connection_, schema_);
} }
query_drop_intermediate query::drop() query_drop_intermediate query::drop()
{ {
return query_drop_intermediate{connection_}; return query_drop_intermediate{connection_, schema_};
} }
query_select_intermediate query::select(std::initializer_list<column> columns) query_select_intermediate query::select(std::initializer_list<column> columns)
{ {
return {connection_, columns}; return {connection_, schema_, columns};
} }
query_insert_intermediate query::insert() query_insert_intermediate query::insert()
{ {
return query_insert_intermediate{connection_}; return query_insert_intermediate{connection_, schema_};
} }
query_update_intermediate query::update(const std::string &table) query_update_intermediate query::update(const sql::table &table)
{ {
return query_update_intermediate{connection_, table}; return query_update_intermediate{connection_, schema_, table};
} }
query_delete_intermediate query::remove() query_delete_intermediate query::remove()
{ {
return query_delete_intermediate{connection_}; return query_delete_intermediate{connection_, schema_};
}
const sql::schema& query::schema() const
{
return *connection_.schema();
} }
} }

View File

@ -206,7 +206,7 @@ struct column_context
std::vector<fk_context> foreign_contexts; std::vector<fk_context> foreign_contexts;
}; };
std::string build_create_column(const column_definition &col, const dialect &d, column_context &context); //std::string build_create_column(const column_definition &col, const dialect &d, column_context &context);
query_builder &query_builder::table(const std::string &table, const std::vector<column_definition> &columns) query_builder &query_builder::table(const std::string &table, const std::vector<column_definition> &columns)
{ {
@ -219,18 +219,18 @@ query_builder &query_builder::table(const std::string &table, const std::vector<
column_context context; column_context context;
if (columns.size() < 2) { // if (columns.size() < 2) {
for (const auto &col: columns) { // for (const auto &col: columns) {
result.append(build_create_column(col, dialect_, context)); // result.append(build_create_column(col, dialect_, context));
} // }
} else { // } else {
auto it = columns.begin(); // auto it = columns.begin();
result.append(build_create_column(*it++, dialect_, context)); // result.append(build_create_column(*it++, dialect_, context));
for (; it != columns.end(); ++it) { // for (; it != columns.end(); ++it) {
result.append(", "); // result.append(", ");
result.append(build_create_column(*it, dialect_, context)); // result.append(build_create_column(*it, dialect_, context));
} // }
} // }
if (!context.primary_keys.empty()) { if (!context.primary_keys.empty()) {
result.append(", CONSTRAINT PK_" + table + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")"); result.append(", CONSTRAINT PK_" + table + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")");
@ -491,27 +491,27 @@ 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_definition &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) {
result.append("(" + std::to_string(col.attributes().size()) + ")"); // result.append("(" + std::to_string(col.attributes().size()) + ")");
} // }
if (!col.is_nullable()) { // if (!col.is_nullable()) {
result.append(" NOT NULL"); // result.append(" NOT NULL");
} // }
if (is_constraint_set(col.attributes().options(), utils::constraints::UNIQUE)) { // if (is_constraint_set(col.attributes().options(), utils::constraints::UNIQUE)) {
result.append(" UNIQUE"); // result.append(" UNIQUE");
} // }
if (is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) { // if (is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) {
context.primary_keys.emplace_back(col.name()); // context.primary_keys.emplace_back(col.name());
} // }
if (is_constraint_set(col.attributes().options(), utils::constraints::FOREIGN_KEY)) { // if (is_constraint_set(col.attributes().options(), utils::constraints::FOREIGN_KEY)) {
context.foreign_contexts.push_back({col.name(), col.ref_table(), col.ref_column()}); // context.foreign_contexts.push_back({col.name(), col.ref_table(), col.ref_column()});
} // }
//
return result; // return result;
} //}
column alias(const std::string &column, const std::string &as) column alias(const std::string &column, const std::string &as)
{ {

View File

@ -2,6 +2,9 @@
#include "matador/sql/query_data.hpp" #include "matador/sql/query_data.hpp"
#include "matador/sql/column_definition.hpp" #include "matador/sql/column_definition.hpp"
#include "matador/sql/dialect.hpp" #include "matador/sql/dialect.hpp"
#include "matador/sql/query_builder.hpp"
#include "matador/utils/string.hpp"
namespace matador::sql { namespace matador::sql {
@ -50,6 +53,7 @@ void query_compiler::visit(query_select_part &select_part)
void query_compiler::visit(query_from_part &from_part) void query_compiler::visit(query_from_part &from_part)
{ {
query_.table_name = from_part.table().name;
if (dialect_.default_schema_name().empty()) { if (dialect_.default_schema_name().empty()) {
query_.sql += " " + dialect_.token_at(dialect::token_t::FROM) + query_.sql += " " + dialect_.token_at(dialect::token_t::FROM) +
" " + dialect_.prepare_identifier(from_part.table().name) + " " + dialect_.prepare_identifier(from_part.table().name) +
@ -85,7 +89,7 @@ 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_group_by_part &group_by_part)
{ {
query_.sql += " " + dialect_.token_at(dialect::token_t::GROUP_BY) + " " + dialect_.prepare_identifier(group_by_part.column());
} }
void query_compiler::visit(query_order_by_part &order_by_part) void query_compiler::visit(query_order_by_part &order_by_part)
@ -96,27 +100,85 @@ 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_asc_part &order_by_asc_part)
{ {
query_.sql += " " + dialect_.token_at(dialect::token_t::ASC);
} }
void query_compiler::visit(query_order_by_desc_part &order_by_desc_part) void query_compiler::visit(query_order_by_desc_part &order_by_desc_part)
{ {
query_.sql += " " + dialect_.token_at(dialect::token_t::DESC);
}
void query_compiler::visit(query_offset_part &offset_part)
{
query_.sql += " " + dialect_.token_at(dialect::token_t::OFFSET) + " " + std::to_string(offset_part.offset());
}
void query_compiler::visit(query_limit_part &limit_part)
{
query_.sql += " " + dialect_.token_at(dialect::token_t::LIMIT) + " " + std::to_string(limit_part.limit());
} }
void query_compiler::visit(query_insert_part &insert_part) void query_compiler::visit(query_insert_part &insert_part)
{ {
query_.sql = dialect_.token_at(dialect::token_t::INSERT);
}
void query_compiler::visit(query_into_part &into_part)
{
query_.table_name = into_part.table().name;
query_.sql += " " + dialect_.token_at(dialect::token_t::INTO) +
" " + dialect_.prepare_identifier(into_part.table().name);
std::string result{"("};
if (into_part.columns().size() < 2) {
for (const auto &col: into_part.columns()) {
result.append(dialect_.prepare_identifier(col.name));
}
} else {
auto it = into_part.columns().begin();
result.append(dialect_.prepare_identifier((it++)->name));
for (; it != into_part.columns().end(); ++it) {
result.append(", ");
result.append(dialect_.prepare_identifier(it->name));
}
}
result += (")");
query_.sql += " " + result;
} }
void query_compiler::visit(query_values_part &values_part) void query_compiler::visit(query_values_part &values_part)
{ {
query_.sql += " " + dialect_.token_at(dialect::token_t::VALUES);
detail::any_type_to_string_visitor value_to_string(dialect_, query_);
std::string result{"("};
if (values_part.values().size() < 2) {
for (auto val: values_part.values()) {
std::visit(value_to_string, val);
result.append(value_to_string.result);
}
} else {
auto it = values_part.values().begin();
auto val = *it++;
std::visit(value_to_string, val);
result.append(value_to_string.result);
for (; it != values_part.values().end(); ++it) {
result.append(", ");
val = *it;
std::visit(value_to_string, val);
result.append(value_to_string.result);
}
}
result += (")");
query_.sql += " " + result;
} }
void query_compiler::visit(query_update_part &update_part) void query_compiler::visit(query_update_part &update_part)
{ {
query_.table_name = update_part.table().name;
query_.sql = dialect_.token_at(dialect::token_t::UPDATE) + " " + dialect_.prepare_identifier(update_part.table().name);
} }
void query_compiler::visit(query_delete_part &delete_part) void query_compiler::visit(query_delete_part &delete_part)
@ -126,12 +188,122 @@ void query_compiler::visit(query_delete_part &delete_part)
void query_compiler::visit(query_create_part &create_part) void query_compiler::visit(query_create_part &create_part)
{ {
query_.sql = dialect_.token_at(dialect::token_t::CREATE);
}
struct fk_context
{
std::string column;
std::string ref_table;
std::string ref_column;
};
struct column_context
{
std::vector<std::string> primary_keys;
std::vector<fk_context> foreign_contexts;
};
std::string build_create_column(const column_definition &col, const dialect &d, column_context &context);
void query_compiler::visit(query_create_table_part &create_table_part)
{
query_.sql += " " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(create_table_part.table().name) + " ";
query_.table_name = create_table_part.table().name;
std::string result = "(";
column_context context;
if (create_table_part.columns().size() < 2) {
for (const auto &col: create_table_part.columns()) {
result.append(build_create_column(col, dialect_, context));
}
} else {
auto it = create_table_part.columns().begin();
result.append(build_create_column(*it++, dialect_, context));
for (; it != create_table_part.columns().end(); ++it) {
result.append(", ");
result.append(build_create_column(*it, dialect_, context));
}
}
if (!context.primary_keys.empty()) {
result.append(", CONSTRAINT PK_" + create_table_part.table().name + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")");
}
for (const auto &fk: context.foreign_contexts) {
result += ", CONSTRAINT FK_" + create_table_part.table().name;
result += "_" + fk.column;
result += " FOREIGN KEY (" + fk.column + ")";
result += " REFERENCES " + fk.ref_table + "(" + fk.ref_column + ")";
}
result += ")";
query_.sql += result;
} }
void query_compiler::visit(query_drop_part &drop_part) void query_compiler::visit(query_drop_part &drop_part)
{ {
query_.sql = dialect_.token_at(dialect::token_t::DROP);
}
void query_compiler::visit(query_set_part &set_part)
{
query_.sql += " " + dialect_.token_at(dialect::token_t::SET) + " ";
detail::any_type_to_string_visitor value_to_string(dialect_, query_);
std::string result;
if (set_part.key_values().size() < 2) {
for (const auto &col: set_part.key_values()) {
result.append(dialect_.prepare_identifier(col.name()) + "=");
auto var = col.value();
std::visit(value_to_string, var);
result.append(value_to_string.result);
}
} else {
auto it = set_part.key_values().begin();
result.append(dialect_.prepare_identifier(it->name()) + "=");
auto var = (it++)->value();
std::visit(value_to_string, var);
result.append(value_to_string.result);
for (; it != set_part.key_values().end(); ++it) {
result.append(", ");
result.append(dialect_.prepare_identifier((*it).name()) + "=");
var = it->value();
std::visit(value_to_string, var);
result.append(value_to_string.result);
}
}
query_.sql += result;
}
void query_compiler::visit(query_drop_table_part &drop_table_part)
{
query_.sql += " " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(drop_table_part.table().name);
query_.table_name = drop_table_part.table().name;
}
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());
if (col.attributes().size() > 0) {
result.append("(" + std::to_string(col.attributes().size()) + ")");
}
if (!col.is_nullable()) {
result.append(" NOT NULL");
}
if (is_constraint_set(col.attributes().options(), utils::constraints::UNIQUE)) {
result.append(" UNIQUE");
}
if (is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) {
context.primary_keys.emplace_back(col.name());
}
if (is_constraint_set(col.attributes().options(), utils::constraints::FOREIGN_KEY)) {
context.foreign_contexts.push_back({col.name(), col.ref_table(), col.ref_column()});
}
return result;
} }
} }

View File

@ -4,13 +4,9 @@
#include "matador/sql/condition.hpp" #include "matador/sql/condition.hpp"
namespace matador::sql { namespace matador::sql {
basic_query_intermediate::basic_query_intermediate(connection &db) basic_query_intermediate::basic_query_intermediate(connection &db, const std::shared_ptr<sql::schema> & schema)
: connection_(db) {} : connection_(db)
, schema_(schema) {}
std::shared_ptr<schema> basic_query_intermediate::tables() const
{
return connection_.schema();
}
query_result<record> query_select_finish::fetch_all() query_result<record> query_select_finish::fetch_all()
{ {
@ -42,100 +38,95 @@ statement query_select_finish::prepare()
return connection_.prepare(compiler.compile(&data_)); return connection_.prepare(compiler.compile(&data_));
} }
query_intermediate::query_intermediate(connection &db, query_data &data) query_intermediate::query_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema, query_data &data)
: basic_query_intermediate(db), data_(data) {} : basic_query_intermediate(db, schema), 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_, data_}; data_.parts.push_back(std::make_unique<query_offset_part>(offset));
return {connection_, schema_, data_};
} }
query_limit_intermediate query_offset_intermediate::limit(size_t limit) query_limit_intermediate query_offset_intermediate::limit(size_t limit)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_limit_part>(limit));
return {connection_, schema_, 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_, data_}; data_.parts.push_back(std::make_unique<query_limit_part>(limit));
return {connection_, schema_, 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 column &col)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_order_by_part>(col));
// return {connection_, builder_.order_by(name)}; return {connection_, schema_, data_};
} }
query_order_direction_intermediate query_order_by_intermediate::asc() query_order_direction_intermediate query_order_by_intermediate::asc()
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_order_by_asc_part>());
// return {connection_, builder_.asc()}; return {connection_, schema_, data_};
} }
query_order_direction_intermediate query_order_by_intermediate::desc() query_order_direction_intermediate query_order_by_intermediate::desc()
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_order_by_asc_part>());
// return {connection_, builder_.desc()}; return {connection_, schema_, data_};
} }
query_group_by_intermediate query_from_intermediate::group_by(const std::string &name) query_group_by_intermediate query_from_intermediate::group_by(const column &col)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_group_by_part>(col));
// return {connection_, builder_.group_by(name)}; return {connection_, schema_, data_};
} }
query_order_by_intermediate query_from_intermediate::order_by(const std::string &name) query_order_by_intermediate query_from_intermediate::order_by(const column &col)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_order_by_part>(col));
// return {connection_, builder_.order_by(name)}; return {connection_, schema_, data_};
} }
query_group_by_intermediate query_where_intermediate::group_by(const std::string &name) query_group_by_intermediate query_where_intermediate::group_by(const column &col)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_group_by_part>(col));
// return {connection_, builder_.group_by(name)}; return {connection_, schema_, data_};
} }
query_order_by_intermediate query_where_intermediate::order_by(const column &col) query_order_by_intermediate query_where_intermediate::order_by(const column &col)
{ {
data_.parts.push_back(std::make_unique<query_order_by_part>(col)); data_.parts.push_back(std::make_unique<query_order_by_part>(col));
return {connection_, data_}; return {connection_, schema_, 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_left(const table &t)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_join_part>(t));
// return {connection_, builder_.join(join_table_name, join_type_t::INNER, as)}; return {connection_, schema_, data_};
} }
query_group_by_intermediate query_on_intermediate::group_by(const std::string &name) query_group_by_intermediate query_on_intermediate::group_by(const column &col)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_group_by_part>(col));
// return {connection_, builder_.group_by(name)}; return {connection_, schema_, data_};
} }
query_order_by_intermediate query_on_intermediate::order_by(const column &col) query_order_by_intermediate query_on_intermediate::order_by(const column &col)
{ {
data_.parts.push_back(std::make_unique<query_order_by_part>(col)); data_.parts.push_back(std::make_unique<query_order_by_part>(col));
return {connection_, data_}; return {connection_, schema_, data_};
// return {connection_, builder_.order_by(name)};
} }
query_join_intermediate query_from_intermediate::join_left(const table &t) query_join_intermediate query_from_intermediate::join_left(const table &t)
{ {
data_.parts.push_back(std::make_unique<query_join_part>(t)); data_.parts.push_back(std::make_unique<query_join_part>(t));
return {connection_, data_}; return {connection_, schema_, data_};
} }
query_where_intermediate query_from_intermediate::where(const basic_condition &cond) query_select_intermediate::query_select_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema, const std::vector<column>& columns)
{ : query_start_intermediate(db, schema)
return query_where_intermediate{connection_, data_};
// return query_where_intermediate{connection_, builder_.where(cond)};
}
query_select_intermediate::query_select_intermediate(connection &db, const std::vector<column>& columns)
: query_start_intermediate(db)
{ {
data_.parts.push_back(std::make_unique<query_select_part>(columns)); data_.parts.push_back(std::make_unique<query_select_part>(columns));
} }
@ -143,20 +134,19 @@ query_select_intermediate::query_select_intermediate(connection &db, const std::
query_from_intermediate query_select_intermediate::from(const table& t) query_from_intermediate query_select_intermediate::from(const table& t)
{ {
data_.parts.push_back(std::make_unique<query_from_part>(t)); data_.parts.push_back(std::make_unique<query_from_part>(t));
return {connection_, data_}; return {connection_, schema_, data_};
// return {connection_, builder_.from(table, as)};
} }
query_insert_intermediate::query_insert_intermediate(connection &s) query_insert_intermediate::query_insert_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema)
: query_start_intermediate(s) : query_start_intermediate(db, schema)
{ {
data_.parts.push_back(std::make_unique<query_insert_part>()); 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> column_names) query_into_intermediate query_insert_intermediate::into(const sql::table &table, std::initializer_list<column> column_names)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_into_part>(table, column_names));
// return {connection_, builder_.into(table, column_names)}; return {connection_, schema_, data_};
} }
size_t query_execute_finish::execute() size_t query_execute_finish::execute()
@ -171,6 +161,12 @@ statement query_execute_finish::prepare()
return connection_.prepare(compiler.compile(&data_)); return connection_.prepare(compiler.compile(&data_));
} }
std::string query_execute_finish::str() const
{
query_compiler compiler(connection_.dialect());
return compiler.compile(&data_).sql;
}
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 this->values(std::vector<any_type>(values)); return this->values(std::vector<any_type>(values));
@ -178,80 +174,68 @@ query_execute_finish query_into_intermediate::values(std::initializer_list<any_t
query_execute_finish query_into_intermediate::values(const std::vector<any_type> &values) query_execute_finish query_into_intermediate::values(const std::vector<any_type> &values)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_values_part>(values));
return {connection_, schema_, data_};
} }
query_create_intermediate::query_create_intermediate(connection &db) query_create_intermediate::query_create_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema)
: query_start_intermediate(db) { : query_start_intermediate(db, schema) {
data_.parts.push_back(std::make_unique<query_create_part>()); 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_definition> columns) query_execute_finish query_create_intermediate::table(const sql::table &table, std::initializer_list<column_definition> columns)
{ {
return table(table_name, std::vector<column_definition>{columns}); return this->table(table, std::vector<column_definition>{columns});
} }
query_execute_finish query_create_intermediate::table(const std::string &table_name, const std::vector<column_definition> &columns) query_execute_finish query_create_intermediate::table(const sql::table &table, const std::vector<column_definition> &columns)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_create_table_part>(table, columns));
// return {connection_, builder_.table(table_name, columns)}; return {connection_, schema_, data_};
} }
query_drop_intermediate::query_drop_intermediate(connection &s) query_drop_intermediate::query_drop_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema)
: query_start_intermediate(s) : query_start_intermediate(db, schema)
{ {
data_.parts.push_back(std::make_unique<query_drop_part>()); 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 sql::table &table)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_drop_table_part>(table));
// return {connection_, builder_.table(table)}; return {connection_, schema_, data_};
} }
query_execute_finish query_execute_where_intermediate::limit(int limit) query_execute_finish query_execute_where_intermediate::limit(int limit)
{ {
return {connection_, data_}; return {connection_, schema_, data_};
// return {connection_, builder_.limit(limit)}; // return {connection_, builder_.limit(limit)};
} }
query_execute_where_intermediate query_set_intermediate::where(const basic_condition &cond) query_update_intermediate::query_update_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema, const sql::table& table)
: query_start_intermediate(db, schema)
{ {
return {connection_, data_}; data_.parts.push_back(std::make_unique<query_update_part>(table));
// return {connection_, builder_.where(cond)};
}
query_update_intermediate::query_update_intermediate(connection &s, const std::string& table_name)
: query_start_intermediate(s)
{
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_, data_}; data_.parts.push_back(std::make_unique<query_set_part>(columns));
// return {connection_, builder_.set(columns)}; return {connection_, schema_, data_};
} }
query_execute_where_intermediate query_delete_from_intermediate::where(const basic_condition &cond) query_delete_intermediate::query_delete_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema)
{ : query_start_intermediate(db, schema)
return {connection_, data_};
// return {connection_, builder_.where(cond)};
}
query_delete_intermediate::query_delete_intermediate(connection &s)
: query_start_intermediate(s)
{ {
data_.parts.push_back(std::make_unique<query_delete_part>()); 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 sql::table &table)
{ {
return {connection_, data_}; return {connection_, schema_, data_};
// return {connection_, builder_.from(table)};
} }
query_start_intermediate::query_start_intermediate(connection &db) query_start_intermediate::query_start_intermediate(connection &db, const std::shared_ptr<sql::schema> &schema)
: basic_query_intermediate(db) : basic_query_intermediate(db, schema)
{} {}
} }

View File

@ -74,10 +74,16 @@ query_table_name_part::query_table_name_part(sql::dialect::token_t token, std::s
: query_part(token) : query_part(token)
, table_name_(std::move(table_name)) {} , table_name_(std::move(table_name)) {}
query_group_by_part::query_group_by_part(const std::string &table_name) query_group_by_part::query_group_by_part(sql::column col)
: query_table_name_part(dialect::token_t::GROUP_BY, table_name) : query_part(dialect::token_t::GROUP_BY)
, column_(std::move(col))
{} {}
const sql::column &query_group_by_part::column() const
{
return column_;
}
void query_group_by_part::accept(query_part_visitor &visitor) void query_group_by_part::accept(query_part_visitor &visitor)
{ {
visitor.visit(*this); visitor.visit(*this);
@ -116,6 +122,34 @@ void query_order_by_desc_part::accept(query_part_visitor &visitor)
visitor.visit(*this); visitor.visit(*this);
} }
query_offset_part::query_offset_part(size_t offset)
: query_part(dialect::token_t::OFFSET)
, offset_(offset) {}
size_t query_offset_part::offset() const
{
return offset_;
}
void query_offset_part::accept(query_part_visitor &visitor)
{
visitor.visit(*this);
}
query_limit_part::query_limit_part(size_t limit)
: query_part(dialect::token_t::LIMIT)
, limit_(limit) {}
size_t query_limit_part::limit() const
{
return limit_;
}
void query_limit_part::accept(query_part_visitor &visitor)
{
visitor.visit(*this);
}
query_insert_part::query_insert_part() query_insert_part::query_insert_part()
: query_part(dialect::token_t::INSERT) {} : query_part(dialect::token_t::INSERT) {}
@ -124,23 +158,68 @@ void query_insert_part::accept(query_part_visitor &visitor)
visitor.visit(*this); visitor.visit(*this);
} }
query_values_part::query_values_part(std::initializer_list<any_type> values) query_into_part::query_into_part(sql::table t, std::vector<sql::column> columns)
: query_part(dialect::token_t::INSERT)
, table_(std::move(t))
, columns_(std::move(columns)) {}
const sql::table &query_into_part::table() const
{
return table_;
}
const std::vector<column> &query_into_part::columns() const
{
return columns_;
}
void query_into_part::accept(query_part_visitor &visitor)
{
visitor.visit(*this);
}
query_values_part::query_values_part(std::vector<any_type> values)
: query_part(sql::dialect::token_t::VALUES) : query_part(sql::dialect::token_t::VALUES)
, values_(values) {} , values_(std::move(values)) {}
const std::vector<any_type>& query_values_part::values() const
{
return values_;
}
void query_values_part::accept(query_part_visitor &visitor) void query_values_part::accept(query_part_visitor &visitor)
{ {
visitor.visit(*this); visitor.visit(*this);
} }
query_update_part::query_update_part(const std::string &table_name) query_update_part::query_update_part(sql::table table)
: query_table_name_part(dialect::token_t::UPDATE, table_name) {} : query_part(dialect::token_t::UPDATE)
, table_(std::move(table)) {}
const sql::table& query_update_part::table() const
{
return table_;
}
void query_update_part::accept(query_part_visitor &visitor) void query_update_part::accept(query_part_visitor &visitor)
{ {
visitor.visit(*this); visitor.visit(*this);
} }
query_set_part::query_set_part(const std::vector<sql::key_value_pair>& key_value_pairs)
: query_part(sql::dialect::token_t::SET)
, key_value_pairs_(key_value_pairs) {}
const std::vector<sql::key_value_pair> &query_set_part::key_values() const
{
return key_value_pairs_;
}
void query_set_part::accept(query_part_visitor &visitor)
{
visitor.visit(*this);
}
query_delete_part::query_delete_part() query_delete_part::query_delete_part()
: query_part(sql::dialect::token_t::REMOVE) {} : query_part(sql::dialect::token_t::REMOVE) {}
@ -157,6 +236,26 @@ void query_create_part::accept(query_part_visitor &visitor)
visitor.visit(*this); visitor.visit(*this);
} }
query_create_table_part::query_create_table_part(sql::table table, std::vector<sql::column_definition> columns)
: query_part(sql::dialect::token_t::TABLE)
, table_(std::move(table))
, columns_(std::move(columns)) {}
const sql::table &query_create_table_part::table() const
{
return table_;
}
const std::vector<sql::column_definition> &query_create_table_part::columns() const
{
return columns_;
}
void query_create_table_part::accept(query_part_visitor &visitor)
{
visitor.visit(*this);
}
query_drop_part::query_drop_part() query_drop_part::query_drop_part()
: query_part(sql::dialect::token_t::DROP) {} : query_part(sql::dialect::token_t::DROP) {}
@ -165,4 +264,18 @@ void query_drop_part::accept(query_part_visitor &visitor)
visitor.visit(*this); visitor.visit(*this);
} }
query_drop_table_part::query_drop_table_part(sql::table table)
: query_part(sql::dialect::token_t::TABLE)
, table_(std::move(table)) {}
const sql::table &query_drop_table_part::table() const
{
return table_;
}
void query_drop_table_part::accept(query_part_visitor &visitor)
{
visitor.visit(*this);
}
} }

View File

@ -1,4 +1,5 @@
#include "matador/sql/record.hpp" #include "matador/sql/record.hpp"
#include "matador/sql/column.hpp"
#include <algorithm> #include <algorithm>
#include <stdexcept> #include <stdexcept>
@ -60,12 +61,18 @@ const column_definition &record::primary_key() const
return columns_[pk_index_]; return columns_[pk_index_];
} }
const column_definition &record::at(const std::string &name) const const column_definition &record::at(const column &col) const
{ {
auto ref = columns_by_name_.at(name).first; auto ref = columns_by_name_.at(col.name).first;
return columns_by_name_.at(name).first; return columns_by_name_.at(col.name).first;
} }
//const column_definition &record::at(const std::string &name) const
//{
// auto ref = columns_by_name_.at(name).first;
// return columns_by_name_.at(name).first;
//}
const column_definition &record::at(size_t index) const const column_definition &record::at(size_t index) const
{ {
return columns_.at(index); return columns_.at(index);

View File

@ -7,14 +7,17 @@ namespace matador::sql {
void table_info::create(connection &conn) const void table_info::create(connection &conn) const
{ {
conn.query().create().table(name, prototype.columns()).execute(); // conn.query().create().table(name, prototype.columns()).execute();
} }
void table_info::drop(connection &conn) const void table_info::drop(connection &conn) const
{ {
conn.query().drop().table(name).execute(); // conn.query().drop().table(name).execute();
} }
schema::schema(std::string name)
: name_(std::move(name)) {}
std::string schema::name() const std::string schema::name() const
{ {
return name_; return name_;

View File

@ -8,12 +8,13 @@ namespace matador::sql {
session::session(connection_pool<connection> &pool) session::session(connection_pool<connection> &pool)
: pool_(pool) : pool_(pool)
, dialect_(backend_provider::instance().connection_dialect(pool_.info().type)) {} , dialect_(backend_provider::instance().connection_dialect(pool_.info().type))
, schema_(std::make_shared<sql::schema>(dialect_.default_schema_name())){}
void session::create_schema() void session::create_schema()
{ {
auto c = pool_.acquire(); auto c = pool_.acquire();
for (const auto &t : schema_) { for (const auto &t : *schema_) {
t.second.create(*c); t.second.create(*c);
} }
} }
@ -25,7 +26,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->query().drop().table(table_name).execute(); c->query(schema_).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
@ -90,7 +91,7 @@ bool session::table_exists(const std::string &table_name) const
const schema& session::tables() const const schema& session::tables() const
{ {
return schema_; return *schema_;
} }
const class dialect &session::dialect() const const class dialect &session::dialect() const

View File

@ -10,7 +10,7 @@ using namespace matador::sql;
using namespace matador::utils; using namespace matador::utils;
TEST_CASE("Generate columns from object", "[column generator]") { TEST_CASE("Generate columns from object", "[column generator]") {
schema repo; schema repo("main");
auto columns = column_generator::generate<matador::test::product>(repo); auto columns = column_generator::generate<matador::test::product>(repo);
@ -36,7 +36,7 @@ TEST_CASE("Generate columns from object", "[column generator]") {
} }
TEST_CASE("Generate columns from object with nullable columns", "[column generator]") { TEST_CASE("Generate columns from object with nullable columns", "[column generator]") {
schema repo; schema repo("main");
auto columns = column_generator::generate<matador::test::optional>(repo); auto columns = column_generator::generate<matador::test::optional>(repo);

View File

@ -9,7 +9,7 @@
using namespace matador::sql; using namespace matador::sql;
TEST_CASE("Generate column names from object", "[column name generator]") { TEST_CASE("Generate column names from object", "[column name generator]") {
schema s; schema s("main");
s.attach<matador::test::product>("product"); s.attach<matador::test::product>("product");
auto columns = column_name_generator::generate<matador::test::product>(s); auto columns = column_name_generator::generate<matador::test::product>(s);
@ -34,7 +34,7 @@ TEST_CASE("Generate column names from object", "[column name generator]") {
} }
TEST_CASE("Generate column names for object with has many relation", "[column][relation]") { TEST_CASE("Generate column names for object with has many relation", "[column][relation]") {
schema s; schema s("main");
s.attach<matador::test::product>("product"); s.attach<matador::test::product>("product");
s.attach<matador::test::order_details>("order_details"); s.attach<matador::test::order_details>("order_details");
s.attach<matador::test::order>("order"); s.attach<matador::test::order>("order");