forked from neumannt/saneql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
109 lines (105 loc) · 3.2 KB
/
main.cpp
File metadata and controls
109 lines (105 loc) · 3.2 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
#include "algebra/Operator.hpp"
#include "infra/Schema.hpp"
#include "parser/ASTBase.hpp"
#include "parser/SaneQLLexer.hpp"
#include "parser/SaneQLParser.hpp"
#include "semana/SemanticAnalysis.hpp"
#include "sql/SQLWriter.hpp"
#include <fstream>
#include <iostream>
#include <sstream>
//---------------------------------------------------------------------------
using namespace std;
using namespace saneql;
//---------------------------------------------------------------------------
// (c) 2023 Thomas Neumann
//---------------------------------------------------------------------------
static string readFiles(unsigned count, char* files[]) {
ostringstream output;
for (unsigned i = 0; i != count; i++) {
ifstream in(files[i]);
if (!in.is_open()) {
cerr << "unable to read " << files[i] << endl;
exit(1);
}
output << in.rdbuf();
output << "\n";
}
return output.str();
}
//---------------------------------------------------------------------------
int main(int argc, char* argv[]) {
if (argc < 2) {
cerr << "usage: " << argv[0] << " file..." << endl;
return 1;
}
Schema schema;
schema.populateSchema();
string query = readFiles(argc - 1, argv + 1);
ASTContainer container;
ast::AST* tree = nullptr;
try {
tree = SaneQLParser::parse(container, query);
} catch (const exception& e) {
cerr << e.what() << endl;
return 1;
}
SemanticAnalysis semana(schema);
try {
auto res = semana.analyzeQuery(tree);
SQLWriter sql;
if (res.isScalar()) {
sql.write("select ");
res.scalar()->generate(sql);
} else {
algebra::Sort* sort = nullptr;
auto tree = res.table().get();
if (auto s = dynamic_cast<algebra::Sort*>(tree)) {
sort = s;
tree = sort->input.get();
}
sql.write("select ");
bool first = true;
for (auto& c : res.getBinding().getColumns()) {
if (first)
first = false;
else
sql.write(", ");
sql.writeIU(c.iu);
sql.write(" as ");
sql.writeIdentifier(c.name);
}
sql.write(" from ");
tree->generate(sql);
sql.write(" s");
if (sort) {
if (!sort->order.empty()) {
sql.write(" order by ");
bool first = true;
for (auto& o : sort->order) {
if (first)
first = false;
else
sql.write(", ");
o.value->generate(sql);
if (o.collate != Collate{}) sql.write(" collate TODO"); // TODO
if (o.descending) sql.write(" desc");
}
}
if (sort->limit.has_value()) {
sql.write(" limit ");
sql.write(to_string(*(sort->limit)));
}
if (sort->offset.has_value()) {
sql.write(" offset ");
sql.write(to_string(*(sort->offset)));
}
}
}
cout << sql.getResult() << endl;
} catch (const exception& e) {
cerr << e.what() << endl;
return 1;
}
return 0;
}