dbms: implementation of temporal conditions [#METR-16058]

This commit is contained in:
Andrey Mironov 2015-04-30 14:45:14 +03:00
parent 27ebf02a8d
commit 64dc50dfa4

View File

@ -223,25 +223,43 @@ private:
SpecificEvent, SpecificEvent,
AnyEvent, AnyEvent,
KleeneStar, KleeneStar,
TimeLess,
TimeLessOrEqual, TimeLessOrEqual,
TimeLess,
TimeGreaterOrEqual, TimeGreaterOrEqual,
TimeGreater TimeGreater
}; };
struct PatternAction static std::string to_string(const PatternActionType type)
{
static const std::map<PatternActionType, std::string> map{
{ PatternActionType::SpecificEvent, "SpecificEvent" },
{ PatternActionType::AnyEvent, "AnyEvent" },
{ PatternActionType::KleeneStar, "KleeneStar" },
{ PatternActionType::TimeLessOrEqual, "TimeLessOrEqual" },
{ PatternActionType::TimeLess, "TimeLess", },
{ PatternActionType::TimeGreaterOrEqual, "TimeGreaterOrEqual" },
{ PatternActionType::TimeGreater, "TimeGreater" }
};
return map.find(type)->second;
}
struct PatternAction final
{ {
PatternActionType type; PatternActionType type;
std::uint32_t extra; std::uint32_t extra;
PatternAction() = default; PatternAction() = default;
PatternAction(const PatternActionType type, const std::uint32_t extra) : type{type}, extra{extra} {} PatternAction(const PatternActionType type, const std::uint32_t extra = 0) : type{type}, extra{extra} {}
}; };
using PatternActions = std::vector<PatternAction>;
void parsePattern() void parsePattern()
{ {
decltype(actions) actions{ PatternActions actions{
{ PatternActionType::KleeneStar, 0 } { PatternActionType::KleeneStar }
}; };
ParserString special_open_p("(?"); ParserString special_open_p("(?");
@ -266,7 +284,7 @@ private:
const auto throw_exception = [&] (const std::string & msg) { const auto throw_exception = [&] (const std::string & msg) {
throw Exception{ throw Exception{
msg + " '" + std::string(pos, end) + "' at position " + std::to_string(pos - begin), msg + " '" + std::string(pos, end) + "' at position " + std::to_string(pos - begin),
ErrorCodes::BAD_ARGUMENTS ErrorCodes::SYNTAX_ERROR
}; };
}; };
@ -313,9 +331,9 @@ private:
} }
else if (dot_closure_p.ignore(pos, end)) else if (dot_closure_p.ignore(pos, end))
actions.emplace_back(PatternActionType::KleeneStar, 0); actions.emplace_back(PatternActionType::KleeneStar);
else if (dot_p.ignore(pos, end)) else if (dot_p.ignore(pos, end))
actions.emplace_back(PatternActionType::AnyEvent, 0); actions.emplace_back(PatternActionType::AnyEvent);
else else
throw_exception("Could not parse pattern, unexpected starting symbol"); throw_exception("Could not parse pattern, unexpected starting symbol");
} }
@ -334,9 +352,10 @@ private:
const auto events_end = std::end(data_ref.eventsList); const auto events_end = std::end(data_ref.eventsList);
auto events_it = events_begin; auto events_it = events_begin;
/// an iterator to action plus an iterator to row in events list /// an iterator to action plus an iterator to row in events list plus timestamp at the start of sequence
using backtrack_info = std::pair<decltype(action_it), decltype(events_it)>; using backtrack_info = std::tuple<decltype(action_it), decltype(events_it), Data::Timestamp>;
std::stack<backtrack_info> back_stack; std::stack<backtrack_info> back_stack;
Data::Timestamp start_timestamp{};
/// backtrack if possible /// backtrack if possible
const auto do_backtrack = [&] { const auto do_backtrack = [&] {
@ -344,8 +363,9 @@ private:
{ {
auto & top = back_stack.top(); auto & top = back_stack.top();
action_it = top.first; action_it = std::get<0>(top);
events_it = std::next(top.second); events_it = std::next(std::get<1>(top));
start_timestamp = std::get<2>(top);
back_stack.pop(); back_stack.pop();
@ -358,33 +378,78 @@ private:
while (action_it != action_end && events_it != events_end) while (action_it != action_end && events_it != events_end)
{ {
std::cout << "start_timestamp " << start_timestamp << "; ";
std::cout << "action " << (action_it - action_begin) << " { " << to_string(action_it->type) << ' ' << action_it->extra << " }; ";
std::cout << "symbol " << (events_it - events_begin) << " { " << events_it->first << ' ' << events_it->second.to_ulong() << " }" << std::endl;
if (action_it->type == PatternActionType::SpecificEvent) if (action_it->type == PatternActionType::SpecificEvent)
{ {
if (events_it->second.test(action_it->extra)) if (events_it->second.test(action_it->extra))
{
/// move to the next action and events /// move to the next action and events
start_timestamp = events_it->first;
++action_it, ++events_it; ++action_it, ++events_it;
}
else if (!do_backtrack()) else if (!do_backtrack())
/// backtracking failed, bail out /// backtracking failed, bail out
break; break;
} }
else if (action_it->type == PatternActionType::AnyEvent) else if (action_it->type == PatternActionType::AnyEvent)
{ {
start_timestamp = events_it->first;
++action_it, ++events_it; ++action_it, ++events_it;
} }
else if (action_it->type == PatternActionType::KleeneStar) else if (action_it->type == PatternActionType::KleeneStar)
{ {
back_stack.emplace(action_it, events_it); back_stack.emplace(action_it, events_it, start_timestamp);
/// @todo fix off-by-one error caused by this assignment
start_timestamp = events_it->first;
++action_it; ++action_it;
} }
else if (action_it->type == PatternActionType::TimeLess || else if (action_it->type == PatternActionType::TimeLessOrEqual)
action_it->type == PatternActionType::TimeLessOrEqual)
{ {
++action_it; if (events_it->first - start_timestamp <= action_it->extra)
{
/// condition satisfied, move onto next action
back_stack.emplace(action_it, events_it, start_timestamp);
start_timestamp = events_it->first;
++action_it;
}
else if (!do_backtrack())
break;
} }
else if (action_it->type == PatternActionType::TimeGreaterOrEqual || else if (action_it->type == PatternActionType::TimeLess)
action_it->type == PatternActionType::TimeGreater)
{ {
++action_it; if (events_it->first - start_timestamp < action_it->extra)
{
back_stack.emplace(action_it, events_it, start_timestamp);
start_timestamp = events_it->first;
++action_it;
}
else if (!do_backtrack())
break;
}
else if (action_it->type == PatternActionType::TimeGreaterOrEqual)
{
if (events_it->first - start_timestamp >= action_it->extra)
{
back_stack.emplace(action_it, events_it, start_timestamp);
start_timestamp = events_it->first;
++action_it;
}
else if (++events_it == events_end && !do_backtrack())
break;
}
else if (action_it->type == PatternActionType::TimeGreater)
{
if (events_it->first - start_timestamp > action_it->extra)
{
back_stack.emplace(action_it, events_it, start_timestamp);
start_timestamp = events_it->first;
++action_it;
}
else if (++events_it == events_end && !do_backtrack())
break;
} }
else else
throw Exception{ throw Exception{
@ -393,16 +458,23 @@ private:
}; };
} }
/// skip multiple .* at the end /// if there are some actions remaining
while (action_it->type == PatternActionType::KleeneStar) if (action_it != action_end)
++action_it; {
/// match multiple empty strings at end
while (action_it->type == PatternActionType::KleeneStar ||
action_it->type == PatternActionType::TimeLessOrEqual ||
action_it->type == PatternActionType::TimeLess ||
(action_it->type == PatternActionType::TimeGreaterOrEqual && action_it->extra == 0))
++action_it;
}
return action_it == action_end; return action_it == action_end;
} }
std::string pattern; std::string pattern;
std::size_t arg_count; std::size_t arg_count;
std::vector<PatternAction> actions; PatternActions actions;
}; };
} }