1#include <vkdb/interpreter.h>
2#include <vkdb/database.h>
6 : token_{token}, message_{message} {}
17 : database_{database}, callback_{callback} {}
24 auto results{visit(expr)};
25 for (
const auto& result : results) {
26 if (result.has_value()) {
27 stream << to_string(result.value()) <<
'\n';
35std::string Interpreter::to_string(
const OutputResult& result)
const {
36 return std::visit([
this](
auto&& result) -> std::string {
37 using R = std::decay_t<
decltype(result)>;
38 if constexpr (std::is_same_v<R, SelectResult>) {
39 return to_string(result);
40 }
else if constexpr (std::is_same_v<R, TablesResult>) {
41 return to_string(result);
46std::string Interpreter::to_string(
const SelectResult& result)
const {
47 return std::visit([
this](
auto&& result) -> std::string {
48 using R = std::decay_t<
decltype(result)>;
49 if constexpr (std::is_same_v<R, SelectDataResult>) {
50 return datapointsToString<double>(result);
51 }
else if constexpr (std::is_same_v<R, SelectDoubleResult>) {
52 return std::to_string(result);
53 }
else if constexpr (std::is_same_v<R, SelectCountResult>) {
54 return std::to_string(result);
59std::string Interpreter::to_string(
const TablesResult& result)
const {
60 std::string tables_result{};
62 for (
const auto& table_name : result) {
66 tables_result += table_name;
72Results Interpreter::visit(
const Expr& expr)
const {
75 for (
const auto& query : expr) {
76 results.push_back(visit(query));
79 }
catch (
const RuntimeError& e) {
84Result Interpreter::visit(
const Query& query)
const {
86 return std::visit([
this](
auto&& query) -> Result {
87 using Q = std::decay_t<
decltype(query)>;
88 if constexpr (std::is_same_v<Q, SelectQuery>) {
90 }
else if constexpr (std::is_same_v<Q, PutQuery>) {
93 }
else if constexpr (std::is_same_v<Q, DeleteQuery>) {
96 }
else if constexpr (std::is_same_v<Q, CreateQuery>) {
99 }
else if constexpr (std::is_same_v<Q, DropQuery>) {
102 }
else if constexpr (std::is_same_v<Q, AddQuery>) {
105 }
else if constexpr (std::is_same_v<Q, RemoveQuery>) {
108 }
else if constexpr (std::is_same_v<Q, TablesQuery>) {
112 }
catch (
const RuntimeError& e) {
117void Interpreter::add_optional_tag_list(
118 FriendlyQueryBuilder<double> &query_builder,
119 const std::optional<TagListExprResult>& tag_list
121 if (tag_list.has_value()) {
122 for (
const auto& [key, value] : tag_list.value()) {
123 std::ignore = query_builder.whereTagsContain({key, value});
128SelectResult Interpreter::handle_select_type(
129 FriendlyQueryBuilder<double> &query_builder,
132 return std::visit([&query_builder](
auto&& type) -> SelectResult {
133 using T = std::decay_t<
decltype(type)>;
135 if constexpr (std::is_same_v<T, SelectTypeDataExpr>) {
136 return query_builder.execute();
137 }
else if constexpr (std::is_same_v<T, SelectTypeCountExpr>) {
138 return query_builder.count();
139 }
else if constexpr (std::is_same_v<T, SelectTypeAvgExpr>) {
140 return query_builder.avg();
141 }
else if constexpr (std::is_same_v<T, SelectTypeSumExpr>) {
142 return query_builder.sum();
143 }
else if constexpr (std::is_same_v<T, SelectTypeMinExpr>) {
144 return query_builder.min();
145 }
else if constexpr (std::is_same_v<T, SelectTypeMaxExpr>) {
146 return query_builder.max();
148 }
catch (
const std::exception& e) {
149 throw RuntimeError{type.token, e.what()};
154SelectResult Interpreter::visit(
const SelectQuery& query)
const {
156 auto type_result{visit(query.type)};
157 auto metric_result{visit(query.metric)};
158 auto table_name_result{visit(query.table_name)};
159 auto& table{database_.
getTable(table_name_result)};
160 auto query_builder{table.query()
161 .whereMetricIs(metric_result)
163 std::visit([
this, &query_builder](
auto&& select_clause) ->
void {
164 using C = std::decay_t<
decltype(select_clause)>;
165 if constexpr (std::is_same_v<C, AllClause>) {
166 auto all_clause_result{visit(select_clause)};
167 add_optional_tag_list(query_builder, all_clause_result);
168 }
else if constexpr (std::is_same_v<C, BetweenClause>) {
169 auto between_clause_result{visit(select_clause)};
170 std::ignore = query_builder.whereTimestampBetween(
171 std::get<0>(between_clause_result),
172 std::get<1>(between_clause_result)
174 add_optional_tag_list(
176 std::get<2>(between_clause_result)
178 }
else if constexpr (std::is_same_v<C, AtClause>) {
179 auto at_clause_result{visit(select_clause)};
180 std::ignore = query_builder.whereTimestampIs(at_clause_result.first);
181 add_optional_tag_list(query_builder, at_clause_result.second);
184 return handle_select_type(query_builder, type_result);
185 }
catch (
const RuntimeError& e) {
190PutResult Interpreter::visit(
const PutQuery& query)
const {
192 auto metric_result{visit(query.metric)};
193 auto timestamp_result{visit(query.timestamp)};
194 auto value_result{visit(query.value)};
195 auto table_name_result{visit(query.table_name)};
197 auto& table{database_.
getTable(table_name_result)};
198 if (!query.tag_list.has_value()) {
200 .put(timestamp_result, metric_result, {}, value_result)
204 auto tag_list_result{visit(query.tag_list.value())};
206 .put(timestamp_result, metric_result, tag_list_result, value_result)
208 }
catch (
const std::exception& e) {
209 throw RuntimeError{query.metric.token, e.what()};
213DeleteResult Interpreter::visit(
const DeleteQuery& query)
const {
215 auto metric_result{visit(query.metric)};
216 auto timestamp_result{visit(query.timestamp)};
217 auto table_name_result{visit(query.table_name)};
219 auto& table{database_.
getTable(table_name_result)};
220 if (!query.tag_list.has_value()) {
222 .remove(timestamp_result, metric_result, {})
225 auto tag_list_result{visit(query.tag_list.value())};
227 .remove(timestamp_result, metric_result, tag_list_result)
229 }
catch (
const std::exception& e) {
230 throw RuntimeError{query.metric.token, e.what()};
234CreateResult Interpreter::visit(
const CreateQuery& query)
const {
236 auto table_name_result{visit(query.table_name)};
238 if (query.tag_columns.has_value()) {
239 auto tag_columns_result{visit(query.tag_columns.value())};
244 }
catch (
const std::exception& e) {
245 throw RuntimeError{query.table_name.token, e.what()};
249DropResult Interpreter::visit(
const DropQuery& query)
const {
251 auto table_name_result{visit(query.table_name)};
253 }
catch (
const std::exception& e) {
254 throw RuntimeError{query.table_name.token, e.what()};
258AddResult Interpreter::visit(
const AddQuery& query)
const {
260 auto tag_columns_result{visit(query.tag_columns)};
261 auto table_name_result{visit(query.table_name)};
262 auto& table{database_.
getTable(table_name_result)};
263 for (
const auto& tag_key : tag_columns_result) {
264 table.addTagColumn(tag_key);
266 }
catch (
const std::exception& e) {
267 throw RuntimeError{query.table_name.token, e.what()};
271RemoveResult Interpreter::visit(
const RemoveQuery& query)
const {
273 auto tag_columns_result{visit(query.tag_columns)};
274 auto table_name_result{visit(query.table_name)};
275 auto& table{database_.
getTable(table_name_result)};
276 for (
const auto& tag_key : tag_columns_result) {
277 table.removeTagColumn(tag_key);
279 }
catch (
const std::exception& e) {
280 throw RuntimeError{query.table_name.token, e.what()};
284TablesResult Interpreter::visit(
const TablesQuery& query)
const {
286 TablesResult tables_result{};
287 for (
const auto& table_name : database_.
tables()) {
288 tables_result.push_back(table_name);
290 return tables_result;
291 }
catch (
const std::exception& e) {
292 throw RuntimeError{query.token, e.what()};
296AllClauseResult Interpreter::visit(
const AllClause& clause)
const {
297 AllClauseResult all_clause_result{};
298 if (clause.where_clause.has_value()) {
299 all_clause_result = visit(clause.where_clause.value());
301 return all_clause_result;
304BetweenClauseResult Interpreter::visit(
const BetweenClause& clause)
const {
305 BetweenClauseResult between_clause_result{};
307 std::get<0>(between_clause_result) = visit(clause.start);
308 std::get<1>(between_clause_result) = visit(clause.end);
309 if (clause.where_clause.has_value()) {
310 std::get<2>(between_clause_result) = visit(clause.where_clause.value());
312 return between_clause_result;
313 }
catch (
const std::exception& e) {
314 throw RuntimeError{clause.start.token, e.what()};
318AtClauseResult Interpreter::visit(
const AtClause& clause)
const {
319 AtClauseResult at_clause_result{};
321 at_clause_result.first = visit(clause.timestamp);
322 if (clause.where_clause.has_value()) {
323 at_clause_result.second = visit(clause.where_clause.value());
325 return at_clause_result;
326 }
catch (
const std::exception& e) {
327 throw RuntimeError{clause.timestamp.token, e.what()};
331WhereClauseResult Interpreter::visit(
const WhereClause& clause)
const {
332 return visit(clause.tag_list);
335SelectTypeResult Interpreter::visit(
const SelectType& type)
const noexcept {
339MetricExprResult Interpreter::visit(
const MetricExpr& metric)
const noexcept {
340 return metric.token.lexeme();
343TableNameExprResult Interpreter::visit(
344 const TableNameExpr& table_name
346 return table_name.token.lexeme();
349TagKeyExprResult Interpreter::visit(
const TagKeyExpr& tag_key)
const noexcept {
350 return tag_key.token.lexeme();
353TagValueExprResult Interpreter::visit(
354 const TagValueExpr& tag_value
356 return tag_value.token.lexeme();
359TagExprResult Interpreter::visit(
const TagExpr& tag)
const noexcept {
360 auto tag_key_result{visit(tag.key)};
361 auto tag_value_result{visit(tag.value)};
362 return {tag_key_result, tag_value_result};
365TagListExprResult Interpreter::visit(
const TagListExpr& tag_list)
const {
366 TagListExprResult tag_list_result;
367 for (
const auto& tag : tag_list.tags) {
368 tag_list_result.emplace(visit(tag));
370 return tag_list_result;
373TagColumnsExprResult Interpreter::visit(
374 const TagColumnsExpr& tag_columns
376 TagColumnsExprResult tag_columns_result;
377 for (
const auto& tag_key : tag_columns.keys) {
378 tag_columns_result.emplace(visit(tag_key));
380 return tag_columns_result;
383TimestampExprResult Interpreter::visit(
const TimestampExpr& timestamp)
const {
385 return std::stoull(timestamp.token.lexeme());
386 }
catch (
const std::exception& e) {
387 throw RuntimeError{timestamp.token,
"Invalid timestamp."};
391ValueExprResult Interpreter::visit(
const ValueExpr& value)
const {
393 return std::stod(value.token.lexeme());
394 }
catch (
const std::exception& e) {
395 throw RuntimeError{value.token,
"Invalid value."};
Represents a database in vkdb.
Table & getTable(const TableName &table_name)
Get the Table object.
std::vector< TableName > tables() const noexcept
Get the names of the tables in the database.
void dropTable(const TableName &table_name)
Drop the Table object.
Table & createTable(const TableName &table_name)
Create a Table object.
void interpret(const Expr &expr, std::ostream &stream=std::cout) const noexcept
Interpret the expression.
Interpreter(Database &database, error_callback callback=[](const RuntimeError &) {}) noexcept
Construct a new Interpreter object.
Token token() const noexcept
Get the token.
std::string message() const noexcept
Get the message.
RuntimeError(Token token, const std::string &message) noexcept
Construct a new Runtime Error object.
Table & setTagColumns(const TagColumns &tag_columns) noexcept
Set the TagColumns object.