-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontext.cpp
More file actions
130 lines (110 loc) · 4.55 KB
/
context.cpp
File metadata and controls
130 lines (110 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include "context.hpp"
using namespace std;
namespace x3 = boost::spirit::x3;
namespace SQL_Compiler {
/*
* Relation
*/
Relation::Relation(vector<string> const& names, string const& name, int shift) : m_name(name) {
for (int att = 0; att < (int)names.size(); ++att) {
attributes[names[att]] = att + shift;
}
}
int Relation::operator[](string const& attribute) const {
if (attributes.count(attribute) > 0)
return attributes.at(attribute);
throw SemanticError(attribute + " is not an attribute of " + name());
}
string const& Relation::name() const {
return m_name;
}
int Relation::nb_attributes() const {
return attributes.size();
}
/*
* Context
*/
void Context::add_relation(Relation const& r) {
if (relations.count(r.name()) > 0)
throw SemanticError(r.name() + " is already the name of an existing relation");
relations.insert({r.name(), r});
}
Relation const& Context::operator[](string const& name) const {
if (relations.count(name) == 0)
throw SemanticError(name + " is not the name of a relation");
return relations.at(name);
}
namespace {
class GetAttributeNames : public boost::static_visitor<vector<std::string>> {
public:
vector<std::string> operator()(SQL_AST::minus_op const& minus_op) {
auto left = boost::apply_visitor(*this, minus_op.left_);
auto right = boost::apply_visitor(*this, minus_op.right_);
if (left != right)
throw SemanticError("Attribute names of an UNION must be the same");
return left;
}
vector<std::string> operator()(SQL_AST::union_op const& union_op) {
auto left = boost::apply_visitor(*this, union_op.left_);
auto right = boost::apply_visitor(*this, union_op.right_);
if (left != right)
throw SemanticError("Attribute names of a MINUS must be the same");
return left;
}
vector<std::string> operator()(SQL_AST::select const& select) {
vector<std::string> names;
for (auto& project : select.projections_) {
if (project.rename_) {
names.push_back(project.rename_.value());
} else {
names.push_back(project.attribute_.column_);
}
}
return names;
}
};
}
vector<string> get_attributes_names(SQL_AST::query const& q) {
GetAttributeNames getter;
return boost::apply_visitor(getter, q);
}
vector<string> get_attributes_names(std::string const& filename) {
vector<std::string> names;
ifstream file(filename);
if (!file)
throw SemanticError("fail to open "+filename);
boost::spirit::istream_iterator iter(file >> noskipws), eof;
auto const parser = (+(x3::ascii::alnum)) % (*("," | x3::ascii::blank));
x3::parse(iter, eof, parser, names);
return names;
}
vector<string> get_attributes_names(SQL_AST::from_relation const& from_rel) {
if (auto subquery_ptr = boost::get<SQL_AST::subquery>(&from_rel)) {
auto const& subquery = *subquery_ptr;
return get_attributes_names(subquery.query_);
} else if (auto load_file_ptr = boost::get<SQL_AST::load_file>(&from_rel)) {
auto const& load_file = *load_file_ptr;
return get_attributes_names(load_file.filename_);
} else {
throw runtime_error("[context.cpp][get_attributes_names] Critical Error");
}
}
string get_alias(SQL_AST::from_relation const& rel) {
return boost::apply_visitor([](auto const& rel) -> string { return rel.alias_;}, rel);
}
void extend_from(Context& ctx, SQL_AST::cartesian_product const& relations) {
int shift = 0;
for (auto const& sql_relation : relations) {
Relation relation = build_relation(sql_relation, shift);
ctx.add_relation(relation);
shift += relation.nb_attributes();
}
}
Relation build_relation(SQL_AST::from_relation const& sql_relation, int shift) {
auto alias = get_alias(sql_relation);
auto names = get_attributes_names(sql_relation);
return Relation(names, alias, shift);
}
}