#include "function.h" #include "evaluate.h" #include "use.h" #include #include namespace NSQLComplete { namespace { class TVisitor: public NSQLPureAST::TSQLv1NarrowingVisitor { public: TVisitor(const TParsedInput& input, const INamedNodes* nodes) : NSQLPureAST::TSQLv1NarrowingVisitor(input.Tokens, input.Original.CursorPosition) , Nodes_(nodes) { } std::any visit(antlr4::tree::ParseTree* tree) override { if (IsEnclosing(tree)) { return TSQLv1NarrowingVisitor::visit(tree); } return {}; } std::any visitTable_ref(SQLv1::Table_refContext* ctx) override { auto* function = ctx->an_id_expr(); auto* lparen = ctx->TOKEN_LPAREN(); if (function == nullptr || lparen == nullptr) { return {}; } if (CursorPosition() <= TextInterval(lparen).b) { return {}; } TMaybe context = GetFunction(ctx, *Nodes_); if (!context) { return {}; } const size_t argN = ArgumentNumber(ctx).GetOrElse(0); context->ArgumentNumber = argN; context->Arg0 = (argN != 0) ? context->Arg0 : Nothing(); context->Arg1 = (argN != 1) ? context->Arg1 : Nothing(); return *context; } private: TMaybe ArgumentNumber(SQLv1::Table_refContext* ctx) const { for (auto [i, arg] : Enumerate(ctx->table_arg())) { if (IsEnclosing(arg)) { return i; } } return Nothing(); } const INamedNodes* Nodes_; }; TMaybe GetArgument(size_t index, SQLv1::Table_refContext* ctx, const INamedNodes& nodes) { auto* table_arg = ctx->table_arg(index); if (!table_arg) { return Nothing(); } auto* named_expr = table_arg->named_expr(); if (!named_expr) { return Nothing(); } return ToObjectRef(PartiallyEvaluate(named_expr, nodes)); } TMaybe GetCluster(SQLv1::Table_refContext* ctx, const INamedNodes& nodes) { auto* cluster_expr = ctx->cluster_expr(); if (!cluster_expr) { return Nothing(); } return ParseClusterContext(cluster_expr, nodes); } } // namespace TMaybe EnclosingFunction(TParsedInput input, const INamedNodes& nodes) { std::any result = TVisitor(input, &nodes).visit(input.SqlQuery); if (!result.has_value()) { return Nothing(); } return std::any_cast(result); } TMaybe GetFunction(SQLv1::Table_refContext* ctx, const INamedNodes& nodes) { auto* function = ctx->an_id_expr(); auto* lparen = ctx->TOKEN_LPAREN(); if (function == nullptr || lparen == nullptr) { return Nothing(); } return TFunctionContext{ .Name = function->getText(), .ArgumentNumber = 0, .Arg0 = GetArgument(0, ctx, nodes), .Arg1 = GetArgument(1, ctx, nodes), .Cluster = GetCluster(ctx, nodes), }; } } // namespace NSQLComplete