mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-13 11:04:10 +00:00
dbms: implementation of temporal conditions [#METR-16058]
This commit is contained in:
parent
27ebf02a8d
commit
64dc50dfa4
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user