diff options
author | vitya-smirnov <[email protected]> | 2025-10-07 09:34:39 +0300 |
---|---|---|
committer | vitya-smirnov <[email protected]> | 2025-10-07 09:52:14 +0300 |
commit | babe7533f18c11be1f8a195ed2324d2d9a89436a (patch) | |
tree | 45b7627141bf5a52b45a3d61fd1fbdd564bb8dd9 | |
parent | 8fe7cfe254fde2772477a8933a163b5f303716b4 (diff) |
YQL-20086 sql/v1
commit_hash:55bc611cdaa0d8a0fc3c4c7708ed9f17cc4976cf
223 files changed, 23654 insertions, 23903 deletions
diff --git a/yql/essentials/sql/v1/aggregation.cpp b/yql/essentials/sql/v1/aggregation.cpp index 87a1859f208..e7a9d2a1fe9 100644 --- a/yql/essentials/sql/v1/aggregation.cpp +++ b/yql/essentials/sql/v1/aggregation.cpp @@ -15,25 +15,25 @@ using namespace NYql; namespace NSQLTranslationV1 { namespace { - bool BlockWindowAggregationWithoutFrameSpec(TPosition pos, TStringBuf name, ISource* src, TContext& ctx) { - if (src) { - auto winNamePtr = src->GetWindowName(); - if (winNamePtr) { - auto winSpecPtr = src->FindWindowSpecification(ctx, *winNamePtr); - if (!winSpecPtr) { - ctx.Error(pos) << "Failed to use aggregation function " << name << " without window specification or in wrong place"; - return true; - } +bool BlockWindowAggregationWithoutFrameSpec(TPosition pos, TStringBuf name, ISource* src, TContext& ctx) { + if (src) { + auto winNamePtr = src->GetWindowName(); + if (winNamePtr) { + auto winSpecPtr = src->FindWindowSpecification(ctx, *winNamePtr); + if (!winSpecPtr) { + ctx.Error(pos) << "Failed to use aggregation function " << name << " without window specification or in wrong place"; + return true; } } - return false; } + return false; +} - bool ShouldEmitAggApply(const TContext& ctx) { - const bool blockEngineEnabled = ctx.BlockEngineEnable || ctx.BlockEngineForce; - return ctx.EmitAggApply.GetOrElse(blockEngineEnabled); - } +bool ShouldEmitAggApply(const TContext& ctx) { + const bool blockEngineEnabled = ctx.BlockEngineEnable || ctx.BlockEngineForce; + return ctx.EmitAggApply.GetOrElse(blockEngineEnabled); } +} // namespace static const THashSet<TString> AggApplyFuncs = { "count_traits_factory", @@ -44,13 +44,16 @@ static const THashSet<TString> AggApplyFuncs = { "some_traits_factory", }; -class TAggregationFactory : public IAggregation { +class TAggregationFactory: public IAggregation { public: TAggregationFactory(TPosition pos, const TString& name, const TString& func, EAggregateMode aggMode, - bool multi = false, bool validateArgs = true) - : IAggregation(pos, name, func, aggMode), Factory_(!func.empty() ? - BuildBind(Pos_, aggMode == EAggregateMode::OverWindow || aggMode == EAggregateMode::OverWindowDistinct ? "window_module" : "aggregate_module", func) : nullptr), - Multi_(multi), ValidateArgs_(validateArgs), DynamicFactory_(!Factory_) + bool multi = false, bool validateArgs = true) + : IAggregation(pos, name, func, aggMode) + , Factory_(!func.empty() ? BuildBind(Pos_, aggMode == EAggregateMode::OverWindow || aggMode == EAggregateMode::OverWindowDistinct ? "window_module" : "aggregate_module", func) : nullptr) + , + Multi_(multi) + , ValidateArgs_(validateArgs) + , DynamicFactory_(!Factory_) { if (aggMode != EAggregateMode::OverWindow && aggMode != EAggregateMode::OverWindowDistinct && !func.empty() && AggApplyFuncs.contains(func)) { AggApplyName_ = func.substr(0, func.size() - 15); @@ -75,7 +78,7 @@ protected: if (expectedArgs != exprs.size()) { ctx.Error(Pos_) << "Aggregation function " << (isFactory ? "factory " : "") << Name_ - << " requires exactly " << expectedArgs << " argument(s), given: " << exprs.size(); + << " requires exactly " << expectedArgs << " argument(s), given: " << exprs.size(); return false; } } @@ -141,13 +144,13 @@ protected: } return Y("Apply", Factory_, (DynamicFactory_ ? Y("ListItemType", type) : type), - extractor); + extractor); } return Y("MultiAggregate", - Y("ListItemType", type), - extractor, - Factory_); + Y("ListItemType", type), + extractor, + Factory_); } bool DoInit(TContext& ctx, ISource* src) override { @@ -209,10 +212,8 @@ protected: } if (AggMode_ == EAggregateMode::OverWindow) { - Factory_ = BuildLambda(Pos_, Y("type", "extractor"), Y("block", Q(Y( - Y("let", "x", Y("Apply", Factory_, "type", "extractor")), - Y("return", Y("ToWindowTraits", "x")) - )))); + Factory_ = BuildLambda(Pos_, Y("type", "extractor"), Y("block", Q(Y(Y("let", "x", Y("Apply", Factory_, "type", "extractor")), + Y("return", Y("ToWindowTraits", "x")))))); } } @@ -231,11 +232,12 @@ private: bool DynamicFactory_; }; -class TAggregationFactoryImpl final : public TAggregationFactory { +class TAggregationFactoryImpl final: public TAggregationFactory { public: TAggregationFactoryImpl(TPosition pos, const TString& name, const TString& func, EAggregateMode aggMode, bool multi) : TAggregationFactory(pos, name, func, aggMode, multi) - {} + { + } private: TNodePtr DoClone() const final { @@ -247,19 +249,20 @@ TAggregationPtr BuildFactoryAggregation(TPosition pos, const TString& name, cons return new TAggregationFactoryImpl(pos, name, func, aggMode, multi); } -class TKeyPayloadAggregationFactory final : public TAggregationFactory { +class TKeyPayloadAggregationFactory final: public TAggregationFactory { public: TKeyPayloadAggregationFactory(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) : TAggregationFactory(pos, name, factory, aggMode) , FakeSource_(BuildFakeSource(pos)) - {} + { + } private: bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) final { ui32 adjustArgsCount = isFactory ? 0 : 2; if (exprs.size() < adjustArgsCount || exprs.size() > 1 + adjustArgsCount) { ctx.Error(Pos_) << "Aggregation function " << (isFactory ? "factory " : "") << Name_ << " requires " - << adjustArgsCount << " or " << (1 + adjustArgsCount) << " arguments, given: " << exprs.size(); + << adjustArgsCount << " or " << (1 + adjustArgsCount) << " arguments, given: " << exprs.size(); return false; } if (BlockWindowAggregationWithoutFrameSpec(Pos_, GetName(), src, ctx)) { @@ -313,8 +316,8 @@ private: Y_UNUSED(ctx); Y_UNUSED(allowAggApply); auto apply = Y("Apply", Factory_, type, - BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Key_) : Key_), - BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Payload_) : Payload_)); + BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Key_) : Key_), + BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Payload_) : Payload_)); AddFactoryArguments(apply); return apply; } @@ -362,11 +365,12 @@ TAggregationPtr BuildKeyPayloadFactoryAggregation(TPosition pos, const TString& return new TKeyPayloadAggregationFactory(pos, name, factory, aggMode); } -class TPayloadPredicateAggregationFactory final : public TAggregationFactory { +class TPayloadPredicateAggregationFactory final: public TAggregationFactory { public: TPayloadPredicateAggregationFactory(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) : TAggregationFactory(pos, name, factory, aggMode) - {} + { + } private: bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) final { @@ -389,8 +393,7 @@ private: } if (exprs.size() != adjustArgsCount) { - ctx.Error(Pos_) << "Aggregation function " << (isFactory ? "factory " : "") << Name_ << " requires " << - adjustArgsCount << " arguments, given: " << exprs.size(); + ctx.Error(Pos_) << "Aggregation function " << (isFactory ? "factory " : "") << Name_ << " requires " << adjustArgsCount << " arguments, given: " << exprs.size(); return false; } @@ -435,8 +438,8 @@ private: Y_UNUSED(ctx); Y_UNUSED(allowAggApply); return Y("Apply", Factory_, type, - BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Payload_) : Payload_), - BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Predicate_) : Predicate_)); + BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Payload_) : Payload_), + BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Predicate_) : Predicate_)); } std::vector<ui32> GetFactoryColumnIndices() const final { @@ -470,18 +473,20 @@ TAggregationPtr BuildPayloadPredicateFactoryAggregation(TPosition pos, const TSt return new TPayloadPredicateAggregationFactory(pos, name, factory, aggMode); } -class TTwoArgsAggregationFactory final : public TAggregationFactory { +class TTwoArgsAggregationFactory final: public TAggregationFactory { public: TTwoArgsAggregationFactory(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) : TAggregationFactory(pos, name, factory, aggMode) - {} + { + } private: bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) final { ui32 adjustArgsCount = isFactory ? 0 : 2; if (exprs.size() != adjustArgsCount) { - ctx.Error(Pos_) << "Aggregation function " << (isFactory ? "factory " : "") << Name_ << " requires " << - adjustArgsCount << " arguments, given: " << exprs.size(); + ctx.Error(Pos_) << "Aggregation function " << (isFactory ? "factory " : "") + << Name_ << " requires " << adjustArgsCount << " arguments, given: " + << exprs.size(); return false; } @@ -551,14 +556,15 @@ TAggregationPtr BuildTwoArgsFactoryAggregation(TPosition pos, const TString& nam return new TTwoArgsAggregationFactory(pos, name, factory, aggMode); } -class THistogramAggregationFactory final : public TAggregationFactory { +class THistogramAggregationFactory final: public TAggregationFactory { public: THistogramAggregationFactory(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) : TAggregationFactory(pos, name, factory, aggMode) , FakeSource_(BuildFakeSource(pos)) , Weight_(Y("Double", Q("1.0"))) , Intervals_(Y("Uint32", Q("100"))) - {} + { + } private: bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) final { @@ -578,18 +584,18 @@ private: /// \todo: solve it with named arguments const auto integer = exprs.back()->IsIntegerLiteral(); switch (exprs.size()) { - case 2U: - if (!integer) { - Weight_ = exprs.back(); - } - break; - case 3U: - if (!integer) { - ctx.Error(Pos_) << "Aggregation function " << Name_ << " for case with 3 arguments should have third argument of integer type"; - return false; - } - Weight_ = exprs[1]; - break; + case 2U: + if (!integer) { + Weight_ = exprs.back(); + } + break; + case 3U: + if (!integer) { + ctx.Error(Pos_) << "Aggregation function " << Name_ << " for case with 3 arguments should have third argument of integer type"; + return false; + } + Weight_ = exprs[1]; + break; } if (exprs.size() >= 2 && integer) { Intervals_ = Y("Cast", exprs.back(), Q("Uint32")); @@ -617,8 +623,8 @@ private: Y_UNUSED(ctx); Y_UNUSED(allowAggApply); auto apply = Y("Apply", Factory_, type, - BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Expr_) : Expr_), - BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Weight_) : Weight_)); + BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Expr_) : Expr_), + BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Weight_) : Weight_)); AddFactoryArguments(apply); return apply; } @@ -650,7 +656,7 @@ TAggregationPtr BuildHistogramFactoryAggregation(TPosition pos, const TString& n return new THistogramAggregationFactory(pos, name, factory, aggMode); } -class TLinearHistogramAggregationFactory final : public TAggregationFactory { +class TLinearHistogramAggregationFactory final: public TAggregationFactory { public: TLinearHistogramAggregationFactory(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) : TAggregationFactory(pos, name, factory, aggMode) @@ -658,7 +664,8 @@ public: , BinSize_(Y("Double", Q("10.0"))) , Minimum_(Y("Double", Q(ToString(-1.0 * Max<double>())))) , Maximum_(Y("Double", Q(ToString(Max<double>())))) - {} + { + } private: bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) final { @@ -697,8 +704,8 @@ private: Y_UNUSED(ctx); Y_UNUSED(allowAggApply); return Y("Apply", Factory_, type, - BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Expr_) : Expr_), - BinSize_, Minimum_, Maximum_); + BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Expr_) : Expr_), + BinSize_, Minimum_, Maximum_); } void AddFactoryArguments(TNodePtr& apply) const final { @@ -727,12 +734,13 @@ TAggregationPtr BuildLinearHistogramFactoryAggregation(TPosition pos, const TStr return new TLinearHistogramAggregationFactory(pos, name, factory, aggMode); } -class TPercentileFactory final : public TAggregationFactory { +class TPercentileFactory final: public TAggregationFactory { public: TPercentileFactory(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) : TAggregationFactory(pos, name, factory, aggMode) , FakeSource_(BuildFakeSource(pos)) - {} + { + } private: TMaybe<TString> GetGenericKey() const final { @@ -758,9 +766,9 @@ private: bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) final { ui32 adjustArgsCount = isFactory ? 0 : 1; - if (exprs.size() < 0 + adjustArgsCount || exprs.size() > 1 + adjustArgsCount) { + if (exprs.size() < 0 + adjustArgsCount || exprs.size() > 1 + adjustArgsCount) { ctx.Error(Pos_) << "Aggregation function " << (isFactory ? "factory " : "") << Name_ << " requires " - << (0 + adjustArgsCount) << " or " << (1 + adjustArgsCount) << " arguments, given: " << exprs.size(); + << (0 + adjustArgsCount) << " or " << (1 + adjustArgsCount) << " arguments, given: " << exprs.size(); return false; } @@ -777,8 +785,9 @@ private: } } - if (!TAggregationFactory::InitAggr(ctx, isFactory, src, node, isFactory ? TVector<TNodePtr>() : TVector<TNodePtr>(1, exprs.front()))) + if (!TAggregationFactory::InitAggr(ctx, isFactory, src, node, isFactory ? TVector<TNodePtr>() : TVector<TNodePtr>(1, exprs.front()))) { return false; + } TNodePtr x; if (1 + adjustArgsCount == exprs.size()) { @@ -824,15 +833,17 @@ private: } std::pair<TNodePtr, bool> AggregationTraits(const TNodePtr& type, bool overState, bool many, bool allowAggApply, TContext& ctx) const final { - if (Percentiles_.empty()) - return { TNodePtr(), true }; + if (Percentiles_.empty()) { + return {TNodePtr(), true}; + } TNodePtr names(Q(Percentiles_.cbegin()->first)); if (Percentiles_.size() > 1U) { names = Y(); - for (const auto& percentile : Percentiles_) + for (const auto& percentile : Percentiles_) { names = L(names, Q(percentile.first)); + } names = Q(names); } @@ -840,17 +851,15 @@ private: const auto listType = distinct ? Y("ListType", Y("StructMemberType", Y("ListItemType", type), BuildQuotedAtom(Pos_, DistinctKey_))) : type; auto apply = GetApply(listType, many, allowAggApply, ctx); if (!apply) { - return { TNodePtr(), false }; + return {TNodePtr(), false}; } auto wrapped = WrapIfOverState(apply, overState, many, ctx); if (!wrapped) { - return { TNodePtr(), false }; + return {TNodePtr(), false}; } - return { distinct ? - Q(Y(names, wrapped, BuildQuotedAtom(Pos_, DistinctKey_))) : - Q(Y(names, wrapped)), true }; + return {distinct ? Q(Y(names, wrapped, BuildQuotedAtom(Pos_, DistinctKey_))) : Q(Y(names, wrapped)), true}; } bool DoInit(TContext& ctx, ISource* src) final { @@ -874,16 +883,16 @@ TAggregationPtr BuildPercentileFactoryAggregation(TPosition pos, const TString& return new TPercentileFactory(pos, name, factory, aggMode); } -class TTopFreqFactory final : public TAggregationFactory { +class TTopFreqFactory final: public TAggregationFactory { public: TTopFreqFactory(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) : TAggregationFactory(pos, name, factory, aggMode) , FakeSource_(BuildFakeSource(pos)) - {} + { + } private: - - //first - n, second - buffer + // first - n, second - buffer using TPair = std::pair<TNodePtr, TNodePtr>; bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) final { @@ -892,13 +901,13 @@ private: const ui32 MinBuffer = 100; if (exprs.size() < adjustArgsCount || exprs.size() > 2 + adjustArgsCount) { - ctx.Error(Pos_) << "Aggregation function " << (isFactory? "factory " : "") << Name_ << - " requires " << adjustArgsCount << " to " << (2 + adjustArgsCount) << " arguments, given: " << exprs.size(); + ctx.Error(Pos_) << "Aggregation function " << (isFactory ? "factory " : "") << Name_ << " requires " << adjustArgsCount << " to " << (2 + adjustArgsCount) << " arguments, given: " << exprs.size(); return false; } - if (!TAggregationFactory::InitAggr(ctx, isFactory, src, node, isFactory ? TVector<TNodePtr>() : TVector<TNodePtr>(1, exprs.front()))) + if (!TAggregationFactory::InitAggr(ctx, isFactory, src, node, isFactory ? TVector<TNodePtr>() : TVector<TNodePtr>(1, exprs.front()))) { return false; + } TNodePtr n = Y("Null"); TNodePtr buffer = Y("Null"); @@ -925,7 +934,7 @@ private: buffer = Y("Coalesce", buffer, Y("Uint32", Q(ToString(MinBuffer)))); buffer = Y("Max", buffer, Y("Uint32", Q(ToString(MinBuffer)))); - auto x = TPair{ n, buffer }; + auto x = TPair{n, buffer}; if (isFactory) { TopFreqFactoryParams_ = x; } else { @@ -945,11 +954,11 @@ private: TPair topFreqs(TopFreqs_.cbegin()->second); if (TopFreqs_.size() > 1U) { - topFreqs = { Y(), Y() }; + topFreqs = {Y(), Y()}; for (const auto& topFreq : TopFreqs_) { - topFreqs = { L(topFreqs.first, topFreq.second.first), L(topFreqs.second, topFreq.second.second) }; + topFreqs = {L(topFreqs.first, topFreq.second.first), L(topFreqs.second, topFreq.second.second)}; } - topFreqs = { Q(topFreqs.first), Q(topFreqs.second) }; + topFreqs = {Q(topFreqs.first), Q(topFreqs.second)}; } auto apply = Y("Apply", Factory_, type, BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Expr_) : Expr_), topFreqs.first, topFreqs.second); @@ -961,15 +970,17 @@ private: } std::pair<TNodePtr, bool> AggregationTraits(const TNodePtr& type, bool overState, bool many, bool allowAggApply, TContext& ctx) const final { - if (TopFreqs_.empty()) - return { TNodePtr(), true }; + if (TopFreqs_.empty()) { + return {TNodePtr(), true}; + } TNodePtr names(Q(TopFreqs_.cbegin()->first)); if (TopFreqs_.size() > 1U) { names = Y(); - for (const auto& topFreq : TopFreqs_) + for (const auto& topFreq : TopFreqs_) { names = L(names, Q(topFreq.first)); + } names = Q(names); } @@ -977,17 +988,15 @@ private: const auto listType = distinct ? Y("ListType", Y("StructMemberType", Y("ListItemType", type), BuildQuotedAtom(Pos_, DistinctKey_))) : type; auto apply = GetApply(listType, many, allowAggApply, ctx); if (!apply) { - return { nullptr, false }; + return {nullptr, false}; } auto wrapped = WrapIfOverState(apply, overState, many, ctx); if (!wrapped) { - return { nullptr, false }; + return {nullptr, false}; } - return { distinct ? - Q(Y(names, wrapped, BuildQuotedAtom(Pos_, DistinctKey_))) : - Q(Y(names, wrapped)), true }; + return {distinct ? Q(Y(names, wrapped, BuildQuotedAtom(Pos_, DistinctKey_))) : Q(Y(names, wrapped)), true}; } bool DoInit(TContext& ctx, ISource* src) final { @@ -1014,19 +1023,20 @@ TAggregationPtr BuildTopFreqFactoryAggregation(TPosition pos, const TString& nam } template <bool HasKey> -class TTopAggregationFactory final : public TAggregationFactory { +class TTopAggregationFactory final: public TAggregationFactory { public: TTopAggregationFactory(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) : TAggregationFactory(pos, name, factory, aggMode) , FakeSource_(BuildFakeSource(pos)) - {} + { + } private: bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) final { ui32 adjustArgsCount = isFactory ? 1 : (HasKey ? 3 : 2); if (exprs.size() != adjustArgsCount) { ctx.Error(Pos_) << "Aggregation function " << (isFactory ? "factory " : "") << Name_ << " requires " - << adjustArgsCount << " arguments, given: " << exprs.size(); + << adjustArgsCount << " arguments, given: " << exprs.size(); return false; } @@ -1071,8 +1081,8 @@ private: TNodePtr apply; if (HasKey) { apply = Y("Apply", Factory_, type, - BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Key_) : Key_), - BuildLambda(Pos_, Y("row"), many ? Y("Payload", Payload_) : Payload_)); + BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Key_) : Key_), + BuildLambda(Pos_, Y("row"), many ? Y("Payload", Payload_) : Payload_)); } else { apply = Y("Apply", Factory_, type, BuildLambda(Pos_, Y("row"), many ? Y("Unwrap", Payload_) : Payload_)); } @@ -1128,20 +1138,22 @@ TAggregationPtr BuildTopFactoryAggregation(TPosition pos, const TString& name, c } template TAggregationPtr BuildTopFactoryAggregation<false>(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); -template TAggregationPtr BuildTopFactoryAggregation<true >(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +template TAggregationPtr BuildTopFactoryAggregation<true>(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); -class TCountDistinctEstimateAggregationFactory final : public TAggregationFactory { +class TCountDistinctEstimateAggregationFactory final: public TAggregationFactory { public: TCountDistinctEstimateAggregationFactory(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) : TAggregationFactory(pos, name, factory, aggMode) - {} + { + } private: bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) final { ui32 adjustArgsCount = isFactory ? 0 : 1; if (exprs.size() < adjustArgsCount || exprs.size() > 1 + adjustArgsCount) { - ctx.Error(Pos_) << Name_ << " aggregation function " << (isFactory ? "factory " : "") << " requires " << - adjustArgsCount << " or " << (1 + adjustArgsCount) << " argument(s), given: " << exprs.size(); + ctx.Error(Pos_) << Name_ << " aggregation function " << (isFactory ? "factory " : "") + << " requires " << adjustArgsCount << " or " << (1 + adjustArgsCount) + << " argument(s), given: " << exprs.size(); return false; } @@ -1201,7 +1213,7 @@ TAggregationPtr BuildCountDistinctEstimateFactoryAggregation(TPosition pos, cons return new TCountDistinctEstimateAggregationFactory(pos, name, factory, aggMode); } -class TListAggregationFactory final : public TAggregationFactory { +class TListAggregationFactory final: public TAggregationFactory { public: TListAggregationFactory(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) : TAggregationFactory(pos, name, factory, aggMode) @@ -1216,7 +1228,7 @@ private: ui32 maxArgs = (1 + adjustArgsCount); if (exprs.size() < minArgs || exprs.size() > maxArgs) { ctx.Error(Pos_) << "List aggregation " << (isFactory ? "factory " : "") << "function require " << minArgs - << " or " << maxArgs << " arguments, given: " << exprs.size(); + << " or " << maxArgs << " arguments, given: " << exprs.size(); return false; } @@ -1281,26 +1293,26 @@ TAggregationPtr BuildListFactoryAggregation(TPosition pos, const TString& name, return new TListAggregationFactory(pos, name, factory, aggMode); } -class TUserDefinedAggregationFactory final : public TAggregationFactory { +class TUserDefinedAggregationFactory final: public TAggregationFactory { public: TUserDefinedAggregationFactory(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) : TAggregationFactory(pos, name, factory, aggMode) - {} + { + } private: bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) final { ui32 adjustArgsCount = isFactory ? 0 : 1; if (exprs.size() < (3 + adjustArgsCount) || exprs.size() > (7 + adjustArgsCount)) { - ctx.Error(Pos_) << "User defined aggregation function " << (isFactory ? "factory " : "") << " requires " << - (3 + adjustArgsCount) << " to " << (7 + adjustArgsCount) << " arguments, given: " << exprs.size(); + ctx.Error(Pos_) << "User defined aggregation function " << (isFactory ? "factory " : "") << " requires " << (3 + adjustArgsCount) << " to " << (7 + adjustArgsCount) << " arguments, given: " << exprs.size(); return false; } Lambdas_[0] = BuildLambda(Pos_, Y("value", "parent"), Y("NamedApply", exprs[adjustArgsCount], Q(Y("value")), Y("AsStruct"), Y("DependsOn", "parent"))); Lambdas_[1] = BuildLambda(Pos_, Y("value", "state", "parent"), Y("NamedApply", exprs[adjustArgsCount + 1], Q(Y("state", "value")), Y("AsStruct"), Y("DependsOn", "parent"))); Lambdas_[2] = BuildLambda(Pos_, Y("one", "two"), Y("IfType", exprs[adjustArgsCount + 2], Y("NullType"), - BuildLambda(Pos_, Y(), Y("Void")), - BuildLambda(Pos_, Y(), Y("Apply", exprs[adjustArgsCount + 2], "one", "two")))); + BuildLambda(Pos_, Y(), Y("Void")), + BuildLambda(Pos_, Y(), Y("Apply", exprs[adjustArgsCount + 2], "one", "two")))); for (size_t i = 3U; i < Lambdas_.size(); ++i) { const auto j = adjustArgsCount + i; @@ -1349,11 +1361,12 @@ TAggregationPtr BuildUserDefinedFactoryAggregation(TPosition pos, const TString& return new TUserDefinedAggregationFactory(pos, name, factory, aggMode); } -class TCountAggregation final : public TAggregationFactory { +class TCountAggregation final: public TAggregationFactory { public: TCountAggregation(TPosition pos, const TString& name, const TString& func, EAggregateMode aggMode) : TAggregationFactory(pos, name, func, aggMode) - {} + { + } private: TNodePtr DoClone() const final { @@ -1380,19 +1393,20 @@ TAggregationPtr BuildCountAggregation(TPosition pos, const TString& name, const return new TCountAggregation(pos, name, func, aggMode); } -class TPGFactoryAggregation final : public TAggregationFactory { +class TPGFactoryAggregation final: public TAggregationFactory { public: TPGFactoryAggregation(TPosition pos, const TString& name, EAggregateMode aggMode) : TAggregationFactory(pos, name, "", aggMode, false, false) , PgFunc_(Name_) - {} + { + } bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) override { auto ret = TAggregationFactory::InitAggr(ctx, isFactory, src, node, exprs); if (ret) { if (isFactory) { Factory_ = BuildLambda(Pos_, Y("type", "extractor"), Y(AggMode_ == EAggregateMode::OverWindow ? "PgWindowTraitsTuple" : "PgAggregationTraitsTuple", - Q(PgFunc_), Y("ListItemType", "type"), "extractor")); + Q(PgFunc_), Y("ListItemType", "type"), "extractor")); } else { Lambda_ = BuildLambda(Pos_, Y("row"), exprs); } @@ -1413,11 +1427,11 @@ public: Y_UNUSED(allowAggApply); if (ShouldEmitAggApply(ctx) && allowAggApply && AggMode_ != EAggregateMode::OverWindow) { return Y("AggApply", - Q("pg_" + to_lower(PgFunc_)), Y("ListItemType", type), Lambda_); + Q("pg_" + to_lower(PgFunc_)), Y("ListItemType", type), Lambda_); } return Y(AggMode_ == EAggregateMode::OverWindow ? "PgWindowTraits" : "PgAggregationTraits", - Q(PgFunc_), Y("ListItemType", type), Lambda_); + Q(PgFunc_), Y("ListItemType", type), Lambda_); } private: @@ -1433,7 +1447,7 @@ TAggregationPtr BuildPGFactoryAggregation(TPosition pos, const TString& name, EA return new TPGFactoryAggregation(pos, name, aggMode); } -class TNthValueFactoryAggregation final : public TAggregationFactory { +class TNthValueFactoryAggregation final: public TAggregationFactory { public: public: TNthValueFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode) @@ -1448,7 +1462,7 @@ private: ui32 expectedArgs = (1 + adjustArgsCount); if (exprs.size() != expectedArgs) { ctx.Error(Pos_) << "NthValue aggregation " << (isFactory ? "factory " : "") << "function require " - << expectedArgs << " arguments, given: " << exprs.size(); + << expectedArgs << " arguments, given: " << exprs.size(); return false; } diff --git a/yql/essentials/sql/v1/antlr_token.h b/yql/essentials/sql/v1/antlr_token.h index 329c21ea794..8f349bf49ca 100644 --- a/yql/essentials/sql/v1/antlr_token.h +++ b/yql/essentials/sql/v1/antlr_token.h @@ -13,4 +13,4 @@ inline ui32 UnifiedToken(bool useAntlr4, ui32 id) { return useAntlr4 + (id << 16); } -} // namespace NSQLTranslationV1 +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/builtin.cpp b/yql/essentials/sql/v1/builtin.cpp index 78fdd702ad7..e5ed591beec 100644 --- a/yql/essentials/sql/v1/builtin.cpp +++ b/yql/essentials/sql/v1/builtin.cpp @@ -39,9 +39,7 @@ TNodePtr MakeTypeConfig(const TPosition& pos, const TString& ns, const TVector<T auto args = NYT::TNode::CreateMap(); for (ui32 i = 0; i < udfArgs.size(); ++i) { if (!udfArgs[i]->IsNull() && udfArgs[i]->IsLiteral()) { - args[ToString(i)] = NYT::TNode() - ("type", udfArgs[i]->GetLiteralType()) - ("value", udfArgs[i]->GetLiteralValue()); + args[ToString(i)] = NYT::TNode()("type", udfArgs[i]->GetLiteralType())("value", udfArgs[i]->GetLiteralValue()); } } @@ -69,7 +67,8 @@ public: TGroupingNode(TPosition pos, const TVector<TNodePtr>& args) : TAstListNode(pos) , Args_(args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) final { if (!src) { @@ -80,7 +79,7 @@ public: columns.reserve(Args_.size()); const bool isJoin = src->GetJoin(); ISource* composite = src->GetCompositeSource(); - for (const auto& node: Args_) { + for (const auto& node : Args_) { auto namePtr = node->GetColumnName(); if (!namePtr || !*namePtr) { ctx.Error(Pos_) << "GROUPING function should use columns as arguments"; @@ -125,7 +124,8 @@ public: , Name_(name) , Aggr_(aggr) , Args_(args) - {} + { + } TCiString GetName() const { return Name_; @@ -198,25 +198,27 @@ private: } void DoUpdateState() const final { - State_.Set(ENodeState::Const, !Args_.empty() && AllOf(Args_, [](const auto& arg){ return arg->IsConstant(); })); + State_.Set(ENodeState::Const, !Args_.empty() && AllOf(Args_, [](const auto& arg) { return arg->IsConstant(); })); State_.Set(ENodeState::Aggregated); } TNodePtr PreaggregateExpr_; + protected: const TString Name_; TAggregationPtr Aggr_; TVector<TNodePtr> Args_; }; -class TBasicAggrFactory final : public TAstListNode { +class TBasicAggrFactory final: public TAstListNode { public: TBasicAggrFactory(TPosition pos, const TString& name, TAggregationPtr aggr, const TVector<TNodePtr>& args) : TAstListNode(pos) , Name_(name) , Aggr_(aggr) , Args_(args) - {} + { + } TCiString GetName() const { return Name_; @@ -324,6 +326,7 @@ public: State_.Set(ENodeState::Aggregated, Atom_->IsAggregated()); State_.Set(ENodeState::OverWindow, Atom_->IsOverWindow()); } + private: TNodePtr Node_; TNodePtr Atom_; @@ -401,38 +404,38 @@ public: } switch (*slot) { - case NUdf::EDataSlot::Date: - case NUdf::EDataSlot::TzDate: - value = ToString(out.Get<ui16>()); - break; - case NUdf::EDataSlot::Date32: - case NUdf::EDataSlot::TzDate32: - value = ToString(out.Get<i32>()); - break; - case NUdf::EDataSlot::Datetime: - case NUdf::EDataSlot::TzDatetime: - value = ToString(out.Get<ui32>()); - break; - case NUdf::EDataSlot::Timestamp: - case NUdf::EDataSlot::TzTimestamp: - value = ToString(out.Get<ui64>()); - break; - case NUdf::EDataSlot::Datetime64: - case NUdf::EDataSlot::Timestamp64: - case NUdf::EDataSlot::TzDatetime64: - case NUdf::EDataSlot::TzTimestamp64: - value = ToString(out.Get<i64>()); - break; - case NUdf::EDataSlot::Interval: - case NUdf::EDataSlot::Interval64: - value = ToString(out.Get<i64>()); - if ('T' == atom->back()) { - ctx.Error(Pos_) << "Time prefix 'T' at end of interval constant. The designator 'T' shall be absent if all of the time components are absent."; - return false; - } - break; - default: - Y_ABORT("Unexpected data slot"); + case NUdf::EDataSlot::Date: + case NUdf::EDataSlot::TzDate: + value = ToString(out.Get<ui16>()); + break; + case NUdf::EDataSlot::Date32: + case NUdf::EDataSlot::TzDate32: + value = ToString(out.Get<i32>()); + break; + case NUdf::EDataSlot::Datetime: + case NUdf::EDataSlot::TzDatetime: + value = ToString(out.Get<ui32>()); + break; + case NUdf::EDataSlot::Timestamp: + case NUdf::EDataSlot::TzTimestamp: + value = ToString(out.Get<ui64>()); + break; + case NUdf::EDataSlot::Datetime64: + case NUdf::EDataSlot::Timestamp64: + case NUdf::EDataSlot::TzDatetime64: + case NUdf::EDataSlot::TzTimestamp64: + value = ToString(out.Get<i64>()); + break; + case NUdf::EDataSlot::Interval: + case NUdf::EDataSlot::Interval64: + value = ToString(out.Get<i64>()); + if ('T' == atom->back()) { + ctx.Error(Pos_) << "Time prefix 'T' at end of interval constant. The designator 'T' shall be absent if all of the time components are absent."; + return false; + } + break; + default: + Y_ABORT("Unexpected data slot"); } if (NUdf::GetDataTypeInfo(*slot).Features & NUdf::TzDateType) { @@ -466,7 +469,7 @@ public: }; template <bool HasMode> -class TSideEffects : public TCallNode { +class TSideEffects: public TCallNode { public: TSideEffects(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "WithSideEffectsMode", 2, 2, args) @@ -500,7 +503,7 @@ public: } }; -class TTableName : public TCallNode { +class TTableName: public TCallNode { public: TTableName(TPosition pos, const TVector<TNodePtr>& args, const TString& service) : TCallNode(pos, "TableName", 0, 2, args) @@ -523,17 +526,17 @@ public: // TODO: TablePath() and TableRecordIndex() have more strict limitations if (src->GetJoin()) { if (!ctx.Warning(Pos_, TIssuesIds::YQL_EMPTY_TABLENAME_RESULT, [](auto& out) { - out << "TableName() may produce empty result when used in ambiguous context (with JOIN)"; - })) { + out << "TableName() may produce empty result when used in ambiguous context (with JOIN)"; + })) { return false; } } if (src->HasAggregations()) { if (!ctx.Warning(Pos_, TIssuesIds::YQL_EMPTY_TABLENAME_RESULT, [](auto& out) { - out << "TableName() will produce empty result when used with aggregation.\n" - "Please consult documentation for possible workaround"; - })) { + out << "TableName() will produce empty result when used with aggregation.\n" + "Please consult documentation for possible workaround"; + })) { return false; } } @@ -582,12 +585,13 @@ private: const bool EmptyArgs_; }; -class TYqlParseType final : public INode { +class TYqlParseType final: public INode { public: TYqlParseType(TPosition pos, const TVector<TNodePtr>& args) : INode(pos) , Args_(args) - {} + { + } TAstNode* Translate(TContext& ctx) const override { if (Args_.size() != 1) { @@ -617,6 +621,7 @@ public: void DoUpdateState() const final { State_.Set(ENodeState::Const); } + private: TVector<TNodePtr> Args_; }; @@ -677,13 +682,12 @@ public: return TCallNode::DoInit(ctx, src); } - TNodePtr DoClone() const final { return new TYqlPgType(Pos_, CloneContainer(Args_)); } }; -class TYqlPgConst : public TCallNode { +class TYqlPgConst: public TCallNode { public: TYqlPgConst(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "PgConst", 2, -1, args) @@ -730,7 +734,7 @@ public: } }; -class TYqlPgCast : public TCallNode { +class TYqlPgCast: public TCallNode { public: TYqlPgCast(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "PgCast", 2, -1, args) @@ -766,7 +770,7 @@ public: } }; -class TYqlPgOp : public TCallNode { +class TYqlPgOp: public TCallNode { public: TYqlPgOp(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "PgOp", 2, 3, args) @@ -797,7 +801,7 @@ public: }; template <bool RangeFunction> -class TYqlPgCall : public TCallNode { +class TYqlPgCall: public TCallNode { public: TYqlPgCall(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "PgCall", 1, -1, args) @@ -829,7 +833,7 @@ public: }; template <const char* Name> -class TYqlSubqueryFor : public TCallNode { +class TYqlSubqueryFor: public TCallNode { public: TYqlSubqueryFor(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, Name, 2, 2, args) @@ -851,7 +855,7 @@ public: }; template <const char* Name> -class TYqlSubqueryOrderBy : public TCallNode { +class TYqlSubqueryOrderBy: public TCallNode { public: TYqlSubqueryOrderBy(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, Name, 2, 2, args) @@ -872,9 +876,8 @@ public: } }; - template <bool Strict> -class TYqlTypeAssert : public TCallNode { +class TYqlTypeAssert: public TCallNode { public: TYqlTypeAssert(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, Strict ? "EnsureType" : "EnsureConvertibleTo", 2, 3, args) @@ -906,11 +909,12 @@ public: } }; -class TFromBytes final : public TCallNode { +class TFromBytes final: public TCallNode { public: TFromBytes(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "FromBytes", 2, 2, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -930,11 +934,12 @@ public: } }; -class TYqlTaggedBase : public TCallNode { +class TYqlTaggedBase: public TCallNode { public: TYqlTaggedBase(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TCallNode(pos, opName, 2, 2, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -950,33 +955,36 @@ public: } }; -class TYqlAsTagged final : public TYqlTaggedBase { +class TYqlAsTagged final: public TYqlTaggedBase { public: TYqlAsTagged(TPosition pos, const TVector<TNodePtr>& args) : TYqlTaggedBase(pos, "AsTagged", args) - {} + { + } TNodePtr DoClone() const final { return new TYqlAsTagged(Pos_, CloneContainer(Args_)); } }; -class TYqlUntag final : public TYqlTaggedBase { +class TYqlUntag final: public TYqlTaggedBase { public: TYqlUntag(TPosition pos, const TVector<TNodePtr>& args) : TYqlTaggedBase(pos, "Untag", args) - {} + { + } TNodePtr DoClone() const final { return new TYqlUntag(Pos_, CloneContainer(Args_)); } }; -class TYqlVariant final : public TCallNode { +class TYqlVariant final: public TCallNode { public: TYqlVariant(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "Variant", 3, 3, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -996,11 +1004,12 @@ public: } }; -class TYqlEnum final : public TCallNode { +class TYqlEnum final: public TCallNode { public: TYqlEnum(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "Enum", 2, 2, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -1020,11 +1029,12 @@ public: } }; -class TYqlAsVariant final : public TCallNode { +class TYqlAsVariant final: public TCallNode { public: TYqlAsVariant(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "AsVariant", 2, 2, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -1044,11 +1054,12 @@ public: } }; -class TYqlAsEnum final : public TCallNode { +class TYqlAsEnum final: public TCallNode { public: TYqlAsEnum(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "AsEnum", 1, 1, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -1077,7 +1088,8 @@ class TYqlAtomBase: public TCallNode { public: TYqlAtomBase(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TCallNode(pos, opName, 1, 1, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!Args_.empty()) { @@ -1103,14 +1115,12 @@ public: } }; -class TYqlAtom final : public TYqlAtomBase<TYqlAtom, false> -{ +class TYqlAtom final: public TYqlAtomBase<TYqlAtom, false> { using TBase = TYqlAtomBase<TYqlAtom, false>; using TBase::TBase; }; -class TFileYqlAtom final : public TYqlAtomBase<TFileYqlAtom, true> -{ +class TFileYqlAtom final: public TYqlAtomBase<TFileYqlAtom, true> { using TBase = TYqlAtomBase<TFileYqlAtom, true>; using TBase::TBase; }; @@ -1119,7 +1129,8 @@ class TTryMember final: public TCallNode { public: TTryMember(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TCallNode(pos, opName, 3, 3, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (Args_.size() != 3) { @@ -1140,12 +1151,13 @@ public: } }; -template<bool Pretty> +template <bool Pretty> class TFormatTypeDiff final: public TCallNode { public: TFormatTypeDiff(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TCallNode(pos, opName, 3, 3, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (Args_.size() != 2) { @@ -1171,7 +1183,8 @@ class TAddMember final: public TCallNode { public: TAddMember(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TCallNode(pos, opName, 3, 3, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (Args_.size() != 3) { @@ -1196,7 +1209,8 @@ class TRemoveMember final: public TCallNode { public: TRemoveMember(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TCallNode(pos, opName, 2, 2, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (Args_.size() != 2) { @@ -1221,7 +1235,8 @@ class TCombineMembers final: public TCallNode { public: TCombineMembers(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TCallNode(pos, opName, 1, -1, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (Args_.empty()) { @@ -1243,7 +1258,8 @@ class TFlattenMembers final: public TCallNode { public: TFlattenMembers(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TCallNode(pos, opName, 1, -1, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (Args_.empty()) { @@ -1258,8 +1274,7 @@ public: // flatten with prefix Args_[i] = Q(Y( MakeAtomFromExpression(Pos_, ctx, Args_[i]->GetTupleElement(0)).Build(), - Args_[i]->GetTupleElement(1) - )); + Args_[i]->GetTupleElement(1))); } else { ctx.Error(Pos_) << OpName_ << " requires arguments to be tuples of size 2: prefix and struct"; return false; @@ -1289,14 +1304,14 @@ TString NormalizeTypeString(const TString& str) { } static const TSet<TString> AvailableDataTypes = {"Bool", "String", "Uint32", "Uint64", "Int32", "Int64", "Float", "Double", "Utf8", "Yson", "Json", "JsonDocument", - "Date", "Datetime", "Timestamp", "Interval", "Uint8", "Int8", "Uint16", "Int16", "TzDate", "TzDatetime", "TzTimestamp", "Uuid", "Decimal", "DyNumber", - "Date32", "Datetime64", "Timestamp64", "Interval64", "TzDate32", "TzDatetime64", "TzTimestamp64"}; + "Date", "Datetime", "Timestamp", "Interval", "Uint8", "Int8", "Uint16", "Int16", "TzDate", "TzDatetime", "TzTimestamp", "Uuid", "Decimal", "DyNumber", + "Date32", "Datetime64", "Timestamp64", "Interval64", "TzDate32", "TzDatetime64", "TzTimestamp64"}; TNodePtr GetDataTypeStringNode(TContext& ctx, TCallNode& node, unsigned argNum, TString* outTypeStrPtr = nullptr) { auto errMsgFunc = [&node, argNum]() { static std::array<TString, 2> numToName = {{"first", "second"}}; TStringBuilder sb; sb << "At " << numToName.at(argNum) << " argument of " << node.GetOpName() << " expected type string, available one of: " - << JoinRange(", ", AvailableDataTypes.begin(), AvailableDataTypes.end()) << ";"; + << JoinRange(", ", AvailableDataTypes.begin(), AvailableDataTypes.end()) << ";"; return TString(sb); }; auto typeStringNode = node.GetArgs().at(argNum); @@ -1323,7 +1338,8 @@ class TYqlParseFileOp final: public TCallNode { public: TYqlParseFileOp(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "ParseFile", 2, 2, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -1337,10 +1353,10 @@ public: auto aliasNode = BuildFileNameArgument(Args_[1]->GetPos(), Args_[1], ctx.Settings.FileAliasPrefix); OpName_ = "Apply"; Args_[0] = Y("Udf", Q("File.ByLines"), Y("Void"), - Y("TupleType", - Y("TupleType", Y("DataType", dataTypeStringNode)), - Y("StructType"), - Y("TupleType"))); + Y("TupleType", + Y("TupleType", Y("DataType", dataTypeStringNode)), + Y("StructType"), + Y("TupleType"))); Args_[1] = Y("FilePath", aliasNode); return TCallNode::DoInit(ctx, src); @@ -1355,7 +1371,7 @@ public: } }; -class TYqlDataType final : public TCallNode { +class TYqlDataType final: public TCallNode { public: TYqlDataType(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "DataType", 1, 3, args) @@ -1370,7 +1386,7 @@ public: for (ui32 i = 0; i < Args_.size(); ++i) { if (!Args_[i]->Init(ctx, FakeSource_.Get())) { - return false; + return false; } Args_[i] = MakeAtomFromExpression(Pos_, ctx, Args_[i]).Build(); @@ -1387,11 +1403,12 @@ private: TSourcePtr FakeSource_; }; -class TYqlResourceType final : public TCallNode { +class TYqlResourceType final: public TCallNode { public: TYqlResourceType(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "ResourceType", 1, 1, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -1411,11 +1428,12 @@ public: } }; -class TYqlTaggedType final : public TCallNode { +class TYqlTaggedType final: public TCallNode { public: TYqlTaggedType(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "TaggedType", 2, 2, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -1435,11 +1453,12 @@ public: } }; -class TYqlCallableType final : public TCallNode { +class TYqlCallableType final: public TCallNode { public: TYqlCallableType(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "CallableType", 2, -1, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -1474,11 +1493,12 @@ public: } }; -class TYqlTupleElementType final : public TCallNode { +class TYqlTupleElementType final: public TCallNode { public: TYqlTupleElementType(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "TupleElementType", 2, 2, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -1498,11 +1518,12 @@ public: } }; -class TYqlStructMemberType final : public TCallNode { +class TYqlStructMemberType final: public TCallNode { public: TYqlStructMemberType(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "StructMemberType", 2, 2, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -1522,11 +1543,12 @@ public: } }; -class TYqlCallableArgumentType final : public TCallNode { +class TYqlCallableArgumentType final: public TCallNode { public: TYqlCallableArgumentType(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "CallableArgumentType", 2, 2, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -1548,12 +1570,13 @@ public: } }; -class TStructTypeNode : public TAstListNode { +class TStructTypeNode: public TAstListNode { public: TStructTypeNode(TPosition pos, const TVector<TNodePtr>& exprs) : TAstListNode(pos) , Exprs_(exprs) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { Nodes_.push_back(BuildAtom(Pos_, "StructType", TNodeFlags::Default)); @@ -1581,11 +1604,12 @@ class TYqlIf final: public TCallNode { public: TYqlIf(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, IsStrict ? "IfStrict" : "If", 2, 3, args) - {} + { + } private: TCallNode::TPtr DoClone() const override { - return new TYqlIf(GetPos(), CloneContainer(Args_)); + return new TYqlIf(GetPos(), CloneContainer(Args_)); } bool DoInit(TContext& ctx, ISource* src) override { @@ -1605,11 +1629,12 @@ class TYqlSubstring final: public TCallNode { public: TYqlSubstring(TPosition pos, const TString& name, const TVector<TNodePtr>& args) : TCallNode(pos, name, 2, 3, args) - {} + { + } private: TCallNode::TPtr DoClone() const override { - return new TYqlSubstring(GetPos(), OpName_, CloneContainer(Args_)); + return new TYqlSubstring(GetPos(), OpName_, CloneContainer(Args_)); } bool DoInit(TContext& ctx, ISource* src) override { @@ -1624,7 +1649,8 @@ class TYqlIn final: public TCallNode { public: TYqlIn(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "IN", 3, 3, args) - {} + { + } private: TNodePtr DoClone() const final { @@ -1661,10 +1687,10 @@ private: if (singleElement->GetSource() || singleElement->IsSelect()) { TStringBuf parenKind = singleElement->GetSource() ? "" : "external "; if (!ctx.Warning(pos, TIssuesIds::YQL_CONST_SUBREQUEST_IN_LIST, [&](auto& out) { - out << "Using subrequest in scalar context after IN, " - << "perhaps you should remove " - << parenKind << "parenthesis here"; - })) { + out << "Using subrequest in scalar context after IN, " + << "perhaps you should remove " + << parenKind << "parenthesis here"; + })) { return false; } } @@ -1690,14 +1716,13 @@ private: Args_ = { inNode->GetSource() ? inNode->GetSource() : inNode, key, - BuildTuple(pos, hintElements) - }; + BuildTuple(pos, hintElements)}; return TCallNode::DoInit(ctx, src); } static TNodePtr BuildHint(TPosition pos, const TString& name) { - return BuildTuple(pos, { BuildQuotedAtom(pos, name, NYql::TNodeFlags::Default) }); + return BuildTuple(pos, {BuildQuotedAtom(pos, name, NYql::TNodeFlags::Default)}); } TString GetOpName() const override { @@ -1705,24 +1730,27 @@ private: } }; -class TYqlUdfBase : public TCallNode { +class TYqlUdfBase: public TCallNode { public: TYqlUdfBase(TPosition pos, const TString& name) : TCallNode(pos, "Udf", 1, 1, UdfArgs(pos, name)) - {} + { + } TYqlUdfBase(TPosition pos, const TString& name, const TVector<TNodePtr>& args, ui32 argsCount = 2) : TCallNode(pos, "Udf", argsCount, argsCount, UdfArgs(pos, name, &args)) - {} + { + } protected: TYqlUdfBase(TPosition pos, const TString& opName, ui32 minArgs, ui32 maxArgs, const TVector<TNodePtr>& args) : TCallNode(pos, opName, minArgs, maxArgs, args) - {} + { + } private: static TVector<TNodePtr> UdfArgs(TPosition pos, const TString& name, const TVector<TNodePtr>* args = nullptr) { - TVector<TNodePtr> res = { BuildQuotedAtom(pos, name) }; + TVector<TNodePtr> res = {BuildQuotedAtom(pos, name)}; if (args) { res.insert(res.end(), args->begin(), args->end()); } @@ -1731,7 +1759,7 @@ private: void DoUpdateState() const override { TCallNode::DoUpdateState(); - State_.Set(ENodeState::Aggregated, false/*!RunConfig || RunConfig->IsAggregated()*/); + State_.Set(ENodeState::Aggregated, false /*!RunConfig || RunConfig->IsAggregated()*/); State_.Set(ENodeState::Const, true /* FIXME: To avoid CheckAggregationLevel issue for non-const TypeOf. */); } @@ -1739,40 +1767,46 @@ private: TNodePtr RunConfig_; }; -class TYqlUdf final : public TYqlUdfBase { +class TYqlUdf final: public TYqlUdfBase { public: TYqlUdf(TPosition pos, const TString& name) : TYqlUdfBase(pos, name) - {} + { + } TYqlUdf(TPosition pos, const TString& name, const TVector<TNodePtr>& args, ui32 argsCount = 2) : TYqlUdfBase(pos, name, args, argsCount) - {} + { + } private: TYqlUdf(const TYqlUdf& other) : TYqlUdfBase(other.GetPos(), "Udf", other.MinArgs_, other.MaxArgs_, CloneContainer(other.Args_)) - {} + { + } TNodePtr DoClone() const final { return new TYqlUdf(*this); } }; -class TYqlTypeConfigUdf final : public TYqlUdfBase { +class TYqlTypeConfigUdf final: public TYqlUdfBase { public: TYqlTypeConfigUdf(TPosition pos, const TString& name) : TYqlUdfBase(pos, name) - {} + { + } TYqlTypeConfigUdf(TPosition pos, const TString& name, const TVector<TNodePtr>& args, ui32 argsCount = 2) : TYqlUdfBase(pos, name, args, argsCount) - {} + { + } private: TYqlTypeConfigUdf(const TYqlTypeConfigUdf& other) : TYqlUdfBase(other.GetPos(), "Udf", other.MinArgs_, other.MaxArgs_, CloneContainer(other.Args_)) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!ValidateArguments(ctx)) { @@ -1796,7 +1830,8 @@ class TWeakFieldOp final: public TCallNode { public: TWeakFieldOp(TPosition pos, const TVector<TNodePtr>& args) : TCallNode(pos, "WeakField", 2, 3, args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!src) { @@ -1811,7 +1846,7 @@ public: } bool hasError = false; - for (auto& arg: Args_) { + for (auto& arg : Args_) { if (!arg->Init(ctx, src)) { hasError = true; continue; @@ -1875,16 +1910,18 @@ public: }; template <bool Join> -class TTableRow final : public INode { +class TTableRow final: public INode { public: TTableRow(TPosition pos, const TVector<TNodePtr>& args) : TTableRow(pos, args.size()) - {} + { + } TTableRow(TPosition pos, ui32 argsCount) : INode(pos) , ArgsCount_(argsCount) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!src || src->IsFake()) { @@ -1904,7 +1941,7 @@ public: const auto& sameKeyMap = src->GetJoin()->GetSameKeysMap(); if (sameKeyMap) { block = L(block, Y("let", "flatSameKeys", "row")); - for (const auto& sameKeysPair: sameKeyMap) { + for (const auto& sameKeysPair : sameKeyMap) { const auto& column = sameKeysPair.first; auto keys = Y("Coalesce"); auto sameSourceIter = sameKeysPair.second.begin(); @@ -1924,12 +1961,12 @@ public: } auto members = Y(); - for (auto& joinLabel: src->GetJoin()->GetJoinLabels()) { + for (auto& joinLabel : src->GetJoin()->GetJoinLabels()) { members = L(members, BuildQuotedAtom(Pos_, joinLabel + ".")); } block = L(block, Y("let", "res", Y("DivePrefixMembers", "row", Q(members)))); - for (const auto& sameKeysPair: src->GetJoin()->GetSameKeysMap()) { + for (const auto& sameKeysPair : src->GetJoin()->GetSameKeysMap()) { const auto& column = sameKeysPair.first; auto addMemberKeyNode = Y("Member", "row", Q(column)); block = L(block, Y("let", "res", Y("AddMember", "res", Q(column), addMemberKeyNode))); @@ -1966,12 +2003,14 @@ private: TTableRows::TTableRows(TPosition pos, const TVector<TNodePtr>& args) : TTableRows(pos, args.size()) -{} +{ +} TTableRows::TTableRows(TPosition pos, ui32 argsCount) : INode(pos) , ArgsCount_(argsCount) -{} +{ +} bool TTableRows::DoInit(TContext& ctx, ISource* /*src*/) { if (ArgsCount_ > 0) { @@ -2000,7 +2039,8 @@ TSessionWindow::TSessionWindow(TPosition pos, const TVector<TNodePtr>& args) , Args_(args) , FakeSource_(BuildFakeSource(pos)) , Valid_(false) -{} +{ +} void TSessionWindow::MarkValid() { YQL_ENSURE(!HasState(ENodeState::Initialized)); @@ -2022,19 +2062,19 @@ TNodePtr TSessionWindow::BuildTraits(const TString& label) const { }; auto absDelta = Y("If", - coalesceLess("prev", "curr"), - Y("-", "curr", "prev"), - Y("-", "prev", "curr")); + coalesceLess("prev", "curr"), + Y("-", "curr", "prev"), + Y("-", "prev", "curr")); auto newSessionPred = Y("And", Y("AggrNotEquals", "curr", "prev"), coalesceLess(timeoutExpr, absDelta)); auto timeoutLambda = BuildLambda(timeoutExpr->GetPos(), Y("prev", "curr"), newSessionPred); auto sortSpec = Y("SortTraits", Y("TypeOf", label), trueNode, BuildLambda(Pos_, Y("row"), Y("PersistableRepr", timeExpr))); return Y("SessionWindowTraits", - Y("TypeOf", label), - sortSpec, - BuildLambda(Pos_, Y("row"), timeExpr), - timeoutLambda); + Y("TypeOf", label), + sortSpec, + BuildLambda(Pos_, Y("row"), timeExpr), + timeoutLambda); } auto orderExpr = Args_[0]; @@ -2045,11 +2085,11 @@ TNodePtr TSessionWindow::BuildTraits(const TString& label) const { auto sortSpec = Y("SortTraits", Y("TypeOf", label), trueNode, BuildLambda(Pos_, Y("row"), Y("PersistableRepr", orderExpr))); return Y("SessionWindowTraits", - Y("TypeOf", label), - sortSpec, - initLambda, - updateLambda, - calculateLambda); + Y("TypeOf", label), + sortSpec, + initLambda, + updateLambda, + calculateLambda); } bool TSessionWindow::DoInit(TContext& ctx, ISource* src) { @@ -2081,7 +2121,7 @@ bool TSessionWindow::DoInit(TContext& ctx, ISource* src) { src->AllColumns(); return orderExpr->Init(ctx, src) && initLambda->Init(ctx, FakeSource_.Get()) && - updateLambda->Init(ctx, FakeSource_.Get()) && calculateLambda->Init(ctx, FakeSource_.Get()); + updateLambda->Init(ctx, FakeSource_.Get()) && calculateLambda->Init(ctx, FakeSource_.Get()); } TAstNode* TSessionWindow::Translate(TContext&) const { @@ -2101,19 +2141,21 @@ TString TSessionWindow::GetOpName() const { return "SessionWindow"; } -template<bool IsStart> -class TSessionStart final : public INode { +template <bool IsStart> +class TSessionStart final: public INode { public: TSessionStart(TPosition pos, const TVector<TNodePtr>& args) : INode(pos) , ArgsCount_(args.size()) { } + private: TSessionStart(TPosition pos, size_t argsCount) : INode(pos) , ArgsCount_(argsCount) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (!src || src->IsFake()) { @@ -2205,7 +2247,8 @@ THoppingWindow::THoppingWindow(TPosition pos, TVector<TNodePtr> args) , Args_(std::move(args)) , FakeSource_(BuildFakeSource(pos)) , Valid_(false) -{} +{ +} TNodePtr THoppingWindow::BuildTraits(const TString& label) const { YQL_ENSURE(HasState(ENodeState::Initialized)); @@ -2218,8 +2261,7 @@ TNodePtr THoppingWindow::BuildTraits(const TString& label) const { Interval_, Delay_, Q(DataWatermarks_), - Q("v2") - ); + Q("v2")); } TNodePtr THoppingWindow::GetInterval() const { @@ -2323,7 +2365,7 @@ TNodePtr BuildUdfUserTypeArg(TPosition pos, TNodePtr positionalArgs, TNodePtr na } TVector<TNodePtr> BuildUdfArgs(const TContext& ctx, TPosition pos, const TVector<TNodePtr>& args, - TNodePtr positionalArgs, TNodePtr namedArgs, TNodePtr externalTypes, TNodePtr typeConfig) { + TNodePtr positionalArgs, TNodePtr namedArgs, TNodePtr externalTypes, TNodePtr typeConfig) { if (!ctx.Settings.EnableGenericUdfs) { return {}; } @@ -2344,8 +2386,8 @@ TVector<TNodePtr> BuildUdfArgs(const TContext& ctx, TPosition pos, const TVector } TNodePtr BuildSqlCall(TContext& ctx, TPosition pos, const TString& module, const TString& name, const TVector<TNodePtr>& args, - TNodePtr positionalArgs, TNodePtr namedArgs, TNodePtr externalTypes, const TDeferredAtom& typeConfig, TNodePtr runConfig, - TNodePtr options, const TVector<TNodePtr>& depends) + TNodePtr positionalArgs, TNodePtr namedArgs, TNodePtr externalTypes, const TDeferredAtom& typeConfig, TNodePtr runConfig, + TNodePtr options, const TVector<TNodePtr>& depends) { const TString fullName = module + "." + name; TNodePtr callable; @@ -2357,7 +2399,7 @@ TNodePtr BuildSqlCall(TContext& ctx, TPosition pos, const TString& module, const } if (callable) { - TVector<TNodePtr> applyArgs = { callable }; + TVector<TNodePtr> applyArgs = {callable}; applyArgs.insert(applyArgs.end(), args.begin(), args.end()); return new TCallNodeImpl(pos, namedArgs ? "NamedApply" : "Apply", applyArgs); } @@ -2368,10 +2410,10 @@ TNodePtr BuildSqlCall(TContext& ctx, TPosition pos, const TString& module, const auto tupleNodePtr = positionalArgs->GetTupleNode(); YQL_ENSURE(tupleNodePtr); TNodePtr positionalArgsNode = new TCallNodeImpl(pos, "PositionalArgs", tupleNodePtr->Elements()); - sqlCallArgs.push_back(BuildTuple(pos, { positionalArgsNode, namedArgs })); + sqlCallArgs.push_back(BuildTuple(pos, {positionalArgsNode, namedArgs})); } else { TNodePtr positionalArgsNode = new TCallNodeImpl(pos, "PositionalArgs", args); - sqlCallArgs.push_back(BuildTuple(pos, { positionalArgsNode })); + sqlCallArgs.push_back(BuildTuple(pos, {positionalArgsNode})); } // optional arguments @@ -2400,7 +2442,7 @@ TNodePtr BuildSqlCall(TContext& ctx, TPosition pos, const TString& module, const } for (const auto& d : depends) { - sqlCallArgs.push_back(new TCallNodeImpl(pos, "DependsOn", { d })); + sqlCallArgs.push_back(new TCallNodeImpl(pos, "DependsOn", {d})); } return new TCallNodeImpl(pos, "SqlCall", sqlCallArgs); @@ -2414,7 +2456,8 @@ public: , Name_(name) , Args_(args) , ForReduce_(forReduce) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (Module_ == "yql") { @@ -2459,8 +2502,9 @@ public: } } - if ("Datetime" == Module_ || ("Yson" == Module_ && ctx.PragmaYsonFast)) + if ("Datetime" == Module_ || ("Yson" == Module_ && ctx.PragmaYsonFast)) { Module_.append('2'); + } TNodePtr typeConfig = MakeTypeConfig(Pos_, to_lower(Module_), Args_); if (ForReduce_) { @@ -2505,6 +2549,7 @@ public: Y_DEBUG_ABORT_UNLESS(Node_); Node_->VisitTree(func, visited); } + private: TCiString Module_; TString Name_; @@ -2535,13 +2580,14 @@ TNodePtr BuildUdf(TContext& ctx, TPosition pos, const TString& module, const TSt class TScriptUdf final: public INode { public: TScriptUdf(TPosition pos, const TString& moduleName, const TString& funcName, const TVector<TNodePtr>& args, - TNodePtr options) + TNodePtr options) : INode(pos) , ModuleName_(moduleName) , FuncName_(funcName) , Args_(args) , Options_(options) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { const bool isPython = ModuleName_.find(TStringBuf("Python")) != TString::npos; @@ -2573,11 +2619,10 @@ public: } else { // Python supports getting functions signatures right from docstrings type = Y("EvaluateType", Y("ParseTypeHandle", Y("Apply", - Y("bind", "core_module", Q("PythonFuncSignature")), - Q(ModuleName_), - scriptNode, - Y("String", nameAtom) - ))); + Y("bind", "core_module", Q("PythonFuncSignature")), + Q(ModuleName_), + scriptNode, + Y("String", nameAtom)))); } if (!type->Init(ctx, src)) { @@ -2640,7 +2685,7 @@ private: }; TNodePtr BuildScriptUdf(TPosition pos, const TString& moduleName, const TString& funcName, const TVector<TNodePtr>& args, - TNodePtr options) { + TNodePtr options) { return new TScriptUdf(pos, moduleName, funcName, args, options); } @@ -2650,11 +2695,12 @@ public: TYqlToDict(TPosition pos, const TString& mode, const TVector<TNodePtr>& args) : TCallNode(pos, "ToDict", 4, 4, args) , Mode_(mode) - {} + { + } private: TCallNode::TPtr DoClone() const override { - return new TYqlToDict<Sorted, Hashed>(GetPos(), Mode_, CloneContainer(Args_)); + return new TYqlToDict<Sorted, Hashed>(GetPos(), Mode_, CloneContainer(Args_)); } bool DoInit(TContext& ctx, ISource* src) override { @@ -2664,20 +2710,23 @@ private: } Args_.push_back(BuildLambda(Pos_, Y("val"), Y("Nth", "val", Q("0")))); Args_.push_back(BuildLambda(Pos_, Y("val"), Y("Nth", "val", Q("1")))); - Args_.push_back(Q(Y(Q(Sorted ? "Sorted" : Hashed ? "Hashed" : "Auto"), Q(Mode_)))); + Args_.push_back(Q(Y(Q(Sorted ? "Sorted" : Hashed ? "Hashed" + : "Auto"), Q(Mode_)))); return TCallNode::DoInit(ctx, src); } + private: TString Mode_; }; -template<bool IsStart> -class THoppingTime final : public TAstListNode { +template <bool IsStart> +class THoppingTime final: public TAstListNode { public: THoppingTime(TPosition pos, TVector<TNodePtr> args) : TAstListNode(pos) , Args_(std::move(args)) - {} + { + } private: bool DoInit(TContext& ctx, ISource* src) override { @@ -2703,18 +2752,17 @@ private: } const auto fieldName = legacySpec - ? "_yql_time" - : spec->GetLabel(); + ? "_yql_time" + : spec->GetLabel(); if constexpr (IsStart) { const auto interval = legacySpec - ? legacySpec->Interval - : dynamic_cast<THoppingWindow*>(spec.Get())->GetInterval(); + ? legacySpec->Interval + : dynamic_cast<THoppingWindow*>(spec.Get())->GetInterval(); Add("Sub", Y("Member", "row", Q(fieldName)), - interval - ); + interval); } else { Add("Member", "row", Q(fieldName)); } @@ -2758,6 +2806,7 @@ public: TPtr DoClone() const override { return new TInvalidBuiltin(GetPos(), Info_); } + private: TString Info_; }; @@ -2808,77 +2857,76 @@ using TBuiltinFactoryCallbackMap = std::unordered_map<TString, TBuiltinFuncInfo, using TCoreFuncMap = std::unordered_map<TString, TCoreFuncInfo, THash<TString>>; TAggrFuncFactoryCallback BuildAggrFuncFactoryCallback( - const TString& functionName, - const TString& factoryName, - EAggrFuncTypeCallback type = NORMAL, - const TString& functionNameOverride = TString(), - const TVector<EAggregateMode>& validModes = {}) { - + const TString& functionName, + const TString& factoryName, + EAggrFuncTypeCallback type = NORMAL, + const TString& functionNameOverride = TString(), + const TVector<EAggregateMode>& validModes = {}) { const TString realFunctionName = functionNameOverride.empty() ? functionName : functionNameOverride; - return [functionName, realFunctionName, factoryName, type, validModes] (TPosition pos, const TVector<TNodePtr>& args, EAggregateMode aggMode, bool isFactory) -> INode::TPtr { + return [functionName, realFunctionName, factoryName, type, validModes](TPosition pos, const TVector<TNodePtr>& args, EAggregateMode aggMode, bool isFactory) -> INode::TPtr { if (!validModes.empty()) { if (!IsIn(validModes, aggMode)) { TString errorText; if (TVector{EAggregateMode::OverWindow} == validModes) { errorText = TStringBuilder() - << "Can't use window function " << functionName << " without window specification (OVER keyword is missing)"; + << "Can't use window function " << functionName << " without window specification (OVER keyword is missing)"; } else { errorText = TStringBuilder() - << "Can't use " << functionName << " in " << ToString(aggMode) << " aggregation mode"; + << "Can't use " << functionName << " in " << ToString(aggMode) << " aggregation mode"; } return INode::TPtr(new TInvalidBuiltin(pos, errorText)); } } TAggregationPtr factory = nullptr; switch (type) { - case NORMAL: - factory = BuildFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case KEY_PAYLOAD: - factory = BuildKeyPayloadFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case PAYLOAD_PREDICATE: - factory = BuildPayloadPredicateFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case TWO_ARGS: - factory = BuildTwoArgsFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case COUNT: - factory = BuildCountAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case HISTOGRAM: - factory = BuildHistogramFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case LINEAR_HISTOGRAM: - factory = BuildLinearHistogramFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case PERCENTILE: - factory = BuildPercentileFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case TOPFREQ: - factory = BuildTopFreqFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case TOP: - factory = BuildTopFactoryAggregation<false>(pos, realFunctionName, factoryName, aggMode); - break; - case TOP_BY: - factory = BuildTopFactoryAggregation<true>(pos, realFunctionName, factoryName, aggMode); - break; - case COUNT_DISTINCT_ESTIMATE: - factory = BuildCountDistinctEstimateFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case LIST: - factory = BuildListFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case UDAF: - factory = BuildUserDefinedFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; - case PG: - factory = BuildPGFactoryAggregation(pos, realFunctionName, aggMode); - break; - case NTH_VALUE: - factory = BuildNthFactoryAggregation(pos, realFunctionName, factoryName, aggMode); - break; + case NORMAL: + factory = BuildFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case KEY_PAYLOAD: + factory = BuildKeyPayloadFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case PAYLOAD_PREDICATE: + factory = BuildPayloadPredicateFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case TWO_ARGS: + factory = BuildTwoArgsFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case COUNT: + factory = BuildCountAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case HISTOGRAM: + factory = BuildHistogramFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case LINEAR_HISTOGRAM: + factory = BuildLinearHistogramFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case PERCENTILE: + factory = BuildPercentileFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case TOPFREQ: + factory = BuildTopFreqFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case TOP: + factory = BuildTopFactoryAggregation<false>(pos, realFunctionName, factoryName, aggMode); + break; + case TOP_BY: + factory = BuildTopFactoryAggregation<true>(pos, realFunctionName, factoryName, aggMode); + break; + case COUNT_DISTINCT_ESTIMATE: + factory = BuildCountDistinctEstimateFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case LIST: + factory = BuildListFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case UDAF: + factory = BuildUserDefinedFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; + case PG: + factory = BuildPGFactoryAggregation(pos, realFunctionName, aggMode); + break; + case NTH_VALUE: + factory = BuildNthFactoryAggregation(pos, realFunctionName, factoryName, aggMode); + break; } if (isFactory) { auto realArgs = args; @@ -2891,73 +2939,69 @@ TAggrFuncFactoryCallback BuildAggrFuncFactoryCallback( } TAggrFuncFactoryCallback BuildAggrFuncFactoryCallback( - const TString& functionName, - const TString& factoryName, - const TVector<EAggregateMode>& validModes, - EAggrFuncTypeCallback type = NORMAL, - const TString& functionNameOverride = TString()) { + const TString& functionName, + const TString& factoryName, + const TVector<EAggregateMode>& validModes, + EAggrFuncTypeCallback type = NORMAL, + const TString& functionNameOverride = TString()) { return BuildAggrFuncFactoryCallback(functionName, factoryName, type, functionNameOverride, validModes); } -template<typename TType> +template <typename TType> TBuiltinFactoryCallback BuildSimpleBuiltinFactoryCallback() { - return [] (TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { + return [](TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { return new TType(pos, args); }; } -template<typename TType> +template <typename TType> TBuiltinFactoryCallback BuildNamedBuiltinFactoryCallback(const TString& name) { - return [name] (TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { + return [name](TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { return new TType(pos, name, args); }; } -template<typename TType> +template <typename TType> TBuiltinFactoryCallback BuildArgcBuiltinFactoryCallback(i32 minArgs, i32 maxArgs) { - return [minArgs, maxArgs] (TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { + return [minArgs, maxArgs](TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { return new TType(pos, minArgs, maxArgs, args); }; } -template<typename TType> +template <typename TType> TBuiltinFactoryCallback BuildNamedArgcBuiltinFactoryCallback(const TString& name, i32 minArgs, i32 maxArgs) { - return [name, minArgs, maxArgs] (TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { + return [name, minArgs, maxArgs](TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { return new TType(pos, name, minArgs, maxArgs, args); }; } -template<typename TType> +template <typename TType> TBuiltinFactoryCallback BuildNamedDepsArgcBuiltinFactoryCallback(ui32 reqArgsCount, const TString& name, i32 minArgs, i32 maxArgs) { return [reqArgsCount, name, minArgs, maxArgs](TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { return new TType(reqArgsCount, pos, name, minArgs, maxArgs, args); }; } -template<typename TType> +template <typename TType> TBuiltinFactoryCallback BuildBoolBuiltinFactoryCallback(bool arg) { - return [arg] (TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { + return [arg](TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { return new TType(pos, args, arg); }; } -template<typename TType> +template <typename TType> TBuiltinFactoryCallback BuildFoldBuiltinFactoryCallback(const TString& name, const TString& defaultValue) { - return [name, defaultValue] (TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { + return [name, defaultValue](TPosition pos, const TVector<TNodePtr>& args) -> TNodePtr { return new TType(pos, name, "Bool", defaultValue, 1, args); }; } TNodePtr MakePair(TPosition pos, const TVector<TNodePtr>& args) { - TNodePtr list = new TAstListNodeImpl(pos, { - args[0], - args.size() > 1 ? args[1] : new TAstListNodeImpl(pos,{ new TAstAtomNodeImpl(pos, "Null", TNodeFlags::Default) }) - }); - - return new TAstListNodeImpl(pos, { - new TAstAtomNodeImpl(pos, "quote", TNodeFlags::Default), - list - }); + TNodePtr list = new TAstListNodeImpl(pos, {args[0], + args.size() > 1 ? args[1] : new TAstListNodeImpl(pos, {new TAstAtomNodeImpl(pos, "Null", TNodeFlags::Default)})}); + + return new TAstListNodeImpl(pos, {new TAstAtomNodeImpl(pos, "quote", TNodeFlags::Default), + list}); } struct TBuiltinFuncData { @@ -2965,9 +3009,11 @@ struct TBuiltinFuncData { const TAggrFuncFactoryCallbackMap AggrFuncs; const TCoreFuncMap CoreFuncs; - TBuiltinFuncData(): - BuiltinFuncs(MakeBuiltinFuncs()), - AggrFuncs(MakeAggrFuncs()), + TBuiltinFuncData() + : BuiltinFuncs(MakeBuiltinFuncs()) + , + AggrFuncs(MakeAggrFuncs()) + , CoreFuncs(MakeCoreFuncs()) { } @@ -2976,7 +3022,7 @@ struct TBuiltinFuncData { TBuiltinFactoryCallbackMap builtinFuncs = { // Branching {"if", {"If", "Normal", BuildSimpleBuiltinFactoryCallback<TYqlIf<false>>()}}, - {"ifstrict", {"IfStrict", "Normal", BuildSimpleBuiltinFactoryCallback<TYqlIf<true>>() }}, + {"ifstrict", {"IfStrict", "Normal", BuildSimpleBuiltinFactoryCallback<TYqlIf<true>>()}}, // String builtins {"len", {"Length", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("Size", 1, 1)}}, @@ -2991,8 +3037,8 @@ struct TBuiltinFuncData { {"endswith", {"EndsWith", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("EndsWith", 2, 2)}}, // Numeric builtins - {"abs", {"Abs", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("Abs", 1, 1) }}, - {"tobytes", {"ToBytes", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("ToBytes", 1, 1) }}, + {"abs", {"Abs", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("Abs", 1, 1)}}, + {"tobytes", {"ToBytes", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("ToBytes", 1, 1)}}, {"frombytes", {"FromBytes", "Normal", BuildSimpleBuiltinFactoryCallback<TFromBytes>()}}, // Compare builtins @@ -3004,7 +3050,7 @@ struct TBuiltinFuncData { // List builtins {"aslist", {"AsList", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("AsListMayWarn", 0, -1)}}, - {"asliststrict", {"AsListStrict", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("AsListStrict", 0, -1) }}, + {"asliststrict", {"AsListStrict", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("AsListStrict", 0, -1)}}, {"listlength", {"ListLength", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("Length", 1, 1)}}, {"listhasitems", {"ListHasItems", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("HasItems", 1, 1)}}, {"listextend", {"ListExtend", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("ListExtend", 0, -1)}}, @@ -3077,11 +3123,11 @@ struct TBuiltinFuncData { {"dictkeys", {"DictKeys", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("DictKeys", 1, 1)}}, {"dictpayloads", {"DictPayloads", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("DictPayloads", 1, 1)}}, {"dictitems", {"DictItems", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("DictItems", 1, 1)}}, - {"dictlookup", {"DictLookup", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("Lookup", 2, 2) }}, + {"dictlookup", {"DictLookup", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("Lookup", 2, 2)}}, {"dictcontains", {"DictContains", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("Contains", 2, 2)}}, - {"todynamiclinear", {"ToDynamicLinear", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("ToDynamicLinear", 1, 1) }}, - {"fromdynamiclinear", {"FromDynamicLinear", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("FromDynamicLinear", 1, 1) }}, + {"todynamiclinear", {"ToDynamicLinear", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("ToDynamicLinear", 1, 1)}}, + {"fromdynamiclinear", {"FromDynamicLinear", "Normal", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("FromDynamicLinear", 1, 1)}}, // MutDict builtins {"mutdictcreate", {"MutDictCreate", "Normal", BuildSimpleBuiltinFactoryCallback<TMutDictCreateBuiltin>()}}, {"tomutdict", {"ToMutDict", "Normal", BuildSimpleBuiltinFactoryCallback<TToMutDictBuiltin>()}}, @@ -3316,8 +3362,7 @@ struct TBuiltinFuncData { // Hopping intervals time functions {"hopstart", {"HopStart", "Agg", BuildSimpleBuiltinFactoryCallback<THoppingTime<true>>()}}, - {"hopend", {"HopEnd", "Agg", BuildSimpleBuiltinFactoryCallback<THoppingTime<false>>()}} - }; + {"hopend", {"HopEnd", "Agg", BuildSimpleBuiltinFactoryCallback<THoppingTime<false>>()}}}; return builtinFuncs; } @@ -3418,7 +3463,7 @@ struct TBuiltinFuncData { {"covariance", {"Covariance", "Agg", BuildAggrFuncFactoryCallback("CovarianceSample", "covariance_sample_traits_factory", TWO_ARGS, "Covariance")}}, {"covariancesample", {"CovarianceSample", "Agg", BuildAggrFuncFactoryCallback("CovarianceSample", "covariance_sample_traits_factory", TWO_ARGS)}}, {"covarsamp", {"CovarSamp", "Agg", BuildAggrFuncFactoryCallback("CovarianceSample", "covariance_sample_traits_factory", TWO_ARGS, "CovarSamp")}}, - {"covar", {"Covar","Agg",BuildAggrFuncFactoryCallback("CovarianceSample", "covariance_sample_traits_factory", TWO_ARGS, "Covar")}}, + {"covar", {"Covar", "Agg", BuildAggrFuncFactoryCallback("CovarianceSample", "covariance_sample_traits_factory", TWO_ARGS, "Covar")}}, {"covars", {"CovarS", "Agg", BuildAggrFuncFactoryCallback("CovarianceSample", "covariance_sample_traits_factory", TWO_ARGS, "CovarS")}}, {"covariancepopulation", {"CovariancePopulation", "Agg", BuildAggrFuncFactoryCallback("CovariancePopulation", "covariance_population_traits_factory", TWO_ARGS)}}, {"covarpop", {"CovarPop", "Agg", BuildAggrFuncFactoryCallback("CovariancePopulation", "covariance_population_traits_factory", TWO_ARGS, "CovarPop")}}, @@ -3436,56 +3481,54 @@ struct TBuiltinFuncData { // MatchRecognize navigation functions {"first", {"First", "MatchRec", BuildAggrFuncFactoryCallback("First", "first_traits_factory")}}, - {"last", {"Last", "MatchRec", BuildAggrFuncFactoryCallback("Last", "last_traits_factory")}} - }; + {"last", {"Last", "MatchRec", BuildAggrFuncFactoryCallback("Last", "last_traits_factory")}}}; return aggrFuncs; } TCoreFuncMap MakeCoreFuncs() { TCoreFuncMap coreFuncs = { - {"listindexof", { "IndexOf", 2, 2}}, - {"testbit", { "TestBit", 2, 2}}, - {"setbit", { "SetBit", 2, 2}}, - {"clearbit", { "ClearBit", 2, 2}}, - {"flipbit", { "FlipBit", 2, 2 }}, - {"toset", { "ToSet", 1, 1 }}, - {"setisdisjoint", { "SetIsDisjoint", 2, 2}}, - {"setintersection", { "SetIntersection", 2, 3}}, - {"setincludes", { "SetIncludes", 2, 2}}, - {"setunion", { "SetUnion", 2, 3}}, - {"setdifference", { "SetDifference", 2, 2}}, - {"setsymmetricdifference", { "SetSymmetricDifference", 2, 3}}, - {"listaggregate", { "ListAggregate", 2, 2}}, - {"dictaggregate", { "DictAggregate", 2, 2}}, - {"aggregatetransforminput", { "AggregateTransformInput", 2, 2}}, - {"aggregatetransformoutput", { "AggregateTransformOutput", 2, 2}}, - {"aggregateflatten", { "AggregateFlatten", 1, 1}}, - {"choosemembers", { "ChooseMembers", 2, 2}}, - {"removemembers", { "RemoveMembers", 2, 2}}, - {"forceremovemembers", { "ForceRemoveMembers", 2, 2}}, - {"structmembers", { "StructMembers", 1, 1}}, - {"gathermembers", { "GatherMembers", 1, 1}}, - {"renamemembers", { "RenameMembers", 2, 2}}, - {"forcerenamemembers", { "ForceRenameMembers", 2, 2}}, - {"spreadmembers", { "SpreadMembers", 2, 2}}, - {"forcespreadmembers", { "ForceSpreadMembers", 2, 2}}, - {"listfromtuple", { "ListFromTuple", 1, 1}}, - {"listtotuple", { "ListToTuple", 2, 2}}, - {"opaque", { "Opaque", 1, 1}}, + {"listindexof", {"IndexOf", 2, 2}}, + {"testbit", {"TestBit", 2, 2}}, + {"setbit", {"SetBit", 2, 2}}, + {"clearbit", {"ClearBit", 2, 2}}, + {"flipbit", {"FlipBit", 2, 2}}, + {"toset", {"ToSet", 1, 1}}, + {"setisdisjoint", {"SetIsDisjoint", 2, 2}}, + {"setintersection", {"SetIntersection", 2, 3}}, + {"setincludes", {"SetIncludes", 2, 2}}, + {"setunion", {"SetUnion", 2, 3}}, + {"setdifference", {"SetDifference", 2, 2}}, + {"setsymmetricdifference", {"SetSymmetricDifference", 2, 3}}, + {"listaggregate", {"ListAggregate", 2, 2}}, + {"dictaggregate", {"DictAggregate", 2, 2}}, + {"aggregatetransforminput", {"AggregateTransformInput", 2, 2}}, + {"aggregatetransformoutput", {"AggregateTransformOutput", 2, 2}}, + {"aggregateflatten", {"AggregateFlatten", 1, 1}}, + {"choosemembers", {"ChooseMembers", 2, 2}}, + {"removemembers", {"RemoveMembers", 2, 2}}, + {"forceremovemembers", {"ForceRemoveMembers", 2, 2}}, + {"structmembers", {"StructMembers", 1, 1}}, + {"gathermembers", {"GatherMembers", 1, 1}}, + {"renamemembers", {"RenameMembers", 2, 2}}, + {"forcerenamemembers", {"ForceRenameMembers", 2, 2}}, + {"spreadmembers", {"SpreadMembers", 2, 2}}, + {"forcespreadmembers", {"ForceSpreadMembers", 2, 2}}, + {"listfromtuple", {"ListFromTuple", 1, 1}}, + {"listtotuple", {"ListToTuple", 2, 2}}, + {"opaque", {"Opaque", 1, 1}}, }; return coreFuncs; } }; TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVector<TNodePtr>& args, - const TString& originalNameSpace, EAggregateMode aggMode, bool* mustUseNamed, bool warnOnYqlNameSpace) { - + const TString& originalNameSpace, EAggregateMode aggMode, bool* mustUseNamed, bool warnOnYqlNameSpace) { const TBuiltinFuncData* funcData = Singleton<TBuiltinFuncData>(); const TBuiltinFactoryCallbackMap& builtinFuncs = funcData->BuiltinFuncs; const TAggrFuncFactoryCallbackMap& aggrFuncs = funcData->AggrFuncs; const TCoreFuncMap& coreFuncs = funcData->CoreFuncs; - for (auto& arg: args) { + for (auto& arg : args) { if (!arg) { return nullptr; } @@ -3506,7 +3549,7 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec name = coreFunc->second.Name; if (args.size() < coreFunc->second.MinArgs || args.size() > coreFunc->second.MaxArgs) { return new TInvalidBuiltin(pos, TStringBuilder() << name << " expected from " - << coreFunc->second.MinArgs << " to " << coreFunc->second.MaxArgs << " arguments, but got: " << args.size()); + << coreFunc->second.MinArgs << " to " << coreFunc->second.MaxArgs << " arguments, but got: " << args.size()); } if (coreFunc->second.MinArgs != coreFunc->second.MaxArgs) { @@ -3529,9 +3572,9 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec if (ns == "datetime2") { if (!ctx.Warning(pos, TIssuesIds::YQL_DEPRECATED_DATETIME2, [](auto& out) { - out << "DateTime2:: is a temporary alias for DateTime:: which will be " - << "removed in the future, use DateTime:: instead"; - })) { + out << "DateTime2:: is a temporary alias for DateTime:: which will be " + << "removed in the future, use DateTime:: instead"; + })) { return nullptr; } } @@ -3561,9 +3604,9 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec if (ns == "yql" || ns == "@yql") { if (warnOnYqlNameSpace && GetEnv("YQL_DETERMINISTIC_MODE").empty()) { if (!ctx.Warning(pos, TIssuesIds::YQL_S_EXPRESSIONS_CALL, [](auto& out) { - out << "It is not recommended to directly access s-expressions functions via YQL::" << Endl - << "This mechanism is mostly intended for temporary workarounds or internal testing purposes"; - })) { + out << "It is not recommended to directly access s-expressions functions via YQL::" << Endl + << "This mechanism is mostly intended for temporary workarounds or internal testing purposes"; + })) { return nullptr; } } @@ -3574,10 +3617,7 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec } else if (moduleResource) { auto exportName = ns == "core" ? name : "$" + name; TVector<TNodePtr> applyArgs = { - new TCallNodeImpl(pos, "bind", { - BuildAtom(pos, ns + "_module", 0), BuildQuotedAtom(pos, exportName) - }) - }; + new TCallNodeImpl(pos, "bind", {BuildAtom(pos, ns + "_module", 0), BuildQuotedAtom(pos, exportName)})}; applyArgs.insert(applyArgs.end(), args.begin(), args.end()); return new TCallNodeImpl(pos, "Apply", applyArgs); } else if (ns == "hyperscan" || ns == "pcre" || ns == "pire" || ns.StartsWith("re2")) { @@ -3587,8 +3627,7 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec TVector<TNodePtr> multiArgs{ ns.StartsWith("re2") && lowerName == "capture" ? MakePair(pos, args) : args[0], new TCallNodeImpl(pos, "Void", 0, 0, {}), - args[0] - }; + args[0]}; auto fullName = moduleName + "." + name; return new TYqlTypeConfigUdf(pos, fullName, multiArgs, multiArgs.size() + 1); } else if (!(ns.StartsWith("re2") && (lowerName == "options" || lowerName == "isvalidregexp"))) { @@ -3653,11 +3692,10 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec auto settings = NYT::TNode::CreateMap(); auto makeUdfArgs = [&args, &pos, &settings]() { - return TVector<TNodePtr> { + return TVector<TNodePtr>{ args[0], new TCallNodeImpl(pos, "Void", {}), - BuildQuotedAtom(pos, NYT::NodeToYsonString(settings)) - }; + BuildQuotedAtom(pos, NYT::NodeToYsonString(settings))}; }; auto structNode = args[0]->GetStructNode(); @@ -3691,23 +3729,20 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec } else if (label == "EntitiesStrategy") { if (!item->IsLiteral() || item->GetLiteralType() != "String") { return new TInvalidBuiltin( - pos, TStringBuilder() << name << " entities strategy must be string literal" - ); + pos, TStringBuilder() << name << " entities strategy must be string literal"); } if (!EqualToOneOf(item->GetLiteralValue(), "whitelist", "blacklist")) { return new TInvalidBuiltin( pos, - TStringBuilder() << name << " got invalid entities strategy: expected 'whitelist' or 'blacklist'" - ); + TStringBuilder() << name << " got invalid entities strategy: expected 'whitelist' or 'blacklist'"); } settings(label, item->GetLiteralValue()); } else if (label == "Mode") { if (!item->IsLiteral() || item->GetLiteralType() != "String") { return new TInvalidBuiltin( - pos, TStringBuilder() << name << " mode must be string literal" - ); + pos, TStringBuilder() << name << " mode must be string literal"); } settings(label, item->GetLiteralValue()); @@ -3718,7 +3753,7 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec pos, TStringBuilder() << name << " got unsupported setting: " << label - << "; supported: Entities, EntitiesStrategy, BlockstatDict, ParseWithFat" ); + << "; supported: Entities, EntitiesStrategy, BlockstatDict, ParseWithFat"); } } @@ -3738,8 +3773,8 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec TVector<TNodePtr> pgConstArgs; if (!args.empty()) { pgConstArgs.push_back(args.front()); - pgConstArgs.push_back(new TCallNodeImpl(pos, "PgType", { BuildQuotedAtom(pos, - TString(type.StartsWith("pg") ? "" : "_") + type.substr(type.StartsWith("pg") ? 2 : 3), TNodeFlags::Default) })); + pgConstArgs.push_back(new TCallNodeImpl(pos, "PgType", {BuildQuotedAtom(pos, + TString(type.StartsWith("pg") ? "" : "_") + type.substr(type.StartsWith("pg") ? 2 : 3), TNodeFlags::Default)})); pgConstArgs.insert(pgConstArgs.end(), args.begin() + 1, args.end()); } return new TYqlPgConst(pos, pgConstArgs); @@ -3752,7 +3787,7 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec if (normalizedName == "decimal") { if (args.size() == 2) { - TVector<TNodePtr> dataTypeArgs = { BuildQuotedAtom(pos, "Decimal", TNodeFlags::Default) }; + TVector<TNodePtr> dataTypeArgs = {BuildQuotedAtom(pos, "Decimal", TNodeFlags::Default)}; for (auto& arg : args) { if (auto literal = arg->GetLiteral("Int32")) { dataTypeArgs.push_back(BuildQuotedAtom(pos, *literal, TNodeFlags::Default)); @@ -3810,15 +3845,15 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec } switch (ctx.GetColumnReferenceState()) { - case EColumnRefState::MatchRecognizeMeasures: - [[fallthrough]]; - case EColumnRefState::MatchRecognizeDefine: - return new TInvalidBuiltin(pos, "Cannot use aggregation factory inside the MATCH_RECOGNIZE context"); - default: - if ("first" == aggNormalizedName || "last" == aggNormalizedName) { - return new TInvalidBuiltin(pos, "Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context"); - } - return (*aggrCallback).second.Callback(pos, args, aggMode, true); + case EColumnRefState::MatchRecognizeMeasures: + [[fallthrough]]; + case EColumnRefState::MatchRecognizeDefine: + return new TInvalidBuiltin(pos, "Cannot use aggregation factory inside the MATCH_RECOGNIZE context"); + default: + if ("first" == aggNormalizedName || "last" == aggNormalizedName) { + return new TInvalidBuiltin(pos, "Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context"); + } + return (*aggrCallback).second.Callback(pos, args, aggMode, true); } } @@ -3838,17 +3873,17 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec auto aggrCallback = aggrFuncs.find(normalizedName); if (aggrCallback != aggrFuncs.end()) { switch (ctx.GetColumnReferenceState()) { - case EColumnRefState::MatchRecognizeMeasures: { - auto result = (*aggrCallback).second.Callback(pos, args, aggMode, false); - return BuildMatchRecognizeVarAccess(pos, std::move(result)); - } - case EColumnRefState::MatchRecognizeDefine: - return BuildMatchRecognizeDefineAggregate(ctx.Pos(), normalizedName, args); - default: - if ("first" == normalizedName || "last" == normalizedName) { - return new TInvalidBuiltin(pos, "Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context"); + case EColumnRefState::MatchRecognizeMeasures: { + auto result = (*aggrCallback).second.Callback(pos, args, aggMode, false); + return BuildMatchRecognizeVarAccess(pos, std::move(result)); } - return (*aggrCallback).second.Callback(pos, args, aggMode, false); + case EColumnRefState::MatchRecognizeDefine: + return BuildMatchRecognizeDefineAggregate(ctx.Pos(), normalizedName, args); + default: + if ("first" == normalizedName || "last" == normalizedName) { + return new TInvalidBuiltin(pos, "Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context"); + } + return (*aggrCallback).second.Callback(pos, args, aggMode, false); } } if (aggMode == EAggregateMode::Distinct || aggMode == EAggregateMode::OverWindowDistinct) { @@ -3883,9 +3918,7 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec } } } - return new TInvalidBuiltin(pos, TStringBuilder() << - (normalizedName == "asstruct" ? "AsStruct" : "StructType") << - " requires all argument to be named"); + return new TInvalidBuiltin(pos, TStringBuilder() << (normalizedName == "asstruct" ? "AsStruct" : "StructType") << " requires all argument to be named"); } else if (normalizedName == "expandstruct") { if (mustUseNamed) { if (!*mustUseNamed) { @@ -3913,14 +3946,14 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec TMaybe<TNodePtr> dflt; if (mustUseNamed && *mustUseNamed) { *mustUseNamed = false; - auto &positional = *args[0]->GetTupleNode(); + auto& positional = *args[0]->GetTupleNode(); if (positional.GetTupleSize() != (withDefault ? 2 : 1)) { return new TInvalidBuiltin(pos, TStringBuilder() << name - << " requires exactly " << (withDefault ? 2 : 1) << " positional arguments when named args are used"); + << " requires exactly " << (withDefault ? 2 : 1) << " positional arguments when named args are used"); } - auto &named = *args[1]->GetStructNode(); + auto& named = *args[1]->GetStructNode(); variant = positional.GetTupleElement(0); - auto &namedExprs = named.GetExprs(); + auto& namedExprs = named.GetExprs(); labels.reserve(namedExprs.size()); handlers.reserve(namedExprs.size()); for (size_t idx = 0; idx < namedExprs.size(); idx++) { @@ -3934,7 +3967,7 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec size_t minArgs = withDefault ? 2 : 1; if (args.size() < minArgs) { return new TInvalidBuiltin(pos, TStringBuilder() << name - << " requires at least " << minArgs << " positional arguments"); + << " requires at least " << minArgs << " positional arguments"); } variant = args[0]; labels.reserve(args.size() - minArgs); @@ -3979,8 +4012,8 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec TNodePtr externalTypes = nullptr; if (ns == "json") { if (!ctx.Warning(pos, TIssuesIds::YQL_DEPRECATED_JSON_UDF, [](auto& out) { - out << "Json UDF is deprecated. Please use JSON API instead"; - })) { + out << "Json UDF is deprecated. Please use JSON API instead"; + })) { return nullptr; } @@ -3989,8 +4022,7 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec if (lowerName == "serialize") { name = "SerializeJson"; lowerName = to_lower(name); - } - else if (lowerName == "parse") { + } else if (lowerName == "parse") { name = "ParseJson"; lowerName = to_lower(name); } @@ -4043,7 +4075,7 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec auto exprs = castedNamedArgs->GetExprs(); for (auto& arg : exprs) { if (arg->GetLabel() == "Timezone") { - arg = new TCallNodeImpl(pos, "TimezoneId", 1, 1, { arg }); + arg = new TCallNodeImpl(pos, "TimezoneId", 1, 1, {arg}); arg->SetLabel("TimezoneId"); } } @@ -4056,7 +4088,7 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec TNodePtr typeConfig = MakeTypeConfig(pos, ns, usedArgs); return BuildSqlCall(ctx, pos, nameSpace, name, usedArgs, positionalArgs, namedArgs, externalTypes, - TDeferredAtom(typeConfig, ctx), nullptr, nullptr, {}); + TDeferredAtom(typeConfig, ctx), nullptr, nullptr, {}); } void EnumerateBuiltins(const std::function<void(std::string_view name, std::string_view kind)>& callback) { diff --git a/yql/essentials/sql/v1/complete/analysis/global/base_visitor.cpp b/yql/essentials/sql/v1/complete/analysis/global/base_visitor.cpp index e89091a8331..38a20d0a9bb 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/base_visitor.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/base_visitor.cpp @@ -2,18 +2,18 @@ namespace NSQLComplete { - std::any TSQLv1BaseVisitor::VisitNullable(antlr4::ParserRuleContext* ctx) { - if (ctx == nullptr) { - return {}; - } - return visit(ctx); +std::any TSQLv1BaseVisitor::VisitNullable(antlr4::ParserRuleContext* ctx) { + if (ctx == nullptr) { + return {}; } + return visit(ctx); +} - std::any TSQLv1BaseVisitor::aggregateResult(std::any aggregate, std::any nextResult) { - if (nextResult.has_value()) { - return nextResult; - } - return aggregate; +std::any TSQLv1BaseVisitor::aggregateResult(std::any aggregate, std::any nextResult) { + if (nextResult.has_value()) { + return nextResult; } + return aggregate; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/base_visitor.h b/yql/essentials/sql/v1/complete/analysis/global/base_visitor.h index 4c223e7e7f8..c3ad227e90e 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/base_visitor.h +++ b/yql/essentials/sql/v1/complete/analysis/global/base_visitor.h @@ -4,10 +4,10 @@ namespace NSQLComplete { - class TSQLv1BaseVisitor: public SQLv1Antlr4BaseVisitor { - protected: - std::any VisitNullable(antlr4::ParserRuleContext* ctx); - std::any aggregateResult(std::any aggregate, std::any nextResult) override; - }; +class TSQLv1BaseVisitor: public SQLv1Antlr4BaseVisitor { +protected: + std::any VisitNullable(antlr4::ParserRuleContext* ctx); + std::any aggregateResult(std::any aggregate, std::any nextResult) override; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/column.cpp b/yql/essentials/sql/v1/complete/analysis/global/column.cpp index d8c73e00b7f..c8831412515 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/column.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/column.cpp @@ -12,382 +12,382 @@ namespace NSQLComplete { - namespace { +namespace { - class TInferenceVisitor: public TSQLv1BaseVisitor { - public: - TInferenceVisitor(const TNamedNodes* nodes) - : Nodes_(nodes) - { - } - - std::any visitJoin_source(SQLv1::Join_sourceContext* ctx) override { - return AccumulatingVisit(ctx->flatten_source()); - } - - std::any visitNamed_single_source(SQLv1::Named_single_sourceContext* ctx) override { - SQLv1::Single_sourceContext* singleSource = ctx->single_source(); - if (singleSource == nullptr) { - return {}; - } +class TInferenceVisitor: public TSQLv1BaseVisitor { +public: + TInferenceVisitor(const TNamedNodes* nodes) + : Nodes_(nodes) + { + } - std::any any = visit(singleSource); - if (!any.has_value()) { - return {}; - } - TColumnContext context = std::move(std::any_cast<TColumnContext>(any)); + std::any visitJoin_source(SQLv1::Join_sourceContext* ctx) override { + return AccumulatingVisit(ctx->flatten_source()); + } - TMaybe<TString> alias = GetAlias(ctx); - if (alias.Empty()) { - return context; - } + std::any visitNamed_single_source(SQLv1::Named_single_sourceContext* ctx) override { + SQLv1::Single_sourceContext* singleSource = ctx->single_source(); + if (singleSource == nullptr) { + return {}; + } - return std::move(context).Renamed(*alias); - } + std::any any = visit(singleSource); + if (!any.has_value()) { + return {}; + } + TColumnContext context = std::move(std::any_cast<TColumnContext>(any)); - std::any visitTable_ref(SQLv1::Table_refContext* ctx) override { - if (TMaybe<TString> path; (path = GetObjectId(ctx->table_key())) || - (path = GetObjectId(ctx->bind_parameter()))) { - return VisitTableRefPath(ctx, std::move(*path)); - } + TMaybe<TString> alias = GetAlias(ctx); + if (alias.Empty()) { + return context; + } - if (TMaybe<TFunctionContext> function = GetFunction(ctx, *Nodes_)) { - return VisitTableRefFunction(std::move(*function)); - } + return std::move(context).Renamed(*alias); + } - if (auto* bind_parameter = ctx->bind_parameter()) { - return visit(bind_parameter); - } + std::any visitTable_ref(SQLv1::Table_refContext* ctx) override { + if (TMaybe<TString> path; (path = GetObjectId(ctx->table_key())) || + (path = GetObjectId(ctx->bind_parameter()))) { + return VisitTableRefPath(ctx, std::move(*path)); + } - return {}; - } + if (TMaybe<TFunctionContext> function = GetFunction(ctx, *Nodes_)) { + return VisitTableRefFunction(std::move(*function)); + } - std::any visitSelect_stmt(SQLv1::Select_stmtContext* ctx) override { - return AccumulatingVisit(ctx->select_stmt_intersect()); - } + if (auto* bind_parameter = ctx->bind_parameter()) { + return visit(bind_parameter); + } - std::any visitSelect_core(SQLv1::Select_coreContext* ctx) override { - TColumnContext without; - if (std::any any = VisitNullable(ctx->without_column_list()); any.has_value()) { - without = std::move(std::any_cast<TColumnContext>(any)); - } + return {}; + } - TColumnContext context = AccumulatingVisit(ctx->result_column()); - auto asterisks = std::ranges::partition(context.Columns, [](const TColumnId& x) { - return x.Name != "*"; - }); + std::any visitSelect_stmt(SQLv1::Select_stmtContext* ctx) override { + return AccumulatingVisit(ctx->select_stmt_intersect()); + } - if (std::ranges::empty(asterisks)) { - return context; - } + std::any visitSelect_core(SQLv1::Select_coreContext* ctx) override { + TColumnContext without; + if (std::any any = VisitNullable(ctx->without_column_list()); any.has_value()) { + without = std::move(std::any_cast<TColumnContext>(any)); + } - TColumnContext source = AccumulatingVisit(ctx->join_source()); + TColumnContext context = AccumulatingVisit(ctx->result_column()); + auto asterisks = std::ranges::partition(context.Columns, [](const TColumnId& x) { + return x.Name != "*"; + }); - TColumnContext imported; - for (const TColumnId& qualified : asterisks) { - TMaybe<TStringBuf> alias = qualified.TableAlias; - if (alias->Empty()) { - alias = Nothing(); - } + if (std::ranges::empty(asterisks)) { + return context; + } - TColumnContext aliased = source.ExtractAliased(alias); - imported = std::move(imported) | std::move(aliased); - } + TColumnContext source = AccumulatingVisit(ctx->join_source()); - context.Columns.erase(asterisks.begin(), asterisks.end()); - imported = std::move(imported).Renamed(""); - return std::move(context) | std::move(imported) | std::move(without); + TColumnContext imported; + for (const TColumnId& qualified : asterisks) { + TMaybe<TStringBuf> alias = qualified.TableAlias; + if (alias->Empty()) { + alias = Nothing(); } - std::any visitResult_column(SQLv1::Result_columnContext* ctx) override { - if (ctx->opt_id_prefix() == nullptr && ctx->TOKEN_ASTERISK() != nullptr) { - return TColumnContext::Asterisk(); - } + TColumnContext aliased = source.ExtractAliased(alias); + imported = std::move(imported) | std::move(aliased); + } - if (ctx->opt_id_prefix() != nullptr && ctx->TOKEN_ASTERISK() != nullptr) { - TMaybe<TString> alias = GetColumnId(ctx->opt_id_prefix()->an_id()); - if (alias.Empty()) { - return TColumnContext::Asterisk(); - } - - return TColumnContext{ - .Columns = { - {.TableAlias = std::move(*alias), .Name = "*"}, - }, - }; - } + context.Columns.erase(asterisks.begin(), asterisks.end()); + imported = std::move(imported).Renamed(""); + return std::move(context) | std::move(imported) | std::move(without); + } - TMaybe<TString> column = GetAlias(ctx); - if (column.Defined()) { - return TColumnContext{ - .Columns = { - {.Name = std::move(*column)}, - }, - }; - } + std::any visitResult_column(SQLv1::Result_columnContext* ctx) override { + if (ctx->opt_id_prefix() == nullptr && ctx->TOKEN_ASTERISK() != nullptr) { + return TColumnContext::Asterisk(); + } - return {}; + if (ctx->opt_id_prefix() != nullptr && ctx->TOKEN_ASTERISK() != nullptr) { + TMaybe<TString> alias = GetColumnId(ctx->opt_id_prefix()->an_id()); + if (alias.Empty()) { + return TColumnContext::Asterisk(); } - std::any visitWithout_column_list(SQLv1::Without_column_listContext* ctx) override { - return AccumulatingVisit(ctx->without_column_name()); + return TColumnContext{ + .Columns = { + {.TableAlias = std::move(*alias), .Name = "*"}, + }, }; + } - std::any visitWithout_column_name(SQLv1::Without_column_nameContext* ctx) override { - TString table = GetObjectId(ctx->an_id(0)).GetOrElse(""); - TMaybe<TString> column = GetColumnId(ctx->an_id(1)).Or([&] { - return GetColumnId(ctx->an_id_without()); - }); + TMaybe<TString> column = GetAlias(ctx); + if (column.Defined()) { + return TColumnContext{ + .Columns = { + {.Name = std::move(*column)}, + }, + }; + } - if (column.Empty()) { - return {}; - } + return {}; + } - return TColumnContext{ - .WithoutByTableAlias = { - {std::move(table), {{std::move(*column)}}}, - }, - }; - } + std::any visitWithout_column_list(SQLv1::Without_column_listContext* ctx) override { + return AccumulatingVisit(ctx->without_column_name()); + }; - std::any visitBind_parameter(SQLv1::Bind_parameterContext* ctx) override { - TMaybe<TString> name = NSQLComplete::GetName(ctx); - if (!name) { - return {}; - } + std::any visitWithout_column_name(SQLv1::Without_column_nameContext* ctx) override { + TString table = GetObjectId(ctx->an_id(0)).GetOrElse(""); + TMaybe<TString> column = GetColumnId(ctx->an_id(1)).Or([&] { + return GetColumnId(ctx->an_id_without()); + }); - const TNamedNode* node = Nodes_->FindPtr(*name); - if (!node) { - return {}; - } + if (column.Empty()) { + return {}; + } - if (Resolving_.contains(*name)) { - return {}; - } + return TColumnContext{ + .WithoutByTableAlias = { + {std::move(table), {{std::move(*column)}}}, + }, + }; + } - Resolving_.emplace(*name); - Y_DEFER { - Resolving_.erase(*name); - }; + std::any visitBind_parameter(SQLv1::Bind_parameterContext* ctx) override { + TMaybe<TString> name = NSQLComplete::GetName(ctx); + if (!name) { + return {}; + } - auto* rule = std::visit([](auto&& arg) -> antlr4::ParserRuleContext* { - using T = std::decay_t<decltype(arg)>; + const TNamedNode* node = Nodes_->FindPtr(*name); + if (!node) { + return {}; + } - constexpr bool isRule = std::is_pointer_v<T> || - std::is_base_of_v< - antlr4::ParserRuleContext*, - std::remove_pointer_t<T>>; + if (Resolving_.contains(*name)) { + return {}; + } - if constexpr (isRule) { - return arg; - } + Resolving_.emplace(*name); + Y_DEFER { + Resolving_.erase(*name); + }; - return nullptr; - }, *node); + auto* rule = std::visit([](auto&& arg) -> antlr4::ParserRuleContext* { + using T = std::decay_t<decltype(arg)>; - if (!rule) { - return {}; - } + constexpr bool isRule = std::is_pointer_v<T> || + std::is_base_of_v< + antlr4::ParserRuleContext*, + std::remove_pointer_t<T>>; - return visit(rule); + if constexpr (isRule) { + return arg; } - private: - std::any VisitTableRefPath(SQLv1::Table_refContext* ctx, TString path) { - TString cluster = GetObjectId(ctx->cluster_expr()).GetOrElse(""); - return TColumnContext{ - .Tables = { - TTableId{std::move(cluster), std::move(path)}, - }, - }; - } + return nullptr; + }, *node); - std::any VisitTableRefFunction(TFunctionContext function) { - TString cluster = function.Cluster.GetOrElse({}).Name; - - TString path; - function.Name = NormalizeName(function.Name); - if (function.Name == "concat" && function.Arg0) { - path = std::move(*function.Arg0); - } else if (function.Name == "range" && function.Arg0 && function.Arg1) { - path = std::move(*function.Arg0); - path.append('/').append(*function.Arg1); - } else { - return {}; - } + if (!rule) { + return {}; + } - return TColumnContext{ - .Tables = { - TTableId{std::move(cluster), std::move(path)}, - }, - }; - } + return visit(rule); + } - TMaybe<TString> GetAlias(SQLv1::Named_single_sourceContext* ctx) const { - TMaybe<TString> alias = GetColumnId(ctx->an_id()); - alias = alias.Defined() ? alias : GetColumnId(ctx->an_id_as_compat()); - return alias; - } +private: + std::any VisitTableRefPath(SQLv1::Table_refContext* ctx, TString path) { + TString cluster = GetObjectId(ctx->cluster_expr()).GetOrElse(""); + return TColumnContext{ + .Tables = { + TTableId{std::move(cluster), std::move(path)}, + }, + }; + } - TMaybe<TString> GetAlias(SQLv1::Result_columnContext* ctx) const { - antlr4::ParserRuleContext* id = nullptr; - if (ctx->TOKEN_AS() == nullptr) { - id = ctx->expr(); - } else { - id = ctx->an_id_or_type(); - id = id ? id : ctx->an_id_as_compat(); - } - return GetColumnId(id); - } + std::any VisitTableRefFunction(TFunctionContext function) { + TString cluster = function.Cluster.GetOrElse({}).Name; + + TString path; + function.Name = NormalizeName(function.Name); + if (function.Name == "concat" && function.Arg0) { + path = std::move(*function.Arg0); + } else if (function.Name == "range" && function.Arg0 && function.Arg1) { + path = std::move(*function.Arg0); + path.append('/').append(*function.Arg1); + } else { + return {}; + } - TMaybe<TColumnContext> Head(SQLv1::Select_coreContext* ctx) { - SQLv1::Result_columnContext* column = ctx->result_column(0); - if (column == nullptr) { - return Nothing(); - } + return TColumnContext{ + .Tables = { + TTableId{std::move(cluster), std::move(path)}, + }, + }; + } - std::any any = visit(column); - if (!any.has_value()) { - return Nothing(); - } + TMaybe<TString> GetAlias(SQLv1::Named_single_sourceContext* ctx) const { + TMaybe<TString> alias = GetColumnId(ctx->an_id()); + alias = alias.Defined() ? alias : GetColumnId(ctx->an_id_as_compat()); + return alias; + } - return std::any_cast<TColumnContext>(any); - } + TMaybe<TString> GetAlias(SQLv1::Result_columnContext* ctx) const { + antlr4::ParserRuleContext* id = nullptr; + if (ctx->TOKEN_AS() == nullptr) { + id = ctx->expr(); + } else { + id = ctx->an_id_or_type(); + id = id ? id : ctx->an_id_as_compat(); + } + return GetColumnId(id); + } - template <std::derived_from<antlr4::ParserRuleContext> T> - TColumnContext AccumulatingVisit(std::vector<T*> contexts) { - return Accumulate( - contexts, - TColumnContext(), - [this](TColumnContext&& acc, T* ctx) { - std::any any = visit(ctx); - if (!any.has_value()) { - return acc; - } - - TColumnContext child = std::move(std::any_cast<TColumnContext>(any)); - return std::move(acc) | std::move(child); - }); - } + TMaybe<TColumnContext> Head(SQLv1::Select_coreContext* ctx) { + SQLv1::Result_columnContext* column = ctx->result_column(0); + if (column == nullptr) { + return Nothing(); + } - TMaybe<TString> GetColumnId(antlr4::ParserRuleContext* ctx) const { - if (!ctx) { - return Nothing(); - } + std::any any = visit(column); + if (!any.has_value()) { + return Nothing(); + } + + return std::any_cast<TColumnContext>(any); + } - TPartialValue value = PartiallyEvaluate(ctx, *Nodes_); - if (!std::holds_alternative<TIdentifier>(value)) { - return Nothing(); + template <std::derived_from<antlr4::ParserRuleContext> T> + TColumnContext AccumulatingVisit(std::vector<T*> contexts) { + return Accumulate( + contexts, + TColumnContext(), + [this](TColumnContext&& acc, T* ctx) { + std::any any = visit(ctx); + if (!any.has_value()) { + return acc; } - return std::get<TIdentifier>(value); - } + TColumnContext child = std::move(std::any_cast<TColumnContext>(any)); + return std::move(acc) | std::move(child); + }); + } - TMaybe<TString> GetObjectId(antlr4::ParserRuleContext* ctx) const { - if (!ctx) { - return Nothing(); - } + TMaybe<TString> GetColumnId(antlr4::ParserRuleContext* ctx) const { + if (!ctx) { + return Nothing(); + } - return ToObjectRef(PartiallyEvaluate(ctx, *Nodes_)); - } + TPartialValue value = PartiallyEvaluate(ctx, *Nodes_); + if (!std::holds_alternative<TIdentifier>(value)) { + return Nothing(); + } - THashSet<TString> Resolving_; - const TNamedNodes* Nodes_; - }; + return std::get<TIdentifier>(value); + } - class TEnclosingSelectVisitor: public TSQLv1NarrowingVisitor { - public: - explicit TEnclosingSelectVisitor(const TParsedInput& input) - : TSQLv1NarrowingVisitor(input) - { - } + TMaybe<TString> GetObjectId(antlr4::ParserRuleContext* ctx) const { + if (!ctx) { + return Nothing(); + } - std::any visitSelect_core(SQLv1::Select_coreContext* ctx) override { - if (!IsEnclosing(ctx)) { - return {}; - } + return ToObjectRef(PartiallyEvaluate(ctx, *Nodes_)); + } - Enclosing_ = ctx; - return visitChildren(ctx); - } + THashSet<TString> Resolving_; + const TNamedNodes* Nodes_; +}; - SQLv1::Select_coreContext* GetEnclosing() && { - return Enclosing_; - } +class TEnclosingSelectVisitor: public TSQLv1NarrowingVisitor { +public: + explicit TEnclosingSelectVisitor(const TParsedInput& input) + : TSQLv1NarrowingVisitor(input) + { + } - private: - SQLv1::Select_coreContext* Enclosing_ = nullptr; - }; + std::any visitSelect_core(SQLv1::Select_coreContext* ctx) override { + if (!IsEnclosing(ctx)) { + return {}; + } - class TVisitor: public TSQLv1NarrowingVisitor { - public: - TVisitor(const TParsedInput& input, const TNamedNodes* nodes) - : TSQLv1NarrowingVisitor(input) - , Nodes_(nodes) - { - } + Enclosing_ = ctx; + return visitChildren(ctx); + } - std::any visitSql_stmt_core(SQLv1::Sql_stmt_coreContext* ctx) override { - if (ctx->named_nodes_stmt() || IsEnclosing(ctx)) { - return visitChildren(ctx); - } - return {}; - } + SQLv1::Select_coreContext* GetEnclosing() && { + return Enclosing_; + } - std::any visitSelect_core(SQLv1::Select_coreContext* ctx) override { - if (IsEnclosingStrict(ctx->window_clause()) || - IsEnclosingStrict(ctx->ext_order_by_clause())) { - return TInferenceVisitor(Nodes_).visit(ctx); - } +private: + SQLv1::Select_coreContext* Enclosing_ = nullptr; +}; + +class TVisitor: public TSQLv1NarrowingVisitor { +public: + TVisitor(const TParsedInput& input, const TNamedNodes* nodes) + : TSQLv1NarrowingVisitor(input) + , Nodes_(nodes) + { + } - auto* source = ctx->join_source(0); - source = source == nullptr ? ctx->join_source(1) : source; + std::any visitSql_stmt_core(SQLv1::Sql_stmt_coreContext* ctx) override { + if (ctx->named_nodes_stmt() || IsEnclosing(ctx)) { + return visitChildren(ctx); + } + return {}; + } - if (!source) { - return {}; - } + std::any visitSelect_core(SQLv1::Select_coreContext* ctx) override { + if (IsEnclosingStrict(ctx->window_clause()) || + IsEnclosingStrict(ctx->ext_order_by_clause())) { + return TInferenceVisitor(Nodes_).visit(ctx); + } - auto sources = source->flatten_source(); - auto** flatten = FindIfPtr(sources, [&](auto* ctx) { - return IsEnclosingStrict(ctx); - }); + auto* source = ctx->join_source(0); + source = source == nullptr ? ctx->join_source(1) : source; - if (flatten) { - return visitChildren(*flatten); - } + if (!source) { + return {}; + } - return TInferenceVisitor(Nodes_).visit(source); - } + auto sources = source->flatten_source(); + auto** flatten = FindIfPtr(sources, [&](auto* ctx) { + return IsEnclosingStrict(ctx); + }); - private: - bool IsEnclosingStrict(antlr4::ParserRuleContext* ctx) const { - return ctx != nullptr && IsEnclosing(ctx); - } + if (flatten) { + return visitChildren(*flatten); + } - const TNamedNodes* Nodes_; - }; + return TInferenceVisitor(Nodes_).visit(source); + } - antlr4::ParserRuleContext* Enclosing(const TParsedInput& input) { - TEnclosingSelectVisitor visitor(input); - visitor.visit(input.SqlQuery); +private: + bool IsEnclosingStrict(antlr4::ParserRuleContext* ctx) const { + return ctx != nullptr && IsEnclosing(ctx); + } - antlr4::ParserRuleContext* ctx = std::move(visitor).GetEnclosing(); - if (!ctx) { - ctx = input.SqlQuery; - } + const TNamedNodes* Nodes_; +}; - return ctx; - } +antlr4::ParserRuleContext* Enclosing(const TParsedInput& input) { + TEnclosingSelectVisitor visitor(input); + visitor.visit(input.SqlQuery); + + antlr4::ParserRuleContext* ctx = std::move(visitor).GetEnclosing(); + if (!ctx) { + ctx = input.SqlQuery; + } - } // namespace + return ctx; +} - TMaybe<TColumnContext> InferColumnContext(TParsedInput input, const TNamedNodes& nodes) { - // TODO: add utility `auto ToMaybe<T>(std::any any) -> TMaybe<T>` - std::any result = TVisitor(input, &nodes).visit(Enclosing(input)); - if (!result.has_value()) { - return Nothing(); - } - return std::any_cast<TColumnContext>(result); +} // namespace + +TMaybe<TColumnContext> InferColumnContext(TParsedInput input, const TNamedNodes& nodes) { + // TODO: add utility `auto ToMaybe<T>(std::any any) -> TMaybe<T>` + std::any result = TVisitor(input, &nodes).visit(Enclosing(input)); + if (!result.has_value()) { + return Nothing(); } + return std::any_cast<TColumnContext>(result); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/column.h b/yql/essentials/sql/v1/complete/analysis/global/column.h index 0caa617ea7c..d0ec5485402 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/column.h +++ b/yql/essentials/sql/v1/complete/analysis/global/column.h @@ -6,6 +6,6 @@ namespace NSQLComplete { - TMaybe<TColumnContext> InferColumnContext(TParsedInput input, const TNamedNodes& nodes); +TMaybe<TColumnContext> InferColumnContext(TParsedInput input, const TNamedNodes& nodes); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/evaluate.cpp b/yql/essentials/sql/v1/complete/analysis/global/evaluate.cpp index 2c07f470c6a..74b4266c171 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/evaluate.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/evaluate.cpp @@ -9,247 +9,247 @@ namespace NSQLComplete { - namespace { +namespace { - class TVisitor: public SQLv1Antlr4BaseVisitor { - public: - explicit TVisitor(const TNamedNodes* nodes) - : Nodes_(nodes) - { - } - - std::any visitCluster_expr(SQLv1::Cluster_exprContext* ctx) override { - if (auto* x = ctx->pure_column_or_named()) { - return visit(x); - } - return defaultResult(); - } - - std::any visitTable_key(SQLv1::Table_keyContext* ctx) override { - if (auto* x = ctx->id_table_or_type()) { - return visit(x); - } - return defaultResult(); - } - - std::any visitUnary_casual_subexpr(SQLv1::Unary_casual_subexprContext* ctx) override { - TPartialValue prev; - if (auto* x = ctx->id_expr()) { - prev = std::any_cast<TPartialValue>(visit(x)); - } else if (auto* x = ctx->atom_expr()) { - prev = std::any_cast<TPartialValue>(visit(x)); - } - - auto next = std::any_cast<TPartialValue>(visit(ctx->unary_subexpr_suffix())); - if (!IsDefined(next)) { - return prev; - } +class TVisitor: public SQLv1Antlr4BaseVisitor { +public: + explicit TVisitor(const TNamedNodes* nodes) + : Nodes_(nodes) + { + } - return defaultResult(); - } + std::any visitCluster_expr(SQLv1::Cluster_exprContext* ctx) override { + if (auto* x = ctx->pure_column_or_named()) { + return visit(x); + } + return defaultResult(); + } - std::any visitMul_subexpr(SQLv1::Mul_subexprContext* ctx) override { - auto args = ctx->con_subexpr(); - Y_ENSURE(!args.empty()); + std::any visitTable_key(SQLv1::Table_keyContext* ctx) override { + if (auto* x = ctx->id_table_or_type()) { + return visit(x); + } + return defaultResult(); + } - if (args.size() == 1) { - return visit(args[0]); - } + std::any visitUnary_casual_subexpr(SQLv1::Unary_casual_subexprContext* ctx) override { + TPartialValue prev; + if (auto* x = ctx->id_expr()) { + prev = std::any_cast<TPartialValue>(visit(x)); + } else if (auto* x = ctx->atom_expr()) { + prev = std::any_cast<TPartialValue>(visit(x)); + } - NYT::TNode result; - for (auto* arg : args) { - if (!arg) { - return defaultResult(); - } + auto next = std::any_cast<TPartialValue>(visit(ctx->unary_subexpr_suffix())); + if (!IsDefined(next)) { + return prev; + } - auto value = std::any_cast<TPartialValue>(visit(arg)); - if (!std::holds_alternative<NYT::TNode>(value)) { - return defaultResult(); - } + return defaultResult(); + } - auto node = std::get<NYT::TNode>(value); - auto maybe = Concat(std::move(result), std::move(node)); - if (!maybe) { - return defaultResult(); - } + std::any visitMul_subexpr(SQLv1::Mul_subexprContext* ctx) override { + auto args = ctx->con_subexpr(); + Y_ENSURE(!args.empty()); - result = std::move(*maybe); - } - return TPartialValue(std::move(result)); - } + if (args.size() == 1) { + return visit(args[0]); + } - std::any visitKeyword_compat(SQLv1::Keyword_compatContext* ctx) override { - return TPartialValue(GetText(ctx)); + NYT::TNode result; + for (auto* arg : args) { + if (!arg) { + return defaultResult(); } - std::any visitKeyword_expr_uncompat(SQLv1::Keyword_expr_uncompatContext* ctx) override { - return TPartialValue(GetText(ctx)); + auto value = std::any_cast<TPartialValue>(visit(arg)); + if (!std::holds_alternative<NYT::TNode>(value)) { + return defaultResult(); } - std::any visitKeyword_table_uncompat(SQLv1::Keyword_table_uncompatContext* ctx) override { - return TPartialValue(GetText(ctx)); + auto node = std::get<NYT::TNode>(value); + auto maybe = Concat(std::move(result), std::move(node)); + if (!maybe) { + return defaultResult(); } - std::any visitKeyword_select_uncompat(SQLv1::Keyword_select_uncompatContext* ctx) override { - return TPartialValue(GetText(ctx)); - } + result = std::move(*maybe); + } + return TPartialValue(std::move(result)); + } - std::any visitKeyword_alter_uncompat(SQLv1::Keyword_alter_uncompatContext* ctx) override { - return TPartialValue(GetText(ctx)); - } + std::any visitKeyword_compat(SQLv1::Keyword_compatContext* ctx) override { + return TPartialValue(GetText(ctx)); + } - std::any visitKeyword_in_uncompat(SQLv1::Keyword_in_uncompatContext* ctx) override { - return TPartialValue(GetText(ctx)); - } + std::any visitKeyword_expr_uncompat(SQLv1::Keyword_expr_uncompatContext* ctx) override { + return TPartialValue(GetText(ctx)); + } - std::any visitKeyword_window_uncompat(SQLv1::Keyword_window_uncompatContext* ctx) override { - return TPartialValue(GetText(ctx)); - } + std::any visitKeyword_table_uncompat(SQLv1::Keyword_table_uncompatContext* ctx) override { + return TPartialValue(GetText(ctx)); + } - std::any visitKeyword_hint_uncompat(SQLv1::Keyword_hint_uncompatContext* ctx) override { - return TPartialValue(GetText(ctx)); - } + std::any visitKeyword_select_uncompat(SQLv1::Keyword_select_uncompatContext* ctx) override { + return TPartialValue(GetText(ctx)); + } - std::any visitTerminal(antlr4::tree::TerminalNode* node) override { - switch (node->getSymbol()->getType()) { - case SQLv1::TOKEN_ID_QUOTED: - return TPartialValue(TString(Unquoted(GetText(node)))); - case SQLv1::TOKEN_ID_PLAIN: - return TPartialValue(GetText(node)); - case SQLv1::TOKEN_STRING_VALUE: - if (auto content = GetContent(node)) { - return TPartialValue(NYT::TNode(std::move(*content))); - } - } - return defaultResult(); - } + std::any visitKeyword_alter_uncompat(SQLv1::Keyword_alter_uncompatContext* ctx) override { + return TPartialValue(GetText(ctx)); + } - std::any visitBind_parameter(SQLv1::Bind_parameterContext* ctx) override { - TMaybe<std::string> id = GetName(ctx); - if (id.Empty()) { - return defaultResult(); - } + std::any visitKeyword_in_uncompat(SQLv1::Keyword_in_uncompatContext* ctx) override { + return TPartialValue(GetText(ctx)); + } - return EvaluateNode(std::move(*id)); - } + std::any visitKeyword_window_uncompat(SQLv1::Keyword_window_uncompatContext* ctx) override { + return TPartialValue(GetText(ctx)); + } - protected: - std::any defaultResult() override { - return TPartialValue(std::monostate()); - } + std::any visitKeyword_hint_uncompat(SQLv1::Keyword_hint_uncompatContext* ctx) override { + return TPartialValue(GetText(ctx)); + } - private: - TPartialValue EvaluateNode(std::string name) { - const TNamedNode* node = Nodes_->FindPtr(name); - if (!node) { - return std::monostate(); + std::any visitTerminal(antlr4::tree::TerminalNode* node) override { + switch (node->getSymbol()->getType()) { + case SQLv1::TOKEN_ID_QUOTED: + return TPartialValue(TString(Unquoted(GetText(node)))); + case SQLv1::TOKEN_ID_PLAIN: + return TPartialValue(GetText(node)); + case SQLv1::TOKEN_STRING_VALUE: + if (auto content = GetContent(node)) { + return TPartialValue(NYT::TNode(std::move(*content))); } + } + return defaultResult(); + } - if (std::holds_alternative<NYT::TNode>(*node)) { - return std::get<NYT::TNode>(*node); - } + std::any visitBind_parameter(SQLv1::Bind_parameterContext* ctx) override { + TMaybe<std::string> id = GetName(ctx); + if (id.Empty()) { + return defaultResult(); + } - if (std::holds_alternative<SQLv1::ExprContext*>(*node)) { - if (Resolving_.contains(name)) { - return std::monostate(); - } + return EvaluateNode(std::move(*id)); + } - Resolving_.emplace(name); - Y_DEFER { - Resolving_.erase(name); - }; +protected: + std::any defaultResult() override { + return TPartialValue(std::monostate()); + } - std::any any = visit(std::get<SQLv1::ExprContext*>(*node)); - return std::any_cast<TPartialValue>(std::move(any)); - } +private: + TPartialValue EvaluateNode(std::string name) { + const TNamedNode* node = Nodes_->FindPtr(name); + if (!node) { + return std::monostate(); + } + + if (std::holds_alternative<NYT::TNode>(*node)) { + return std::get<NYT::TNode>(*node); + } + if (std::holds_alternative<SQLv1::ExprContext*>(*node)) { + if (Resolving_.contains(name)) { return std::monostate(); } - TMaybe<NYT::TNode> Concat(NYT::TNode lhs, NYT::TNode rhs) { - if (!lhs.HasValue()) { - return rhs; - } + Resolving_.emplace(name); + Y_DEFER { + Resolving_.erase(name); + }; - NYT::TNode::EType type = rhs.GetType(); - if (type != lhs.GetType()) { - return Nothing(); - } + std::any any = visit(std::get<SQLv1::ExprContext*>(*node)); + return std::any_cast<TPartialValue>(std::move(any)); + } - switch (type) { - case NYT::TNode::String: - return lhs.AsString() + rhs.AsString(); - case NYT::TNode::Int64: - case NYT::TNode::Uint64: - case NYT::TNode::Double: - case NYT::TNode::Bool: - case NYT::TNode::List: - case NYT::TNode::Map: - case NYT::TNode::Undefined: - case NYT::TNode::Null: - return Nothing(); - } - } + return std::monostate(); + } - TIdentifier GetText(antlr4::tree::ParseTree* tree) const { - return TIdentifier(tree->getText()); - } + TMaybe<NYT::TNode> Concat(NYT::TNode lhs, NYT::TNode rhs) { + if (!lhs.HasValue()) { + return rhs; + } - TMaybe<TString> GetContent(antlr4::tree::TerminalNode* node) const { - static RE2 regex(R"re(["']([^"'\\]*)["'])re"); + NYT::TNode::EType type = rhs.GetType(); + if (type != lhs.GetType()) { + return Nothing(); + } - TString text = GetText(node); - TString content; - if (!RE2::FullMatch(text, regex, &content)) { - return Nothing(); - } + switch (type) { + case NYT::TNode::String: + return lhs.AsString() + rhs.AsString(); + case NYT::TNode::Int64: + case NYT::TNode::Uint64: + case NYT::TNode::Double: + case NYT::TNode::Bool: + case NYT::TNode::List: + case NYT::TNode::Map: + case NYT::TNode::Undefined: + case NYT::TNode::Null: + return Nothing(); + } + } - return content; - } + TIdentifier GetText(antlr4::tree::ParseTree* tree) const { + return TIdentifier(tree->getText()); + } - THashSet<std::string> Resolving_; - const TNamedNodes* Nodes_; - }; + TMaybe<TString> GetContent(antlr4::tree::TerminalNode* node) const { + static RE2 regex(R"re(["']([^"'\\]*)["'])re"); - TPartialValue EvaluateG(antlr4::ParserRuleContext* ctx, const TNamedNodes& nodes) { - return std::any_cast<TPartialValue>(TVisitor(&nodes).visit(ctx)); + TString text = GetText(node); + TString content; + if (!RE2::FullMatch(text, regex, &content)) { + return Nothing(); } - } // namespace - - bool IsDefined(const TPartialValue& value) { - return !std::holds_alternative<std::monostate>(value); + return content; } - TMaybe<TString> ToObjectRef(const TPartialValue& value) { - return std::visit([](const auto& value) -> TMaybe<TString> { - using T = std::decay_t<decltype(value)>; - if constexpr (std::is_same_v<T, NYT::TNode>) { - if (!value.IsString()) { - return Nothing(); - } + THashSet<std::string> Resolving_; + const TNamedNodes* Nodes_; +}; + +TPartialValue EvaluateG(antlr4::ParserRuleContext* ctx, const TNamedNodes& nodes) { + return std::any_cast<TPartialValue>(TVisitor(&nodes).visit(ctx)); +} - return value.AsString(); - } else if constexpr (std::is_same_v<T, TIdentifier>) { - return value; - } else if constexpr (std::is_same_v<T, std::monostate>) { +} // namespace + +bool IsDefined(const TPartialValue& value) { + return !std::holds_alternative<std::monostate>(value); +} + +TMaybe<TString> ToObjectRef(const TPartialValue& value) { + return std::visit([](const auto& value) -> TMaybe<TString> { + using T = std::decay_t<decltype(value)>; + if constexpr (std::is_same_v<T, NYT::TNode>) { + if (!value.IsString()) { return Nothing(); - } else { - static_assert(false); } - }, value); - } - NYT::TNode Evaluate(SQLv1::Bind_parameterContext* ctx, const TNamedNodes& nodes) { - TPartialValue value = EvaluateG(ctx, nodes); - if (std::holds_alternative<NYT::TNode>(value)) { - return std::get<NYT::TNode>(value); + return value.AsString(); + } else if constexpr (std::is_same_v<T, TIdentifier>) { + return value; + } else if constexpr (std::is_same_v<T, std::monostate>) { + return Nothing(); + } else { + static_assert(false); } - return NYT::TNode(); - } + }, value); +} - TPartialValue PartiallyEvaluate(antlr4::ParserRuleContext* ctx, const TNamedNodes& nodes) { - return EvaluateG(ctx, nodes); +NYT::TNode Evaluate(SQLv1::Bind_parameterContext* ctx, const TNamedNodes& nodes) { + TPartialValue value = EvaluateG(ctx, nodes); + if (std::holds_alternative<NYT::TNode>(value)) { + return std::get<NYT::TNode>(value); } + return NYT::TNode(); +} + +TPartialValue PartiallyEvaluate(antlr4::ParserRuleContext* ctx, const TNamedNodes& nodes) { + return EvaluateG(ctx, nodes); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/evaluate.h b/yql/essentials/sql/v1/complete/analysis/global/evaluate.h index fd10939f0ea..f9391fe5dca 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/evaluate.h +++ b/yql/essentials/sql/v1/complete/analysis/global/evaluate.h @@ -7,19 +7,19 @@ namespace NSQLComplete { - using TIdentifier = TString; +using TIdentifier = TString; - using TPartialValue = std::variant< - NYT::TNode, - TIdentifier, - std::monostate>; +using TPartialValue = std::variant< + NYT::TNode, + TIdentifier, + std::monostate>; - bool IsDefined(const TPartialValue& value); +bool IsDefined(const TPartialValue& value); - TMaybe<TString> ToObjectRef(const TPartialValue& value); +TMaybe<TString> ToObjectRef(const TPartialValue& value); - NYT::TNode Evaluate(SQLv1::Bind_parameterContext* ctx, const TNamedNodes& nodes); +NYT::TNode Evaluate(SQLv1::Bind_parameterContext* ctx, const TNamedNodes& nodes); - TPartialValue PartiallyEvaluate(antlr4::ParserRuleContext* ctx, const TNamedNodes& nodes); +TPartialValue PartiallyEvaluate(antlr4::ParserRuleContext* ctx, const TNamedNodes& nodes); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/function.cpp b/yql/essentials/sql/v1/complete/analysis/global/function.cpp index 510009f7ed8..017d42494ef 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/function.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/function.cpp @@ -8,105 +8,105 @@ namespace NSQLComplete { - namespace { - - class TVisitor: public TSQLv1NarrowingVisitor { - public: - TVisitor(const TParsedInput& input, const TNamedNodes* nodes) - : TSQLv1NarrowingVisitor(input) - , Nodes_(nodes) - { - } - - std::any visit(antlr4::tree::ParseTree* tree) override { - if (IsEnclosing(tree)) { - return TSQLv1NarrowingVisitor::visit(tree); - } - return {}; - } +namespace { + +class TVisitor: public TSQLv1NarrowingVisitor { +public: + TVisitor(const TParsedInput& input, const TNamedNodes* nodes) + : TSQLv1NarrowingVisitor(input) + , Nodes_(nodes) + { + } - 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<TFunctionContext> 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; - } + std::any visit(antlr4::tree::ParseTree* tree) override { + if (IsEnclosing(tree)) { + return TSQLv1NarrowingVisitor::visit(tree); + } + return {}; + } - private: - TMaybe<size_t> ArgumentNumber(SQLv1::Table_refContext* ctx) const { - for (auto [i, arg] : Enumerate(ctx->table_arg())) { - if (IsEnclosing(arg)) { - return i; - } - } - return Nothing(); - } + 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 {}; + } - const TNamedNodes* Nodes_; - }; + TMaybe<TFunctionContext> context = GetFunction(ctx, *Nodes_); + if (!context) { + return {}; + } - TMaybe<TString> GetArgument(size_t index, SQLv1::Table_refContext* ctx, const TNamedNodes& nodes) { - auto* table_arg = ctx->table_arg(index); - if (!table_arg) { - return Nothing(); - } + 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; + } - auto* named_expr = table_arg->named_expr(); - if (!named_expr) { - return Nothing(); +private: + TMaybe<size_t> ArgumentNumber(SQLv1::Table_refContext* ctx) const { + for (auto [i, arg] : Enumerate(ctx->table_arg())) { + if (IsEnclosing(arg)) { + return i; } - - return ToObjectRef(PartiallyEvaluate(named_expr, nodes)); } + return Nothing(); + } - TMaybe<TClusterContext> GetCluster(SQLv1::Table_refContext* ctx, const TNamedNodes& nodes) { - auto* cluster_expr = ctx->cluster_expr(); - if (!cluster_expr) { - return Nothing(); - } + const TNamedNodes* Nodes_; +}; - return ParseClusterContext(cluster_expr, nodes); - } +TMaybe<TString> GetArgument(size_t index, SQLv1::Table_refContext* ctx, const TNamedNodes& 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(); + } - } // namespace + return ToObjectRef(PartiallyEvaluate(named_expr, nodes)); +} - TMaybe<TFunctionContext> EnclosingFunction(TParsedInput input, const TNamedNodes& nodes) { - std::any result = TVisitor(input, &nodes).visit(input.SqlQuery); - if (!result.has_value()) { - return Nothing(); - } - return std::any_cast<TFunctionContext>(result); +TMaybe<TClusterContext> GetCluster(SQLv1::Table_refContext* ctx, const TNamedNodes& nodes) { + auto* cluster_expr = ctx->cluster_expr(); + if (!cluster_expr) { + return Nothing(); } - TMaybe<TFunctionContext> GetFunction(SQLv1::Table_refContext* ctx, const TNamedNodes& nodes) { - auto* function = ctx->an_id_expr(); - auto* lparen = ctx->TOKEN_LPAREN(); - if (function == nullptr || lparen == nullptr) { - return Nothing(); - } + return ParseClusterContext(cluster_expr, nodes); +} - return TFunctionContext{ - .Name = function->getText(), - .ArgumentNumber = 0, - .Arg0 = GetArgument(0, ctx, nodes), - .Arg1 = GetArgument(1, ctx, nodes), - .Cluster = GetCluster(ctx, nodes), - }; +} // namespace + +TMaybe<TFunctionContext> EnclosingFunction(TParsedInput input, const TNamedNodes& nodes) { + std::any result = TVisitor(input, &nodes).visit(input.SqlQuery); + if (!result.has_value()) { + return Nothing(); + } + return std::any_cast<TFunctionContext>(result); +} + +TMaybe<TFunctionContext> GetFunction(SQLv1::Table_refContext* ctx, const TNamedNodes& 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 diff --git a/yql/essentials/sql/v1/complete/analysis/global/function.h b/yql/essentials/sql/v1/complete/analysis/global/function.h index 718304cc85c..25c0b07cc98 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/function.h +++ b/yql/essentials/sql/v1/complete/analysis/global/function.h @@ -9,8 +9,8 @@ namespace NSQLComplete { - TMaybe<TFunctionContext> EnclosingFunction(TParsedInput input, const TNamedNodes& nodes); +TMaybe<TFunctionContext> EnclosingFunction(TParsedInput input, const TNamedNodes& nodes); - TMaybe<TFunctionContext> GetFunction(SQLv1::Table_refContext* ctx, const TNamedNodes& nodes); +TMaybe<TFunctionContext> GetFunction(SQLv1::Table_refContext* ctx, const TNamedNodes& nodes); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/global.cpp b/yql/essentials/sql/v1/complete/analysis/global/global.cpp index 95a260ee973..9023ef7aec8 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/global.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/global.cpp @@ -17,237 +17,237 @@ namespace NSQLComplete { - namespace { +namespace { - template <class C> - void Move(TColumnContext& lhs, TColumnContext& rhs, C TColumnContext::*member) { - C& lhsM = lhs.*member; - C& rhsM = rhs.*member; +template <class C> +void Move(TColumnContext& lhs, TColumnContext& rhs, C TColumnContext::*member) { + C& lhsM = lhs.*member; + C& rhsM = rhs.*member; - lhsM.reserve(lhsM.size() + rhsM.size()); - std::move(rhsM.begin(), rhsM.end(), std::back_inserter(lhsM)); - SortUnique(lhsM); - } - - } // namespace - - bool operator<(const TColumnId& lhs, const TColumnId& rhs) { - return std::tie(lhs.TableAlias, lhs.Name) < std::tie(rhs.TableAlias, rhs.Name); - } + lhsM.reserve(lhsM.size() + rhsM.size()); + std::move(rhsM.begin(), rhsM.end(), std::back_inserter(lhsM)); + SortUnique(lhsM); +} - TColumnContext TColumnContext::ExtractAliased(TMaybe<TStringBuf> alias) { - if (alias.Empty()) { - return *this; - } +} // namespace - auto aliasedTables = std::ranges::partition(Tables, [&](const auto& table) { - return table.Alias != alias; - }); +bool operator<(const TColumnId& lhs, const TColumnId& rhs) { + return std::tie(lhs.TableAlias, lhs.Name) < std::tie(rhs.TableAlias, rhs.Name); +} - auto aliasedColumns = std::ranges::partition(Columns, [&](const auto& column) { - return column.TableAlias != alias; - }); +TColumnContext TColumnContext::ExtractAliased(TMaybe<TStringBuf> alias) { + if (alias.Empty()) { + return *this; + } - TVector<TAliased<TTableId>> tables(aliasedTables.begin(), aliasedTables.end()); - TVector<TColumnId> columns(aliasedColumns.begin(), aliasedColumns.end()); + auto aliasedTables = std::ranges::partition(Tables, [&](const auto& table) { + return table.Alias != alias; + }); - Tables.erase(aliasedTables.begin(), aliasedTables.end()); - Columns.erase(aliasedColumns.begin(), aliasedColumns.end()); + auto aliasedColumns = std::ranges::partition(Columns, [&](const auto& column) { + return column.TableAlias != alias; + }); - THashMap<TString, THashSet<TString>> without; - if (auto it = WithoutByTableAlias.find(*alias); it != WithoutByTableAlias.end()) { - without[*alias] = std::move(it->second); - WithoutByTableAlias.erase(it); - } + TVector<TAliased<TTableId>> tables(aliasedTables.begin(), aliasedTables.end()); + TVector<TColumnId> columns(aliasedColumns.begin(), aliasedColumns.end()); - return { - .Tables = std::move(tables), - .Columns = std::move(columns), - .WithoutByTableAlias = std::move(without), - }; - } + Tables.erase(aliasedTables.begin(), aliasedTables.end()); + Columns.erase(aliasedColumns.begin(), aliasedColumns.end()); - bool TColumnContext::IsAsterisk() const { - return Columns.size() == 1 && - Columns[0].TableAlias.empty() && - Columns[0].Name == "*"; + THashMap<TString, THashSet<TString>> without; + if (auto it = WithoutByTableAlias.find(*alias); it != WithoutByTableAlias.end()) { + without[*alias] = std::move(it->second); + WithoutByTableAlias.erase(it); } - TColumnContext TColumnContext::Renamed(TStringBuf alias) && { - for (TAliased<TTableId>& table : Tables) { - table.Alias = alias; - } + return { + .Tables = std::move(tables), + .Columns = std::move(columns), + .WithoutByTableAlias = std::move(without), + }; +} - for (TColumnId& column : Columns) { - column.TableAlias = alias; - } +bool TColumnContext::IsAsterisk() const { + return Columns.size() == 1 && + Columns[0].TableAlias.empty() && + Columns[0].Name == "*"; +} - THashSet<TString>& without = WithoutByTableAlias[alias]; - for (auto& [tableAlias, excluded] : WithoutByTableAlias) { - if (tableAlias == alias) { - continue; - } +TColumnContext TColumnContext::Renamed(TStringBuf alias) && { + for (TAliased<TTableId>& table : Tables) { + table.Alias = alias; + } - without.insert(excluded.begin(), excluded.end()); - } + for (TColumnId& column : Columns) { + column.TableAlias = alias; + } - if (without.empty()) { - WithoutByTableAlias = {}; - } else { - WithoutByTableAlias = {{TString(alias), std::move(without)}}; + THashSet<TString>& without = WithoutByTableAlias[alias]; + for (auto& [tableAlias, excluded] : WithoutByTableAlias) { + if (tableAlias == alias) { + continue; } - return *this; + without.insert(excluded.begin(), excluded.end()); } - TColumnContext operator|(TColumnContext lhs, TColumnContext rhs) { - Move(lhs, rhs, &TColumnContext::Tables); + if (without.empty()) { + WithoutByTableAlias = {}; + } else { + WithoutByTableAlias = {{TString(alias), std::move(without)}}; + } - Move(lhs, rhs, &TColumnContext::Columns); + return *this; +} - for (auto& [tableAlias, excluded] : rhs.WithoutByTableAlias) { - auto& without = lhs.WithoutByTableAlias[tableAlias]; - without.insert(excluded.begin(), excluded.end()); - } +TColumnContext operator|(TColumnContext lhs, TColumnContext rhs) { + Move(lhs, rhs, &TColumnContext::Tables); - return lhs; - } + Move(lhs, rhs, &TColumnContext::Columns); - TColumnContext TColumnContext::Asterisk() { - return {.Columns = {{.Name = "*"}}}; + for (auto& [tableAlias, excluded] : rhs.WithoutByTableAlias) { + auto& without = lhs.WithoutByTableAlias[tableAlias]; + without.insert(excluded.begin(), excluded.end()); } - class TErrorStrategy: public antlr4::DefaultErrorStrategy { - public: - antlr4::Token* singleTokenDeletion(antlr4::Parser* /* recognizer */) override { - return nullptr; - } - }; + return lhs; +} - template <bool IsAnsiLexer> - class TSpecializedGlobalAnalysis: public IGlobalAnalysis { - public: - using TLexer = std::conditional_t< - IsAnsiLexer, - NALAAnsiAntlr4::SQLv1Antlr4Lexer, - NALADefaultAntlr4::SQLv1Antlr4Lexer>; - - TSpecializedGlobalAnalysis() - : Chars_() - , Lexer_(&Chars_) - , Tokens_(&Lexer_) - , Parser_(&Tokens_) - { - Lexer_.removeErrorListeners(); - Parser_.removeErrorListeners(); - Parser_.setErrorHandler(std::make_shared<TErrorStrategy>()); - } +TColumnContext TColumnContext::Asterisk() { + return {.Columns = {{.Name = "*"}}}; +} - TGlobalContext Analyze(TCompletionInput input, TEnvironment env) override { - TString recovered; - if (IsRecoverable(input)) { - recovered = TString(input.Text); +class TErrorStrategy: public antlr4::DefaultErrorStrategy { +public: + antlr4::Token* singleTokenDeletion(antlr4::Parser* /* recognizer */) override { + return nullptr; + } +}; + +template <bool IsAnsiLexer> +class TSpecializedGlobalAnalysis: public IGlobalAnalysis { +public: + using TLexer = std::conditional_t< + IsAnsiLexer, + NALAAnsiAntlr4::SQLv1Antlr4Lexer, + NALADefaultAntlr4::SQLv1Antlr4Lexer>; + + TSpecializedGlobalAnalysis() + : Chars_() + , Lexer_(&Chars_) + , Tokens_(&Lexer_) + , Parser_(&Tokens_) + { + Lexer_.removeErrorListeners(); + Parser_.removeErrorListeners(); + Parser_.setErrorHandler(std::make_shared<TErrorStrategy>()); + } - // - "_" is to parse `SELECT x._ FROM table` - // instead of `SELECT x.FROM table` - recovered.insert(input.CursorPosition, "_"); + TGlobalContext Analyze(TCompletionInput input, TEnvironment env) override { + TString recovered; + if (IsRecoverable(input)) { + recovered = TString(input.Text); - input.Text = recovered; - } + // - "_" is to parse `SELECT x._ FROM table` + // instead of `SELECT x.FROM table` + recovered.insert(input.CursorPosition, "_"); - SQLv1::Sql_queryContext* sqlQuery = Parse(input.Text); - Y_ENSURE(sqlQuery); + input.Text = recovered; + } - TGlobalContext ctx; + SQLv1::Sql_queryContext* sqlQuery = Parse(input.Text); + Y_ENSURE(sqlQuery); - TParsedInput parsed = { - .Original = input, - .Tokens = &Tokens_, - .Parser = &Parser_, - .SqlQuery = sqlQuery, - }; + TGlobalContext ctx; - TNamedNodes nodes = CollectNamedNodes(parsed, env); + TParsedInput parsed = { + .Original = input, + .Tokens = &Tokens_, + .Parser = &Parser_, + .SqlQuery = sqlQuery, + }; - ctx.Use = FindUseStatement(parsed, nodes); - ctx.Names = Keys(nodes); - ctx.EnclosingFunction = EnclosingFunction(parsed, nodes); - ctx.Column = InferColumnContext(parsed, nodes); + TNamedNodes nodes = CollectNamedNodes(parsed, env); - if (ctx.Use && ctx.Column) { - EnrichTableClusters(*ctx.Column, *ctx.Use); - } + ctx.Use = FindUseStatement(parsed, nodes); + ctx.Names = Keys(nodes); + ctx.EnclosingFunction = EnclosingFunction(parsed, nodes); + ctx.Column = InferColumnContext(parsed, nodes); - return ctx; + if (ctx.Use && ctx.Column) { + EnrichTableClusters(*ctx.Column, *ctx.Use); } - private: - bool IsRecoverable(TCompletionInput input) const { - TStringBuf s = input.Text; - size_t i = input.CursorPosition; + return ctx; + } - return (i < s.size() && IsWordBoundary(s[i]) || i == s.size()); - } +private: + bool IsRecoverable(TCompletionInput input) const { + TStringBuf s = input.Text; + size_t i = input.CursorPosition; - SQLv1::Sql_queryContext* Parse(TStringBuf input) { - Chars_.load(input.Data(), input.Size(), /* lenient = */ false); - Lexer_.reset(); - Tokens_.setTokenSource(&Lexer_); - Parser_.reset(); - return Parser_.sql_query(); - } + return (i < s.size() && IsWordBoundary(s[i]) || i == s.size()); + } - TVector<TString> Keys(const TNamedNodes& nodes) { - TVector<TString> keys; - keys.reserve(nodes.size()); - for (const auto& [name, _] : nodes) { - keys.emplace_back(name); - } - return keys; - } + SQLv1::Sql_queryContext* Parse(TStringBuf input) { + Chars_.load(input.Data(), input.Size(), /* lenient = */ false); + Lexer_.reset(); + Tokens_.setTokenSource(&Lexer_); + Parser_.reset(); + return Parser_.sql_query(); + } - void EnrichTableClusters(TColumnContext& column, const TClusterContext& use) { - for (auto& table : column.Tables) { - if (table.Cluster.empty()) { - table.Cluster = use.Name; - } - } + TVector<TString> Keys(const TNamedNodes& nodes) { + TVector<TString> keys; + keys.reserve(nodes.size()); + for (const auto& [name, _] : nodes) { + keys.emplace_back(name); } + return keys; + } - void DebugPrint(TStringBuf query, antlr4::ParserRuleContext* ctx) { - Cerr << "= = = = = = " << Endl; - Cerr << query << Endl; - Cerr << ctx->toStringTree(&Parser_, true) << Endl; + void EnrichTableClusters(TColumnContext& column, const TClusterContext& use) { + for (auto& table : column.Tables) { + if (table.Cluster.empty()) { + table.Cluster = use.Name; + } } + } - antlr4::ANTLRInputStream Chars_; - TLexer Lexer_; - antlr4::CommonTokenStream Tokens_; - SQLv1 Parser_; - }; + void DebugPrint(TStringBuf query, antlr4::ParserRuleContext* ctx) { + Cerr << "= = = = = = " << Endl; + Cerr << query << Endl; + Cerr << ctx->toStringTree(&Parser_, true) << Endl; + } - class TGlobalAnalysis: public IGlobalAnalysis { - public: - TGlobalContext Analyze(TCompletionInput input, TEnvironment env) override { - const bool isAnsiLexer = IsAnsiQuery(TString(input.Text)); - return GetSpecialized(isAnsiLexer).Analyze(std::move(input), std::move(env)); - } + antlr4::ANTLRInputStream Chars_; + TLexer Lexer_; + antlr4::CommonTokenStream Tokens_; + SQLv1 Parser_; +}; + +class TGlobalAnalysis: public IGlobalAnalysis { +public: + TGlobalContext Analyze(TCompletionInput input, TEnvironment env) override { + const bool isAnsiLexer = IsAnsiQuery(TString(input.Text)); + return GetSpecialized(isAnsiLexer).Analyze(std::move(input), std::move(env)); + } - private: - IGlobalAnalysis& GetSpecialized(bool isAnsiLexer) { - if (isAnsiLexer) { - return AnsiAnalysis_; - } - return DefaultAnalysis_; +private: + IGlobalAnalysis& GetSpecialized(bool isAnsiLexer) { + if (isAnsiLexer) { + return AnsiAnalysis_; } + return DefaultAnalysis_; + } - TSpecializedGlobalAnalysis</* IsAnsiLexer = */ false> DefaultAnalysis_; - TSpecializedGlobalAnalysis</* IsAnsiLexer = */ true> AnsiAnalysis_; - }; + TSpecializedGlobalAnalysis</* IsAnsiLexer = */ false> DefaultAnalysis_; + TSpecializedGlobalAnalysis</* IsAnsiLexer = */ true> AnsiAnalysis_; +}; - IGlobalAnalysis::TPtr MakeGlobalAnalysis() { - return MakeHolder<TGlobalAnalysis>(); - } +IGlobalAnalysis::TPtr MakeGlobalAnalysis() { + return MakeHolder<TGlobalAnalysis>(); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/global.h b/yql/essentials/sql/v1/complete/analysis/global/global.h index b1459d1970d..6fe48e48956 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/global.h +++ b/yql/essentials/sql/v1/complete/analysis/global/global.h @@ -13,55 +13,55 @@ namespace NSQLComplete { - struct TClusterContext { - TString Provider; - TString Name; - - friend bool operator==(const TClusterContext& lhs, const TClusterContext& rhs) = default; - }; - - struct TFunctionContext { - TString Name; - size_t ArgumentNumber = 0; - TMaybe<TString> Arg0 = Nothing(); - TMaybe<TString> Arg1 = Nothing(); - TMaybe<TClusterContext> Cluster = Nothing(); - - friend bool operator==(const TFunctionContext& lhs, const TFunctionContext& rhs) = default; - }; - - // TODO(YQL-19747): Try to refactor to use Map/Set data structures - struct TColumnContext { - TVector<TAliased<TTableId>> Tables; - TVector<TColumnId> Columns; - THashMap<TString, THashSet<TString>> WithoutByTableAlias; - - bool IsAsterisk() const; - TColumnContext ExtractAliased(TMaybe<TStringBuf> alias); - TColumnContext Renamed(TStringBuf alias) &&; - - friend bool operator==(const TColumnContext& lhs, const TColumnContext& rhs) = default; - friend TColumnContext operator|(TColumnContext lhs, TColumnContext rhs); - - static TColumnContext Asterisk(); - }; - - struct TGlobalContext { - TMaybe<TClusterContext> Use; - TVector<TString> Names; - TMaybe<TFunctionContext> EnclosingFunction; - TMaybe<TColumnContext> Column; - }; - - // TODO(YQL-19747): Make it thread-safe to make ISqlCompletionEngine thread-safe. - class IGlobalAnalysis { - public: - using TPtr = THolder<IGlobalAnalysis>; - - virtual ~IGlobalAnalysis() = default; - virtual TGlobalContext Analyze(TCompletionInput input, TEnvironment env) = 0; - }; - - IGlobalAnalysis::TPtr MakeGlobalAnalysis(); +struct TClusterContext { + TString Provider; + TString Name; + + friend bool operator==(const TClusterContext& lhs, const TClusterContext& rhs) = default; +}; + +struct TFunctionContext { + TString Name; + size_t ArgumentNumber = 0; + TMaybe<TString> Arg0 = Nothing(); + TMaybe<TString> Arg1 = Nothing(); + TMaybe<TClusterContext> Cluster = Nothing(); + + friend bool operator==(const TFunctionContext& lhs, const TFunctionContext& rhs) = default; +}; + +// TODO(YQL-19747): Try to refactor to use Map/Set data structures +struct TColumnContext { + TVector<TAliased<TTableId>> Tables; + TVector<TColumnId> Columns; + THashMap<TString, THashSet<TString>> WithoutByTableAlias; + + bool IsAsterisk() const; + TColumnContext ExtractAliased(TMaybe<TStringBuf> alias); + TColumnContext Renamed(TStringBuf alias) &&; + + friend bool operator==(const TColumnContext& lhs, const TColumnContext& rhs) = default; + friend TColumnContext operator|(TColumnContext lhs, TColumnContext rhs); + + static TColumnContext Asterisk(); +}; + +struct TGlobalContext { + TMaybe<TClusterContext> Use; + TVector<TString> Names; + TMaybe<TFunctionContext> EnclosingFunction; + TMaybe<TColumnContext> Column; +}; + +// TODO(YQL-19747): Make it thread-safe to make ISqlCompletionEngine thread-safe. +class IGlobalAnalysis { +public: + using TPtr = THolder<IGlobalAnalysis>; + + virtual ~IGlobalAnalysis() = default; + virtual TGlobalContext Analyze(TCompletionInput input, TEnvironment env) = 0; +}; + +IGlobalAnalysis::TPtr MakeGlobalAnalysis(); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp b/yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp index 1d593044ea5..dc5d86da899 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp @@ -6,10 +6,10 @@ using namespace NSQLComplete; Y_UNIT_TEST_SUITE(GlobalAnalysisTests) { - Y_UNIT_TEST(TopLevelNamesCollected) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); +Y_UNIT_TEST(TopLevelNamesCollected) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - TString query = R"( + TString query = R"( DECLARE $cluster_name AS String; IMPORT math SYMBOLS $sqrt, $pow; @@ -24,24 +24,24 @@ Y_UNIT_TEST_SUITE(GlobalAnalysisTests) { $first, $second, $_ = AsTuple(1, 2, 3); )"; - TGlobalContext ctx = global->Analyze({query}, {}); - Sort(ctx.Names); + TGlobalContext ctx = global->Analyze({query}, {}); + Sort(ctx.Names); - TVector<TString> expected = { - "cluster_name", - "first", - "hello_world", - "pow", - "second", - "sqrt", - }; - UNIT_ASSERT_VALUES_EQUAL(ctx.Names, expected); - } + TVector<TString> expected = { + "cluster_name", + "first", + "hello_world", + "pow", + "second", + "sqrt", + }; + UNIT_ASSERT_VALUES_EQUAL(ctx.Names, expected); +} - Y_UNIT_TEST(LocalNamesCollected) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); +Y_UNIT_TEST(LocalNamesCollected) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - TString query = R"( + TString query = R"( DEFINE ACTION $sum($x, $y) AS $acc = 0; EVALUATE FOR $i IN AsList($x, $y) DO BEGIN @@ -51,182 +51,182 @@ Y_UNIT_TEST_SUITE(GlobalAnalysisTests) { END DEFINE; )"; - TCompletionInput input = SharpedInput(query); + TCompletionInput input = SharpedInput(query); - TGlobalContext ctx = global->Analyze(input, {}); - Sort(ctx.Names); + TGlobalContext ctx = global->Analyze(input, {}); + Sort(ctx.Names); - TVector<TString> expected = { - "a", - "acc", - "b", - "i", - "plus", - "sum", - "x", - "y", - }; - UNIT_ASSERT_VALUES_EQUAL(ctx.Names, expected); - } + TVector<TString> expected = { + "a", + "acc", + "b", + "i", + "plus", + "sum", + "x", + "y", + }; + UNIT_ASSERT_VALUES_EQUAL(ctx.Names, expected); +} - Y_UNIT_TEST(RecursiveName) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); +Y_UNIT_TEST(RecursiveName) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - TString query = R"( + TString query = R"( $x = $x; # )"; + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + UNIT_ASSERT_VALUES_EQUAL(ctx.Names, TVector<TString>{"x"}); +} + +Y_UNIT_TEST(EnclosingFunctionName) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); + { + TString query = "SELECT * FROM Concat(#)"; TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - UNIT_ASSERT_VALUES_EQUAL(ctx.Names, TVector<TString>{"x"}); + TFunctionContext expected = {"Concat", 0}; + UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, expected); } - - Y_UNIT_TEST(EnclosingFunctionName) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - { - TString query = "SELECT * FROM Concat(#)"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TFunctionContext expected = {"Concat", 0}; - UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, expected); - } - { - TString query = "SELECT * FROM Concat(a, #)"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TFunctionContext expected = {"Concat", 1, "a"}; - UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, expected); - } - { - TString query = "SELECT * FROM Concat(a#)"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TFunctionContext expected = {"Concat", 0}; - UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, expected); - } - { - TString query = "SELECT * FROM Concat(#"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TFunctionContext expected = {"Concat", 0}; - UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, expected); - } - { - TString query = "SELECT * FROM (#)"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, Nothing()); - } - { - TString query = "SELECT * FROM plato.Concat(#)"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TClusterContext expected = {"", "plato"}; - UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction->Cluster, expected); - } + { + TString query = "SELECT * FROM Concat(a, #)"; + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TFunctionContext expected = {"Concat", 1, "a"}; + UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, expected); + } + { + TString query = "SELECT * FROM Concat(a#)"; + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TFunctionContext expected = {"Concat", 0}; + UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, expected); + } + { + TString query = "SELECT * FROM Concat(#"; + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TFunctionContext expected = {"Concat", 0}; + UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, expected); + } + { + TString query = "SELECT * FROM (#)"; + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, Nothing()); + } + { + TString query = "SELECT * FROM plato.Concat(#)"; + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TClusterContext expected = {"", "plato"}; + UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction->Cluster, expected); } +} - Y_UNIT_TEST(SimpleSelectFrom) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - { - TString query = "SELECT # FROM plato.Input"; +Y_UNIT_TEST(SimpleSelectFrom) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); + { + TString query = "SELECT # FROM plato.Input"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {.Tables = {TTableId{"plato", "Input"}}}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = "SELECT # FROM plato.`//home/input`"; + TColumnContext expected = {.Tables = {TTableId{"plato", "Input"}}}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } + { + TString query = "SELECT # FROM plato.`//home/input`"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {.Tables = {TTableId{"plato", "//home/input"}}}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = "SELECT # FROM plato.Input AS x"; + TColumnContext expected = {.Tables = {TTableId{"plato", "//home/input"}}}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } + { + TString query = "SELECT # FROM plato.Input AS x"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {.Tables = {TAliased<TTableId>("x", TTableId{"plato", "Input"})}}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } + TColumnContext expected = {.Tables = {TAliased<TTableId>("x", TTableId{"plato", "Input"})}}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); } +} - Y_UNIT_TEST(Join) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - { - TString query = R"( +Y_UNIT_TEST(Join) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); + { + TString query = R"( SELECT # FROM q.a AS x, p.b, c JOIN p.d AS y ON x.key = y.key )"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - - TColumnContext expected = { - .Tables = { - TAliased<TTableId>("", {"", "c"}), - TAliased<TTableId>("", {"p", "b"}), - TAliased<TTableId>("x", {"q", "a"}), - TAliased<TTableId>("y", {"p", "d"}), - }, - }; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + + TColumnContext expected = { + .Tables = { + TAliased<TTableId>("", {"", "c"}), + TAliased<TTableId>("", {"p", "b"}), + TAliased<TTableId>("x", {"q", "a"}), + TAliased<TTableId>("y", {"p", "d"}), + }, + }; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); } +} - Y_UNIT_TEST(Subquery) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - { - TString query = "SELECT # FROM (SELECT * FROM x)"; +Y_UNIT_TEST(Subquery) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); + { + TString query = "SELECT # FROM (SELECT * FROM x)"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {.Tables = {TAliased<TTableId>("", {"", "x"})}}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = "SELECT # FROM (SELECT a, b FROM x)"; + TColumnContext expected = {.Tables = {TAliased<TTableId>("", {"", "x"})}}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } + { + TString query = "SELECT # FROM (SELECT a, b FROM x)"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {.Columns = {{.Name = "a"}, {.Name = "b"}}}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = "SELECT # FROM (SELECT 1 AS a, 2 AS b)"; + TColumnContext expected = {.Columns = {{.Name = "a"}, {.Name = "b"}}}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } + { + TString query = "SELECT # FROM (SELECT 1 AS a, 2 AS b)"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {.Columns = {{.Name = "a"}, {.Name = "b"}}}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = "SELECT # FROM (SELECT 1 AS a, 2 AS b) AS x"; + TColumnContext expected = {.Columns = {{.Name = "a"}, {.Name = "b"}}}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } + { + TString query = "SELECT # FROM (SELECT 1 AS a, 2 AS b) AS x"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {.Columns = {{"x", "a"}, {"x", "b"}}}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = R"( + TColumnContext expected = {.Columns = {{"x", "a"}, {"x", "b"}}}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } + { + TString query = R"( SELECT # FROM (SELECT * FROM example.`/people`) AS ep JOIN (SELECT room AS Room, time FROM example.`/yql/tutorial`) AS et ON 1 = 1 )"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - - TColumnContext expected = { - .Tables = { - TAliased<TTableId>("ep", {"example", "/people"}), - }, - .Columns = { - {.TableAlias = "et", .Name = "Room"}, - {.TableAlias = "et", .Name = "time"}, - }, - }; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = R"( + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + + TColumnContext expected = { + .Tables = { + TAliased<TTableId>("ep", {"example", "/people"}), + }, + .Columns = { + {.TableAlias = "et", .Name = "Room"}, + {.TableAlias = "et", .Name = "time"}, + }, + }; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } + { + TString query = R"( SELECT # FROM ( SELECT x.*, y.name, e FROM (SELECT a.*, d FROM a AS a JOIN c AS c ON TRUE) AS x @@ -234,52 +234,52 @@ Y_UNIT_TEST_SUITE(GlobalAnalysisTests) { ) )"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - - TColumnContext expected = { - .Tables = { - TAliased<TTableId>("", {"", "a"}), - }, - .Columns = { - {.Name = "d"}, - {.Name = "e"}, - }, - }; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = "SELECT # FROM (SELECT 1, *, 2 FROM t)"; - - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - - TColumnContext expected = { - .Tables = { - TAliased<TTableId>("", {"", "t"}), - }, - }; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + + TColumnContext expected = { + .Tables = { + TAliased<TTableId>("", {"", "a"}), + }, + .Columns = { + {.Name = "d"}, + {.Name = "e"}, + }, + }; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); } + { + TString query = "SELECT # FROM (SELECT 1, *, 2 FROM t)"; - Y_UNIT_TEST(SubqueryWithout) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - { - TString query = "SELECT # FROM (SELECT * WITHOUT a FROM x)"; - - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - - TColumnContext expected = { - .Tables = { - TAliased<TTableId>("", {"", "x"}), - }, - .WithoutByTableAlias = { - {"", {"a"}}, - }, - }; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = R"( + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + + TColumnContext expected = { + .Tables = { + TAliased<TTableId>("", {"", "t"}), + }, + }; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } +} + +Y_UNIT_TEST(SubqueryWithout) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); + { + TString query = "SELECT # FROM (SELECT * WITHOUT a FROM x)"; + + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + + TColumnContext expected = { + .Tables = { + TAliased<TTableId>("", {"", "x"}), + }, + .WithoutByTableAlias = { + {"", {"a"}}, + }, + }; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } + { + TString query = R"( SELECT # FROM ( SELECT * WITHOUT Age, eqt.course @@ -289,86 +289,86 @@ Y_UNIT_TEST_SUITE(GlobalAnalysisTests) { ) AS ep )"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - - TColumnContext expected = { - .Tables = { - TAliased<TTableId>("ep", {"", "testing"}), - TAliased<TTableId>("ep", {"example", "/people"}), - TAliased<TTableId>("ep", {"example", "/yql/tutorial"}), - }, - .WithoutByTableAlias = { - {"ep", {"course", "Age"}}, - }, - }; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + + TColumnContext expected = { + .Tables = { + TAliased<TTableId>("ep", {"", "testing"}), + TAliased<TTableId>("ep", {"example", "/people"}), + TAliased<TTableId>("ep", {"example", "/yql/tutorial"}), + }, + .WithoutByTableAlias = { + {"ep", {"course", "Age"}}, + }, + }; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); } +} - Y_UNIT_TEST(Projection) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - { - TString query = "SELECT a, b, # FROM x"; +Y_UNIT_TEST(Projection) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); + { + TString query = "SELECT a, b, # FROM x"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {.Tables = {TAliased<TTableId>("", {"", "x"})}}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } + TColumnContext expected = {.Tables = {TAliased<TTableId>("", {"", "x"})}}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); } +} - Y_UNIT_TEST(NamedSubquery) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - { - TString query = R"( +Y_UNIT_TEST(NamedSubquery) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); + { + TString query = R"( $subquery = (SELECT * FROM x); SELECT # FROM $subquery; )"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {.Tables = {TAliased<TTableId>("", {"", "x"})}}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = R"( + TColumnContext expected = {.Tables = {TAliased<TTableId>("", {"", "x"})}}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } + { + TString query = R"( SELECT # FROM $subquery; )"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = R"( + TColumnContext expected = {}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } + { + TString query = R"( $subquery1 = (SELECT * FROM $subquery1); SELECT # FROM $subquery1; )"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - { - TString query = R"( + TColumnContext expected = {}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); + } + { + TString query = R"( $subquery1 = (SELECT * FROM $subquery2); $subquery2 = (SELECT * FROM $subquery1); SELECT # FROM $subquery2; )"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } + TColumnContext expected = {}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); } +} - Y_UNIT_TEST(EvaluationAssignment) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); +Y_UNIT_TEST(EvaluationAssignment) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - TString query = R"sql( + TString query = R"sql( DECLARE $t1 AS String; DECLARE $t2 AS String; @@ -384,58 +384,58 @@ Y_UNIT_TEST_SUITE(GlobalAnalysisTests) { SELECT # FROM $q1 JOIN $q2 )sql"; - TEnvironment env = { - .Parameters = { - {"$t1", "table1"}, - {"$t2", "table2"}, - }, - }; - - TGlobalContext ctx = global->Analyze(SharpedInput(query), env); - - TColumnContext expected = { - .Tables = { - TAliased<TTableId>("", {"", "table1"}), - TAliased<TTableId>("", {"", "table2"}), - }, - }; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } - - Y_UNIT_TEST(EvaluationRecursion) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - - TVector<TString> queries = { - R"sql($x = $x; SELECT # FROM $x)sql", - R"sql($x = $y; $y = $x; SELECT # FROM $x)sql", - }; - - for (TString& query : queries) { - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - Y_DO_NOT_OPTIMIZE_AWAY(ctx); - } + TEnvironment env = { + .Parameters = { + {"$t1", "table1"}, + {"$t2", "table2"}, + }, + }; + + TGlobalContext ctx = global->Analyze(SharpedInput(query), env); + + TColumnContext expected = { + .Tables = { + TAliased<TTableId>("", {"", "table1"}), + TAliased<TTableId>("", {"", "table2"}), + }, + }; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); +} + +Y_UNIT_TEST(EvaluationRecursion) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); + + TVector<TString> queries = { + R"sql($x = $x; SELECT # FROM $x)sql", + R"sql($x = $y; $y = $x; SELECT # FROM $x)sql", + }; + + for (TString& query : queries) { + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + Y_DO_NOT_OPTIMIZE_AWAY(ctx); } +} - Y_UNIT_TEST(EvaluationSubquery) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); +Y_UNIT_TEST(EvaluationSubquery) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - TString query = R"sql( + TString query = R"sql( $x = (SELECT * FROM $y); $y = (SELECT * FROM $x); $z = $x || $y; SELECT # FROM $z; )sql"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = {}; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } + TColumnContext expected = {}; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); +} - Y_UNIT_TEST(EvaluationStringConcat) { - IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); +Y_UNIT_TEST(EvaluationStringConcat) { + IGlobalAnalysis::TPtr global = MakeGlobalAnalysis(); - TString query = R"sql( + TString query = R"sql( $cluster = 'ex' || 'am' || "ple"; $product = "yql"; $seq = "1"; @@ -443,12 +443,12 @@ Y_UNIT_TEST_SUITE(GlobalAnalysisTests) { SELECT # FROM $cluster.$source; )sql"; - TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); + TGlobalContext ctx = global->Analyze(SharpedInput(query), {}); - TColumnContext expected = { - .Tables = {TAliased<TTableId>("", {"example", "/home/yql/1"})}, - }; - UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); - } + TColumnContext expected = { + .Tables = {TAliased<TTableId>("", {"example", "/home/yql/1"})}, + }; + UNIT_ASSERT_VALUES_EQUAL(ctx.Column, expected); +} } // Y_UNIT_TEST_SUITE(GlobalAnalysisTests) diff --git a/yql/essentials/sql/v1/complete/analysis/global/input.h b/yql/essentials/sql/v1/complete/analysis/global/input.h index 3f40ec1f31d..609c507f09d 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/input.h +++ b/yql/essentials/sql/v1/complete/analysis/global/input.h @@ -6,11 +6,11 @@ namespace NSQLComplete { - struct TParsedInput { - TCompletionInput Original; - antlr4::CommonTokenStream* Tokens; - SQLv1* Parser; - SQLv1::Sql_queryContext* SqlQuery; - }; +struct TParsedInput { + TCompletionInput Original; + antlr4::CommonTokenStream* Tokens; + SQLv1* Parser; + SQLv1::Sql_queryContext* SqlQuery; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp b/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp index 4199da625c2..8a52a90424c 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp @@ -10,161 +10,161 @@ namespace NSQLComplete { - namespace { - - class TVisitor: public TSQLv1NarrowingVisitor { - public: - TVisitor(const TParsedInput& input, TNamedNodes* names, const TEnvironment* env) - : TSQLv1NarrowingVisitor(input) - , Names_(names) - , Env_(env) - { - } - - std::any visitSql_stmt_core(SQLv1::Sql_stmt_coreContext* ctx) override { - if (ctx->declare_stmt() || - ctx->import_stmt() || - ctx->define_action_or_subquery_stmt() || - ctx->named_nodes_stmt() || - IsEnclosing(ctx)) { - return visitChildren(ctx); - } - return {}; - } - - std::any visitDeclare_stmt(SQLv1::Declare_stmtContext* ctx) override { - auto* parameter = ctx->bind_parameter(); - if (!parameter) { - return {}; - } - - TMaybe<std::string> id = GetName(parameter); - if (id.Empty() || id == "_") { - return {}; - } - - id->insert(0, "$"); - const NYT::TNode* node = Env_->Parameters.FindPtr(*id); - id->erase(0, 1); - - if (node) { - (*Names_)[*id] = *node; - } else { - (*Names_)[*id] = std::monostate(); - } - - return {}; - } - - std::any visitImport_stmt(SQLv1::Import_stmtContext* ctx) override { - VisitNullableCollecting(ctx->named_bind_parameter_list()); - return {}; - } - - std::any visitDefine_action_or_subquery_stmt( - SQLv1::Define_action_or_subquery_stmtContext* ctx) override { - VisitNullableCollecting(ctx->bind_parameter()); - if (IsEnclosing(ctx)) { - VisitNullableCollecting(ctx->action_or_subquery_args()); - return visitChildren(ctx); - } - return {}; - } - - std::any visitNamed_nodes_stmt(SQLv1::Named_nodes_stmtContext* ctx) override { - VisitNullableCollecting(ctx->bind_parameter_list()); - if (IsEnclosing(ctx)) { - visitChildren(ctx); - } - - auto* list = ctx->bind_parameter_list(); - if (!list) { - return {}; - } - - auto parameters = list->bind_parameter(); - if (parameters.size() != 1) { - return {}; - } - - auto* parameter = parameters[0]; - if (!parameter) { - return {}; - } - - TMaybe<std::string> id = GetName(parameter); - if (id.Empty() || id == "_") { - return {}; - } - - if (auto* expr = ctx->expr()) { - (*Names_)[std::move(*id)] = expr; - } else { - (*Names_)[std::move(*id)] = std::monostate(); - } - - return {}; - } - - std::any visitFor_stmt(SQLv1::For_stmtContext* ctx) override { - VisitNullableCollecting(ctx->bind_parameter()); - if (IsEnclosing(ctx)) { - return visitChildren(ctx); - } - return {}; - } - - std::any visitLambda(SQLv1::LambdaContext* ctx) override { - VisitNullableCollecting(ctx->smart_parenthesis()); - if (IsEnclosing(ctx)) { - return visitChildren(ctx); - } - return {}; - } - - std::any visitNamed_bind_parameter( - SQLv1::Named_bind_parameterContext* ctx) override { - VisitNullableCollecting(ctx->bind_parameter(0)); - return {}; - } - - std::any visitBind_parameter(SQLv1::Bind_parameterContext* ctx) override { - if (IsEnclosing(ctx) || !IsCollecting_) { - return {}; - } - - TMaybe<std::string> id = GetName(ctx); - if (id.Empty() || id == "_") { - return {}; - } - - (*Names_)[std::move(*id)] = std::monostate(); - return {}; - } - - private: - void VisitNullableCollecting(antlr4::tree::ParseTree* tree) { - if (tree == nullptr) { - return; - } - - const bool old = IsCollecting_; - IsCollecting_ = true; - visit(tree); - IsCollecting_ = old; - } - - TNamedNodes* Names_; - const TEnvironment* Env_; - bool IsCollecting_ = false; - }; - - } // namespace - - TNamedNodes CollectNamedNodes(TParsedInput input, const TEnvironment& env) { - TNamedNodes names; - TVisitor(input, &names, &env).visit(input.SqlQuery); - return names; +namespace { + +class TVisitor: public TSQLv1NarrowingVisitor { +public: + TVisitor(const TParsedInput& input, TNamedNodes* names, const TEnvironment* env) + : TSQLv1NarrowingVisitor(input) + , Names_(names) + , Env_(env) + { } + std::any visitSql_stmt_core(SQLv1::Sql_stmt_coreContext* ctx) override { + if (ctx->declare_stmt() || + ctx->import_stmt() || + ctx->define_action_or_subquery_stmt() || + ctx->named_nodes_stmt() || + IsEnclosing(ctx)) { + return visitChildren(ctx); + } + return {}; + } + + std::any visitDeclare_stmt(SQLv1::Declare_stmtContext* ctx) override { + auto* parameter = ctx->bind_parameter(); + if (!parameter) { + return {}; + } + + TMaybe<std::string> id = GetName(parameter); + if (id.Empty() || id == "_") { + return {}; + } + + id->insert(0, "$"); + const NYT::TNode* node = Env_->Parameters.FindPtr(*id); + id->erase(0, 1); + + if (node) { + (*Names_)[*id] = *node; + } else { + (*Names_)[*id] = std::monostate(); + } + + return {}; + } + + std::any visitImport_stmt(SQLv1::Import_stmtContext* ctx) override { + VisitNullableCollecting(ctx->named_bind_parameter_list()); + return {}; + } + + std::any visitDefine_action_or_subquery_stmt( + SQLv1::Define_action_or_subquery_stmtContext* ctx) override { + VisitNullableCollecting(ctx->bind_parameter()); + if (IsEnclosing(ctx)) { + VisitNullableCollecting(ctx->action_or_subquery_args()); + return visitChildren(ctx); + } + return {}; + } + + std::any visitNamed_nodes_stmt(SQLv1::Named_nodes_stmtContext* ctx) override { + VisitNullableCollecting(ctx->bind_parameter_list()); + if (IsEnclosing(ctx)) { + visitChildren(ctx); + } + + auto* list = ctx->bind_parameter_list(); + if (!list) { + return {}; + } + + auto parameters = list->bind_parameter(); + if (parameters.size() != 1) { + return {}; + } + + auto* parameter = parameters[0]; + if (!parameter) { + return {}; + } + + TMaybe<std::string> id = GetName(parameter); + if (id.Empty() || id == "_") { + return {}; + } + + if (auto* expr = ctx->expr()) { + (*Names_)[std::move(*id)] = expr; + } else { + (*Names_)[std::move(*id)] = std::monostate(); + } + + return {}; + } + + std::any visitFor_stmt(SQLv1::For_stmtContext* ctx) override { + VisitNullableCollecting(ctx->bind_parameter()); + if (IsEnclosing(ctx)) { + return visitChildren(ctx); + } + return {}; + } + + std::any visitLambda(SQLv1::LambdaContext* ctx) override { + VisitNullableCollecting(ctx->smart_parenthesis()); + if (IsEnclosing(ctx)) { + return visitChildren(ctx); + } + return {}; + } + + std::any visitNamed_bind_parameter( + SQLv1::Named_bind_parameterContext* ctx) override { + VisitNullableCollecting(ctx->bind_parameter(0)); + return {}; + } + + std::any visitBind_parameter(SQLv1::Bind_parameterContext* ctx) override { + if (IsEnclosing(ctx) || !IsCollecting_) { + return {}; + } + + TMaybe<std::string> id = GetName(ctx); + if (id.Empty() || id == "_") { + return {}; + } + + (*Names_)[std::move(*id)] = std::monostate(); + return {}; + } + +private: + void VisitNullableCollecting(antlr4::tree::ParseTree* tree) { + if (tree == nullptr) { + return; + } + + const bool old = IsCollecting_; + IsCollecting_ = true; + visit(tree); + IsCollecting_ = old; + } + + TNamedNodes* Names_; + const TEnvironment* Env_; + bool IsCollecting_ = false; +}; + +} // namespace + +TNamedNodes CollectNamedNodes(TParsedInput input, const TEnvironment& env) { + TNamedNodes names; + TVisitor(input, &names, &env).visit(input.SqlQuery); + return names; +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/named_node.h b/yql/essentials/sql/v1/complete/analysis/global/named_node.h index 0050915f523..64ae238e570 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/named_node.h +++ b/yql/essentials/sql/v1/complete/analysis/global/named_node.h @@ -11,13 +11,13 @@ namespace NSQLComplete { - using TNamedNode = std::variant< - SQLv1::ExprContext*, - NYT::TNode, - std::monostate>; +using TNamedNode = std::variant< + SQLv1::ExprContext*, + NYT::TNode, + std::monostate>; - using TNamedNodes = THashMap<TString, TNamedNode>; +using TNamedNodes = THashMap<TString, TNamedNode>; - TNamedNodes CollectNamedNodes(TParsedInput input, const TEnvironment& env); +TNamedNodes CollectNamedNodes(TParsedInput input, const TEnvironment& env); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp index 95f5e1c13bd..8fbb5cfd34d 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp @@ -2,37 +2,37 @@ namespace NSQLComplete { - TSQLv1NarrowingVisitor::TSQLv1NarrowingVisitor(const TParsedInput& input) - : Tokens_(input.Tokens) - , CursorPosition_(input.Original.CursorPosition) - { - } - - bool TSQLv1NarrowingVisitor::shouldVisitNextChild(antlr4::tree::ParseTree* node, const std::any& /*currentResult*/) { - return TextInterval(node).a < static_cast<ssize_t>(CursorPosition_); - } - - bool TSQLv1NarrowingVisitor::IsEnclosing(antlr4::tree::ParseTree* tree) const { - return TextInterval(tree).properlyContains(CursorInterval()); - } - - ssize_t TSQLv1NarrowingVisitor::CursorPosition() const { - return CursorPosition_; - } - - antlr4::misc::Interval TSQLv1NarrowingVisitor::TextInterval(antlr4::tree::ParseTree* tree) const { - auto tokens = tree->getSourceInterval(); - if (tokens.b == -1) { - tokens.b = tokens.a; - } - return antlr4::misc::Interval( - Tokens_->get(tokens.a)->getStartIndex(), - Tokens_->get(tokens.b)->getStopIndex()); - } - - antlr4::misc::Interval TSQLv1NarrowingVisitor::CursorInterval() const { - auto cursor = CursorPosition(); - return antlr4::misc::Interval(cursor, cursor); +TSQLv1NarrowingVisitor::TSQLv1NarrowingVisitor(const TParsedInput& input) + : Tokens_(input.Tokens) + , CursorPosition_(input.Original.CursorPosition) +{ +} + +bool TSQLv1NarrowingVisitor::shouldVisitNextChild(antlr4::tree::ParseTree* node, const std::any& /*currentResult*/) { + return TextInterval(node).a < static_cast<ssize_t>(CursorPosition_); +} + +bool TSQLv1NarrowingVisitor::IsEnclosing(antlr4::tree::ParseTree* tree) const { + return TextInterval(tree).properlyContains(CursorInterval()); +} + +ssize_t TSQLv1NarrowingVisitor::CursorPosition() const { + return CursorPosition_; +} + +antlr4::misc::Interval TSQLv1NarrowingVisitor::TextInterval(antlr4::tree::ParseTree* tree) const { + auto tokens = tree->getSourceInterval(); + if (tokens.b == -1) { + tokens.b = tokens.a; } + return antlr4::misc::Interval( + Tokens_->get(tokens.a)->getStartIndex(), + Tokens_->get(tokens.b)->getStopIndex()); +} + +antlr4::misc::Interval TSQLv1NarrowingVisitor::CursorInterval() const { + auto cursor = CursorPosition(); + return antlr4::misc::Interval(cursor, cursor); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h index 759ad5bd37c..2ae84e5d813 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h +++ b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h @@ -5,21 +5,21 @@ namespace NSQLComplete { - class TSQLv1NarrowingVisitor: public TSQLv1BaseVisitor { - public: - TSQLv1NarrowingVisitor(const TParsedInput& input); +class TSQLv1NarrowingVisitor: public TSQLv1BaseVisitor { +public: + TSQLv1NarrowingVisitor(const TParsedInput& input); - protected: - bool shouldVisitNextChild(antlr4::tree::ParseTree* node, const std::any& /*currentResult*/) override; +protected: + bool shouldVisitNextChild(antlr4::tree::ParseTree* node, const std::any& /*currentResult*/) override; - bool IsEnclosing(antlr4::tree::ParseTree* tree) const; - ssize_t CursorPosition() const; - antlr4::misc::Interval TextInterval(antlr4::tree::ParseTree* tree) const; - antlr4::misc::Interval CursorInterval() const; + bool IsEnclosing(antlr4::tree::ParseTree* tree) const; + ssize_t CursorPosition() const; + antlr4::misc::Interval TextInterval(antlr4::tree::ParseTree* tree) const; + antlr4::misc::Interval CursorInterval() const; - private: - antlr4::TokenStream* Tokens_; - size_t CursorPosition_; - }; +private: + antlr4::TokenStream* Tokens_; + size_t CursorPosition_; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/parse_tree.cpp b/yql/essentials/sql/v1/complete/analysis/global/parse_tree.cpp index 3577a6cf8d1..b14dba9220e 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/parse_tree.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/parse_tree.cpp @@ -7,20 +7,20 @@ namespace NSQLComplete { - TMaybe<std::string> GetName(SQLv1::Bind_parameterContext* ctx) { - if (ctx == nullptr) { - return Nothing(); - } +TMaybe<std::string> GetName(SQLv1::Bind_parameterContext* ctx) { + if (ctx == nullptr) { + return Nothing(); + } - if (auto* x = ctx->an_id_or_type()) { - return x->getText(); - } else if (auto* x = ctx->TOKEN_TRUE()) { - return x->getText(); - } else if (auto* x = ctx->TOKEN_FALSE()) { - return x->getText(); - } else { - return Nothing(); - } + if (auto* x = ctx->an_id_or_type()) { + return x->getText(); + } else if (auto* x = ctx->TOKEN_TRUE()) { + return x->getText(); + } else if (auto* x = ctx->TOKEN_FALSE()) { + return x->getText(); + } else { + return Nothing(); } +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/parse_tree.h b/yql/essentials/sql/v1/complete/analysis/global/parse_tree.h index 72423526547..733e2e27e7b 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/parse_tree.h +++ b/yql/essentials/sql/v1/complete/analysis/global/parse_tree.h @@ -13,10 +13,10 @@ namespace NSQLComplete { - using SQLv1 = NALADefaultAntlr4::SQLv1Antlr4Parser; +using SQLv1 = NALADefaultAntlr4::SQLv1Antlr4Parser; - using NALADefaultAntlr4::SQLv1Antlr4BaseVisitor; +using NALADefaultAntlr4::SQLv1Antlr4BaseVisitor; - TMaybe<std::string> GetName(SQLv1::Bind_parameterContext* ctx); +TMaybe<std::string> GetName(SQLv1::Bind_parameterContext* ctx); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/use.cpp b/yql/essentials/sql/v1/complete/analysis/global/use.cpp index 89e5ae458e6..58b6b13bb09 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/use.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/use.cpp @@ -5,111 +5,111 @@ namespace NSQLComplete { - namespace { - - class TVisitor: public TSQLv1NarrowingVisitor { - public: - TVisitor(const TParsedInput& input, const TNamedNodes* nodes) - : TSQLv1NarrowingVisitor(input) - , Nodes_(nodes) - { - } - - std::any visitSql_stmt_core(SQLv1::Sql_stmt_coreContext* ctx) override { - if (ctx->use_stmt() || IsEnclosing(ctx)) { - return visitChildren(ctx); - } - return {}; - } - - std::any visitUse_stmt(SQLv1::Use_stmtContext* ctx) override { - SQLv1::Cluster_exprContext* expr = ctx->cluster_expr(); - if (!expr) { - return {}; - } - - TMaybe<TClusterContext> cluster = ParseClusterContext(expr, *Nodes_); - if (!cluster) { - return {}; - } +namespace { + +class TVisitor: public TSQLv1NarrowingVisitor { +public: + TVisitor(const TParsedInput& input, const TNamedNodes* nodes) + : TSQLv1NarrowingVisitor(input) + , Nodes_(nodes) + { + } - return *cluster; - } + std::any visitSql_stmt_core(SQLv1::Sql_stmt_coreContext* ctx) override { + if (ctx->use_stmt() || IsEnclosing(ctx)) { + return visitChildren(ctx); + } + return {}; + } - private: - const TNamedNodes* Nodes_; - }; + std::any visitUse_stmt(SQLv1::Use_stmtContext* ctx) override { + SQLv1::Cluster_exprContext* expr = ctx->cluster_expr(); + if (!expr) { + return {}; + } - class TClusterVisitor: public TSQLv1BaseVisitor { - public: - explicit TClusterVisitor(const TNamedNodes* nodes) - : Nodes_(nodes) - { - } + TMaybe<TClusterContext> cluster = ParseClusterContext(expr, *Nodes_); + if (!cluster) { + return {}; + } - std::any visitCluster_expr(SQLv1::Cluster_exprContext* ctx) { - std::string provider; - std::string cluster; + return *cluster; + } - if (SQLv1::An_idContext* id = ctx->an_id()) { - provider = id->getText(); - } +private: + const TNamedNodes* Nodes_; +}; - if (SQLv1::Pure_column_or_namedContext* named = ctx->pure_column_or_named()) { - if (auto id = GetId(named)) { - cluster = std::move(*id); - } - } +class TClusterVisitor: public TSQLv1BaseVisitor { +public: + explicit TClusterVisitor(const TNamedNodes* nodes) + : Nodes_(nodes) + { + } - if (cluster.empty()) { - return {}; - } + std::any visitCluster_expr(SQLv1::Cluster_exprContext* ctx) { + std::string provider; + std::string cluster; - return TClusterContext{ - .Provider = std::move(provider), - .Name = std::move(cluster), - }; - } + if (SQLv1::An_idContext* id = ctx->an_id()) { + provider = id->getText(); + } - private: - TMaybe<TString> GetId(SQLv1::Pure_column_or_namedContext* ctx) const { - if (auto* x = ctx->bind_parameter()) { - return GetId(x); - } else if (auto* x = ctx->an_id()) { - return x->getText(); - } else { - Y_ABORT("You should change implementation according grammar changes"); - } + if (SQLv1::Pure_column_or_namedContext* named = ctx->pure_column_or_named()) { + if (auto id = GetId(named)) { + cluster = std::move(*id); } + } - TMaybe<TString> GetId(SQLv1::Bind_parameterContext* ctx) const { - NYT::TNode node = Evaluate(ctx, *Nodes_); - if (!node.HasValue() || !node.IsString()) { - return Nothing(); - } - return node.AsString(); - } + if (cluster.empty()) { + return {}; + } - const TNamedNodes* Nodes_; + return TClusterContext{ + .Provider = std::move(provider), + .Name = std::move(cluster), }; + } - } // namespace - - TMaybe<TClusterContext> ParseClusterContext(SQLv1::Cluster_exprContext* ctx, const TNamedNodes& nodes) { - std::any result = TClusterVisitor(&nodes).visit(ctx); - if (!result.has_value()) { - return Nothing(); +private: + TMaybe<TString> GetId(SQLv1::Pure_column_or_namedContext* ctx) const { + if (auto* x = ctx->bind_parameter()) { + return GetId(x); + } else if (auto* x = ctx->an_id()) { + return x->getText(); + } else { + Y_ABORT("You should change implementation according grammar changes"); } - return std::any_cast<TClusterContext>(result); } - // TODO(YQL-19747): Use any to maybe conversion function - TMaybe<TClusterContext> FindUseStatement(TParsedInput input, const TNamedNodes& nodes) { - std::any result = TVisitor(input, &nodes).visit(input.SqlQuery); - if (!result.has_value()) { + TMaybe<TString> GetId(SQLv1::Bind_parameterContext* ctx) const { + NYT::TNode node = Evaluate(ctx, *Nodes_); + if (!node.HasValue() || !node.IsString()) { return Nothing(); } - return std::any_cast<TClusterContext>(result); + return node.AsString(); + } + + const TNamedNodes* Nodes_; +}; + +} // namespace + +TMaybe<TClusterContext> ParseClusterContext(SQLv1::Cluster_exprContext* ctx, const TNamedNodes& nodes) { + std::any result = TClusterVisitor(&nodes).visit(ctx); + if (!result.has_value()) { + return Nothing(); + } + return std::any_cast<TClusterContext>(result); +} + +// TODO(YQL-19747): Use any to maybe conversion function +TMaybe<TClusterContext> FindUseStatement(TParsedInput input, const TNamedNodes& nodes) { + std::any result = TVisitor(input, &nodes).visit(input.SqlQuery); + if (!result.has_value()) { + return Nothing(); } + return std::any_cast<TClusterContext>(result); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/use.h b/yql/essentials/sql/v1/complete/analysis/global/use.h index 2ecda65daaa..9cb48d1951d 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/use.h +++ b/yql/essentials/sql/v1/complete/analysis/global/use.h @@ -10,8 +10,8 @@ namespace NSQLComplete { - TMaybe<TClusterContext> ParseClusterContext(SQLv1::Cluster_exprContext* ctx, const TNamedNodes& nodes); +TMaybe<TClusterContext> ParseClusterContext(SQLv1::Cluster_exprContext* ctx, const TNamedNodes& nodes); - TMaybe<TClusterContext> FindUseStatement(TParsedInput input, const TNamedNodes& nodes); +TMaybe<TClusterContext> FindUseStatement(TParsedInput input, const TNamedNodes& nodes); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.cpp b/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.cpp index 0c091b6c4ee..77a9289edb4 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.cpp +++ b/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.cpp @@ -5,161 +5,161 @@ namespace NSQLComplete { - namespace { - - bool Tokenize(ILexer::TPtr& lexer, TCompletionInput input, TParsedTokenList& tokens) { - NYql::TIssues issues; - if (!NSQLTranslation::Tokenize( - *lexer, TString(input.Text), /* queryName = */ "", - tokens, issues, /* maxErrors = */ 1)) { - return false; - } - return true; - } +namespace { + +bool Tokenize(ILexer::TPtr& lexer, TCompletionInput input, TParsedTokenList& tokens) { + NYql::TIssues issues; + if (!NSQLTranslation::Tokenize( + *lexer, TString(input.Text), /* queryName = */ "", + tokens, issues, /* maxErrors = */ 1)) { + return false; + } + return true; +} - TCursor GetCursor(const TParsedTokenList& tokens, size_t cursorPosition) { - size_t current = 0; - for (size_t i = 0; i < tokens.size() && current < cursorPosition; ++i) { - const auto& content = tokens[i].Content; - - current += content.size(); - if (current < cursorPosition) { - continue; - } - - TCursor cursor = { - .PrevTokenIndex = i, - .NextTokenIndex = i, - .Position = cursorPosition, - }; - - if (current == cursorPosition) { - cursor.NextTokenIndex += 1; - } - - return cursor; - } - - return { - .PrevTokenIndex = Nothing(), - .NextTokenIndex = 0, - .Position = cursorPosition, - }; - } +TCursor GetCursor(const TParsedTokenList& tokens, size_t cursorPosition) { + size_t current = 0; + for (size_t i = 0; i < tokens.size() && current < cursorPosition; ++i) { + const auto& content = tokens[i].Content; - TVector<size_t> GetTokenPositions(const TParsedTokenList& tokens) { - TVector<size_t> positions; - positions.reserve(tokens.size()); - size_t pos = 0; - for (const auto& token : tokens) { - positions.emplace_back(pos); - pos += token.Content.size(); - } - return positions; + current += content.size(); + if (current < cursorPosition) { + continue; } - } // namespace + TCursor cursor = { + .PrevTokenIndex = i, + .NextTokenIndex = i, + .Position = cursorPosition, + }; - bool TRichParsedToken::IsLiteral() const { - return Base->Name == "STRING_VALUE" || - Base->Name == "DIGIGTS" || - Base->Name == "INTEGER_VALUE" || - Base->Name == "REAL"; - } + if (current == cursorPosition) { + cursor.NextTokenIndex += 1; + } - size_t TRichParsedToken::End() const { - return Position + Base->Content.size(); + return cursor; } - TRichParsedToken TokenAt(const TCursorTokenContext& context, size_t index) { - return { - .Base = &context.Tokens.at(index), - .Index = index, - .Position = context.TokenPositions.at(index), - }; + return { + .PrevTokenIndex = Nothing(), + .NextTokenIndex = 0, + .Position = cursorPosition, + }; +} + +TVector<size_t> GetTokenPositions(const TParsedTokenList& tokens) { + TVector<size_t> positions; + positions.reserve(tokens.size()); + size_t pos = 0; + for (const auto& token : tokens) { + positions.emplace_back(pos); + pos += token.Content.size(); + } + return positions; +} + +} // namespace + +bool TRichParsedToken::IsLiteral() const { + return Base->Name == "STRING_VALUE" || + Base->Name == "DIGIGTS" || + Base->Name == "INTEGER_VALUE" || + Base->Name == "REAL"; +} + +size_t TRichParsedToken::End() const { + return Position + Base->Content.size(); +} + +TRichParsedToken TokenAt(const TCursorTokenContext& context, size_t index) { + return { + .Base = &context.Tokens.at(index), + .Index = index, + .Position = context.TokenPositions.at(index), + }; +} + +TMaybe<TRichParsedToken> TCursorTokenContext::Enclosing() const { + if (Tokens.size() == 1) { + Y_ENSURE(Tokens[0].Name == "EOF"); + return Nothing(); } - TMaybe<TRichParsedToken> TCursorTokenContext::Enclosing() const { - if (Tokens.size() == 1) { - Y_ENSURE(Tokens[0].Name == "EOF"); - return Nothing(); - } + if (Cursor.PrevTokenIndex.Empty()) { + return Nothing(); + } - if (Cursor.PrevTokenIndex.Empty()) { - return Nothing(); - } + auto token = TokenAt(*this, *Cursor.PrevTokenIndex); + if (Cursor.PrevTokenIndex == Cursor.NextTokenIndex || + !IsWordBoundary(token.Base->Content.back())) { + return token; + } - auto token = TokenAt(*this, *Cursor.PrevTokenIndex); - if (Cursor.PrevTokenIndex == Cursor.NextTokenIndex || - !IsWordBoundary(token.Base->Content.back())) { - return token; - } + return Nothing(); +} +TMaybe<TRichParsedToken> TCursorTokenContext::MatchCursorPrefix(const TVector<TStringBuf>& pattern) const { + const auto prefix = std::span{Tokens.begin(), Cursor.NextTokenIndex}; + if (prefix.size() < pattern.size()) { return Nothing(); } - TMaybe<TRichParsedToken> TCursorTokenContext::MatchCursorPrefix(const TVector<TStringBuf>& pattern) const { - const auto prefix = std::span{Tokens.begin(), Cursor.NextTokenIndex}; - if (prefix.size() < pattern.size()) { + ssize_t i = static_cast<ssize_t>(prefix.size()) - 1; + ssize_t j = static_cast<ssize_t>(pattern.size()) - 1; + for (; 0 <= j; --i, --j) { + if (!pattern[j].empty() && prefix[i].Name != pattern[j]) { return Nothing(); } - - ssize_t i = static_cast<ssize_t>(prefix.size()) - 1; - ssize_t j = static_cast<ssize_t>(pattern.size()) - 1; - for (; 0 <= j; --i, --j) { - if (!pattern[j].empty() && prefix[i].Name != pattern[j]) { - return Nothing(); - } - } - return TokenAt(*this, prefix.size() - pattern.size()); + } + return TokenAt(*this, prefix.size() - pattern.size()); +} + +bool GetStatement( + ILexer::TPtr& lexer, + const TMaterializedInput& input, + TCompletionInput& output, + size_t& output_position) { + TVector<TString> statements; + NYql::TIssues issues; + if (!NSQLTranslationV1::SplitQueryToStatements( + input.Text, lexer, + statements, issues, /* file = */ "", + /* areBlankSkipped = */ false)) { + return false; } - bool GetStatement( - ILexer::TPtr& lexer, - const TMaterializedInput& input, - TCompletionInput& output, - size_t& output_position) { - TVector<TString> statements; - NYql::TIssues issues; - if (!NSQLTranslationV1::SplitQueryToStatements( - input.Text, lexer, - statements, issues, /* file = */ "", - /* areBlankSkipped = */ false)) { - return false; - } - - size_t& cursor = output_position; - cursor = 0; - for (const auto& statement : statements) { - if (input.CursorPosition < cursor + statement.size()) { - output = { - .Text = TStringBuf(input.Text).SubStr(cursor, statement.size()), - .CursorPosition = input.CursorPosition - cursor, - }; - return true; - } - cursor += statement.size(); + size_t& cursor = output_position; + cursor = 0; + for (const auto& statement : statements) { + if (input.CursorPosition < cursor + statement.size()) { + output = { + .Text = TStringBuf(input.Text).SubStr(cursor, statement.size()), + .CursorPosition = input.CursorPosition - cursor, + }; + return true; } - - output.Text = TStringBuf(input.Text); - output.CursorPosition = input.CursorPosition; - return true; + cursor += statement.size(); } - bool GetCursorTokenContext(ILexer::TPtr& lexer, TCompletionInput input, TCursorTokenContext& context) { - TParsedTokenList tokens; - if (!Tokenize(lexer, input, tokens)) { - return false; - } + output.Text = TStringBuf(input.Text); + output.CursorPosition = input.CursorPosition; + return true; +} - TVector<size_t> positions = GetTokenPositions(tokens); - TCursor cursor = GetCursor(tokens, input.CursorPosition); - context = { - .Tokens = std::move(tokens), - .TokenPositions = std::move(positions), - .Cursor = cursor, - }; - return true; +bool GetCursorTokenContext(ILexer::TPtr& lexer, TCompletionInput input, TCursorTokenContext& context) { + TParsedTokenList tokens; + if (!Tokenize(lexer, input, tokens)) { + return false; } + TVector<size_t> positions = GetTokenPositions(tokens); + TCursor cursor = GetCursor(tokens, input.CursorPosition); + context = { + .Tokens = std::move(tokens), + .TokenPositions = std::move(positions), + .Cursor = cursor, + }; + return true; +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.h b/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.h index 987bfa90914..5daa36f3e86 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.h +++ b/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.h @@ -9,43 +9,43 @@ namespace NSQLComplete { - using NSQLTranslation::ILexer; - using NSQLTranslation::TParsedToken; - using NSQLTranslation::TParsedTokenList; - - struct TCursor { - TMaybe<size_t> PrevTokenIndex = Nothing(); - size_t NextTokenIndex = PrevTokenIndex ? *PrevTokenIndex : 0; - size_t Position = 0; - }; - - struct TRichParsedToken { - const TParsedToken* Base = nullptr; - size_t Index = 0; - size_t Position = 0; - - bool IsLiteral() const; - size_t End() const; - }; - - struct TCursorTokenContext { - TParsedTokenList Tokens; - TVector<size_t> TokenPositions; - TCursor Cursor; - - TMaybe<TRichParsedToken> Enclosing() const; - TMaybe<TRichParsedToken> MatchCursorPrefix(const TVector<TStringBuf>& pattern) const; - }; - - bool GetStatement( - ILexer::TPtr& lexer, - const TMaterializedInput& input, - TCompletionInput& output, - size_t& output_position); - - bool GetCursorTokenContext( - ILexer::TPtr& lexer, - TCompletionInput input, - TCursorTokenContext& context); +using NSQLTranslation::ILexer; +using NSQLTranslation::TParsedToken; +using NSQLTranslation::TParsedTokenList; + +struct TCursor { + TMaybe<size_t> PrevTokenIndex = Nothing(); + size_t NextTokenIndex = PrevTokenIndex ? *PrevTokenIndex : 0; + size_t Position = 0; +}; + +struct TRichParsedToken { + const TParsedToken* Base = nullptr; + size_t Index = 0; + size_t Position = 0; + + bool IsLiteral() const; + size_t End() const; +}; + +struct TCursorTokenContext { + TParsedTokenList Tokens; + TVector<size_t> TokenPositions; + TCursor Cursor; + + TMaybe<TRichParsedToken> Enclosing() const; + TMaybe<TRichParsedToken> MatchCursorPrefix(const TVector<TStringBuf>& pattern) const; +}; + +bool GetStatement( + ILexer::TPtr& lexer, + const TMaterializedInput& input, + TCompletionInput& output, + size_t& output_position); + +bool GetCursorTokenContext( + ILexer::TPtr& lexer, + TCompletionInput input, + TCursorTokenContext& context); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context_ut.cpp b/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context_ut.cpp index 0e275cca3b8..c6fd330c130 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context_ut.cpp +++ b/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context_ut.cpp @@ -9,42 +9,42 @@ using namespace NSQLComplete; Y_UNIT_TEST_SUITE(CursorTokenContextTests) { - NSQLTranslation::ILexer::TPtr MakeLexer() { - NSQLTranslationV1::TLexers lexers; - lexers.Antlr4Pure = NSQLTranslationV1::MakeAntlr4PureLexerFactory(); - return NSQLTranslationV1::MakeLexer( - lexers, /* ansi = */ false, /* antlr4 = */ true, - NSQLTranslationV1::ELexerFlavor::Pure); - } - - TCursorTokenContext Context(TString input) { - auto lexer = MakeLexer(); - TCursorTokenContext context; - UNIT_ASSERT(GetCursorTokenContext(lexer, SharpedInput(input), context)); - return context; - } - - Y_UNIT_TEST(Empty) { - auto context = Context(""); - UNIT_ASSERT(context.Cursor.PrevTokenIndex.Empty()); - UNIT_ASSERT_VALUES_EQUAL(context.Cursor.NextTokenIndex, 0); - UNIT_ASSERT_VALUES_EQUAL(context.Cursor.Position, 0); - UNIT_ASSERT(context.Enclosing().Empty()); - } - - Y_UNIT_TEST(Blank) { - UNIT_ASSERT(Context("# ").Enclosing().Empty()); - UNIT_ASSERT(Context(" #").Enclosing().Empty()); - UNIT_ASSERT(Context(" # ").Enclosing().Empty()); - } - - Y_UNIT_TEST(Enclosing) { - UNIT_ASSERT(Context("se#").Enclosing().Defined()); - UNIT_ASSERT(Context("#se").Enclosing().Empty()); - UNIT_ASSERT(Context("`se`#").Enclosing().Empty()); - UNIT_ASSERT(Context("#`se`").Enclosing().Empty()); - UNIT_ASSERT(Context("`se`#`se`").Enclosing().Defined()); - UNIT_ASSERT(Context("\"se\"#\"se\"").Enclosing().Empty()); - } +NSQLTranslation::ILexer::TPtr MakeLexer() { + NSQLTranslationV1::TLexers lexers; + lexers.Antlr4Pure = NSQLTranslationV1::MakeAntlr4PureLexerFactory(); + return NSQLTranslationV1::MakeLexer( + lexers, /* ansi = */ false, /* antlr4 = */ true, + NSQLTranslationV1::ELexerFlavor::Pure); +} + +TCursorTokenContext Context(TString input) { + auto lexer = MakeLexer(); + TCursorTokenContext context; + UNIT_ASSERT(GetCursorTokenContext(lexer, SharpedInput(input), context)); + return context; +} + +Y_UNIT_TEST(Empty) { + auto context = Context(""); + UNIT_ASSERT(context.Cursor.PrevTokenIndex.Empty()); + UNIT_ASSERT_VALUES_EQUAL(context.Cursor.NextTokenIndex, 0); + UNIT_ASSERT_VALUES_EQUAL(context.Cursor.Position, 0); + UNIT_ASSERT(context.Enclosing().Empty()); +} + +Y_UNIT_TEST(Blank) { + UNIT_ASSERT(Context("# ").Enclosing().Empty()); + UNIT_ASSERT(Context(" #").Enclosing().Empty()); + UNIT_ASSERT(Context(" # ").Enclosing().Empty()); +} + +Y_UNIT_TEST(Enclosing) { + UNIT_ASSERT(Context("se#").Enclosing().Defined()); + UNIT_ASSERT(Context("#se").Enclosing().Empty()); + UNIT_ASSERT(Context("`se`#").Enclosing().Empty()); + UNIT_ASSERT(Context("#`se`").Enclosing().Empty()); + UNIT_ASSERT(Context("`se`#`se`").Enclosing().Defined()); + UNIT_ASSERT(Context("\"se\"#\"se\"").Enclosing().Empty()); +} } // Y_UNIT_TEST_SUITE(CursorTokenContextTests) diff --git a/yql/essentials/sql/v1/complete/analysis/local/local.cpp b/yql/essentials/sql/v1/complete/analysis/local/local.cpp index aa5c87e6169..f10bdabb177 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/local.cpp +++ b/yql/essentials/sql/v1/complete/analysis/local/local.cpp @@ -26,425 +26,425 @@ namespace NSQLComplete { - enum class ERangeKind { - Replace, - Filter, +enum class ERangeKind { + Replace, + Filter, +}; + +template <std::regular_invocable<TParserCallStack> StackPredicate> +std::regular_invocable<TMatchedRule> auto RuleAdapted(StackPredicate predicate) { + return [=](const TMatchedRule& rule) { + return predicate(rule.ParserCallStack); }; - - template <std::regular_invocable<TParserCallStack> StackPredicate> - std::regular_invocable<TMatchedRule> auto RuleAdapted(StackPredicate predicate) { - return [=](const TMatchedRule& rule) { - return predicate(rule.ParserCallStack); - }; +} + +template <bool IsAnsiLexer> +class TSpecializedLocalSyntaxAnalysis: public ILocalSyntaxAnalysis { +private: + using TDefaultYQLGrammar = TAntlrGrammar< + NALADefaultAntlr4::SQLv1Antlr4Lexer, + NALADefaultAntlr4::SQLv1Antlr4Parser>; + + using TAnsiYQLGrammar = TAntlrGrammar< + NALAAnsiAntlr4::SQLv1Antlr4Lexer, + NALAAnsiAntlr4::SQLv1Antlr4Parser>; + + using G = std::conditional_t< + IsAnsiLexer, + TAnsiYQLGrammar, + TDefaultYQLGrammar>; + +public: + TSpecializedLocalSyntaxAnalysis( + TLexerSupplier lexer, + const THashSet<TString>& ignoredRules, + const THashMap<TString, THashSet<TString>>& disabledPreviousByToken, + const THashMap<TString, THashSet<TString>>& forcedPreviousByToken) + : Grammar_(&GetSqlGrammar()) + , Lexer_(lexer(/* ansi = */ IsAnsiLexer)) + , C3_(ComputeC3Config(ignoredRules, disabledPreviousByToken, forcedPreviousByToken)) + { } - template <bool IsAnsiLexer> - class TSpecializedLocalSyntaxAnalysis: public ILocalSyntaxAnalysis { - private: - using TDefaultYQLGrammar = TAntlrGrammar< - NALADefaultAntlr4::SQLv1Antlr4Lexer, - NALADefaultAntlr4::SQLv1Antlr4Parser>; - - using TAnsiYQLGrammar = TAntlrGrammar< - NALAAnsiAntlr4::SQLv1Antlr4Lexer, - NALAAnsiAntlr4::SQLv1Antlr4Parser>; - - using G = std::conditional_t< - IsAnsiLexer, - TAnsiYQLGrammar, - TDefaultYQLGrammar>; - - public: - TSpecializedLocalSyntaxAnalysis( - TLexerSupplier lexer, - const THashSet<TString>& ignoredRules, - const THashMap<TString, THashSet<TString>>& disabledPreviousByToken, - const THashMap<TString, THashSet<TString>>& forcedPreviousByToken) - : Grammar_(&GetSqlGrammar()) - , Lexer_(lexer(/* ansi = */ IsAnsiLexer)) - , C3_(ComputeC3Config(ignoredRules, disabledPreviousByToken, forcedPreviousByToken)) - { - } - - TLocalSyntaxContext Analyze(TCompletionInput input) override { - TMaterializedInput materialized = { - .Text = TString(input.Text), - .CursorPosition = input.CursorPosition, - }; + TLocalSyntaxContext Analyze(TCompletionInput input) override { + TMaterializedInput materialized = { + .Text = TString(input.Text), + .CursorPosition = input.CursorPosition, + }; - // - ";" is for a correct stetement split - // - "-- `" is for a ilformed ID_QUOTED recovery - materialized.Text += "; -- `"; + // - ";" is for a correct stetement split + // - "-- `" is for a ilformed ID_QUOTED recovery + materialized.Text += "; -- `"; - TCompletionInput statement; - size_t statement_position; - if (!GetStatement(Lexer_, materialized, statement, statement_position)) { - return {}; - } + TCompletionInput statement; + size_t statement_position; + if (!GetStatement(Lexer_, materialized, statement, statement_position)) { + return {}; + } - TCursorTokenContext context; - if (!GetCursorTokenContext(Lexer_, statement, context)) { - return {}; - } + TCursorTokenContext context; + if (!GetCursorTokenContext(Lexer_, statement, context)) { + return {}; + } - TC3Candidates candidates = C3Complete(statement, context); + TC3Candidates candidates = C3Complete(statement, context); - TLocalSyntaxContext result; + TLocalSyntaxContext result; - result.IsQuoted = Quotation(input, context); + result.IsQuoted = Quotation(input, context); - result.ReplaceRange = EditRange(context, ERangeKind::Replace); - result.ReplaceRange.Begin += statement_position; + result.ReplaceRange = EditRange(context, ERangeKind::Replace); + result.ReplaceRange.Begin += statement_position; - result.FilterRange = EditRange(context, ERangeKind::Filter); - result.FilterRange.Begin += statement_position; + result.FilterRange = EditRange(context, ERangeKind::Filter); + result.FilterRange.Begin += statement_position; - if (auto enclosing = context.Enclosing()) { - if (enclosing->IsLiteral()) { - return result; - } + if (auto enclosing = context.Enclosing()) { + if (enclosing->IsLiteral()) { + return result; + } - if (enclosing->Base->Name == "ID_QUOTED") { - result.Object = ObjectMatch(context, candidates); - return result; - } + if (enclosing->Base->Name == "ID_QUOTED") { + result.Object = ObjectMatch(context, candidates); + return result; } + } - result.Keywords = SiftedKeywords(candidates); - result.Pragma = PragmaMatch(context, candidates); - result.Type = TypeMatch(candidates); - result.Function = FunctionMatch(context, candidates); - result.Hint = HintMatch(candidates); - result.Object = ObjectMatch(context, candidates); - result.Cluster = ClusterMatch(context, candidates); - result.Column = ColumnMatch(context, candidates); - result.Binding = BindingMatch(candidates); + result.Keywords = SiftedKeywords(candidates); + result.Pragma = PragmaMatch(context, candidates); + result.Type = TypeMatch(candidates); + result.Function = FunctionMatch(context, candidates); + result.Hint = HintMatch(candidates); + result.Object = ObjectMatch(context, candidates); + result.Cluster = ClusterMatch(context, candidates); + result.Column = ColumnMatch(context, candidates); + result.Binding = BindingMatch(candidates); + + return result; + } - return result; - } +private: + IC3Engine::TConfig ComputeC3Config( + const THashSet<TString>& ignoredRules, + const THashMap<TString, THashSet<TString>>& disabledPreviousByToken, + const THashMap<TString, THashSet<TString>>& forcedPreviousByToken) const { + return { + .IgnoredTokens = ComputeIgnoredTokens(), + .PreferredRules = ComputePreferredRules(), + .IgnoredRules = ComputeIgnoredRules(ignoredRules), + .DisabledPreviousByToken = Resolved(disabledPreviousByToken), + .ForcedPreviousByToken = Resolved(forcedPreviousByToken), + }; + } - private: - IC3Engine::TConfig ComputeC3Config( - const THashSet<TString>& ignoredRules, - const THashMap<TString, THashSet<TString>>& disabledPreviousByToken, - const THashMap<TString, THashSet<TString>>& forcedPreviousByToken) const { - return { - .IgnoredTokens = ComputeIgnoredTokens(), - .PreferredRules = ComputePreferredRules(), - .IgnoredRules = ComputeIgnoredRules(ignoredRules), - .DisabledPreviousByToken = Resolved(disabledPreviousByToken), - .ForcedPreviousByToken = Resolved(forcedPreviousByToken), - }; + std::unordered_set<TTokenId> ComputeIgnoredTokens() const { + auto ignoredTokens = Grammar_->GetAllTokens(); + for (auto keywordToken : Grammar_->GetKeywordTokens()) { + ignoredTokens.erase(keywordToken); } - - std::unordered_set<TTokenId> ComputeIgnoredTokens() const { - auto ignoredTokens = Grammar_->GetAllTokens(); - for (auto keywordToken : Grammar_->GetKeywordTokens()) { - ignoredTokens.erase(keywordToken); - } - for (auto punctuationToken : Grammar_->GetPunctuationTokens()) { - ignoredTokens.erase(punctuationToken); - } - return ignoredTokens; + for (auto punctuationToken : Grammar_->GetPunctuationTokens()) { + ignoredTokens.erase(punctuationToken); } + return ignoredTokens; + } - std::unordered_set<TRuleId> ComputePreferredRules() const { - return GetC3PreferredRules(); - } + std::unordered_set<TRuleId> ComputePreferredRules() const { + return GetC3PreferredRules(); + } - std::unordered_set<TRuleId> ComputeIgnoredRules(const THashSet<TString>& IgnoredRules) const { - std::unordered_set<TRuleId> ignored; - ignored.reserve(IgnoredRules.size()); - for (const auto& ruleName : IgnoredRules) { - ignored.emplace(Grammar_->GetRuleId(ruleName)); - } - return ignored; + std::unordered_set<TRuleId> ComputeIgnoredRules(const THashSet<TString>& IgnoredRules) const { + std::unordered_set<TRuleId> ignored; + ignored.reserve(IgnoredRules.size()); + for (const auto& ruleName : IgnoredRules) { + ignored.emplace(Grammar_->GetRuleId(ruleName)); } + return ignored; + } - std::unordered_map<TTokenId, std::unordered_set<TTokenId>> - Resolved(const THashMap<TString, THashSet<TString>>& tokens) const { - std::unordered_map<TTokenId, std::unordered_set<TTokenId>> resolved; - for (const auto& [name, set] : tokens) { - resolved[Grammar_->GetTokenId(name)] = Resolved(set); - } - return resolved; + std::unordered_map<TTokenId, std::unordered_set<TTokenId>> + Resolved(const THashMap<TString, THashSet<TString>>& tokens) const { + std::unordered_map<TTokenId, std::unordered_set<TTokenId>> resolved; + for (const auto& [name, set] : tokens) { + resolved[Grammar_->GetTokenId(name)] = Resolved(set); } + return resolved; + } - std::unordered_set<TTokenId> Resolved(const THashSet<TString>& tokens) const { - std::unordered_set<TTokenId> resolved; - for (const TString& name : tokens) { - resolved.emplace(Grammar_->GetTokenId(name)); - } - return resolved; + std::unordered_set<TTokenId> Resolved(const THashSet<TString>& tokens) const { + std::unordered_set<TTokenId> resolved; + for (const TString& name : tokens) { + resolved.emplace(Grammar_->GetTokenId(name)); } + return resolved; + } - TC3Candidates C3Complete(TCompletionInput statement, const TCursorTokenContext& context) { - auto enclosing = context.Enclosing(); - - size_t caretTokenIndex = context.Cursor.NextTokenIndex; - if (enclosing.Defined()) { - caretTokenIndex = enclosing->Index; - } - - TStringBuf text = statement.Text; - if (enclosing.Defined() && enclosing->Base->Name == "NOT_EQUALS2") { - text = statement.Text.Head(statement.CursorPosition); - caretTokenIndex += 1; - } + TC3Candidates C3Complete(TCompletionInput statement, const TCursorTokenContext& context) { + auto enclosing = context.Enclosing(); - return C3_.Complete(text, caretTokenIndex); + size_t caretTokenIndex = context.Cursor.NextTokenIndex; + if (enclosing.Defined()) { + caretTokenIndex = enclosing->Index; } - TLocalSyntaxContext::TKeywords SiftedKeywords(const TC3Candidates& candidates) const { - const auto& vocabulary = Grammar_->GetVocabulary(); - const auto& keywordTokens = Grammar_->GetKeywordTokens(); - - TLocalSyntaxContext::TKeywords keywords; - for (const auto& token : candidates.Tokens) { - if (keywordTokens.contains(token.Number)) { - auto& following = keywords[Display(vocabulary, token.Number)]; - for (auto next : token.Following) { - following.emplace_back(Display(vocabulary, next)); - } - } - } - return keywords; + TStringBuf text = statement.Text; + if (enclosing.Defined() && enclosing->Base->Name == "NOT_EQUALS2") { + text = statement.Text.Head(statement.CursorPosition); + caretTokenIndex += 1; } - TMaybe<TLocalSyntaxContext::TPragma> PragmaMatch( - const TCursorTokenContext& context, const TC3Candidates& candidates) const { - if (!AnyOf(candidates.Rules, RuleAdapted(IsLikelyPragmaStack))) { - return Nothing(); - } + return C3_.Complete(text, caretTokenIndex); + } - TLocalSyntaxContext::TPragma pragma; + TLocalSyntaxContext::TKeywords SiftedKeywords(const TC3Candidates& candidates) const { + const auto& vocabulary = Grammar_->GetVocabulary(); + const auto& keywordTokens = Grammar_->GetKeywordTokens(); - if (TMaybe<TRichParsedToken> begin; - (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT"})) || - (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT", ""}))) { - pragma.Namespace = begin->Base->Content; + TLocalSyntaxContext::TKeywords keywords; + for (const auto& token : candidates.Tokens) { + if (keywordTokens.contains(token.Number)) { + auto& following = keywords[Display(vocabulary, token.Number)]; + for (auto next : token.Following) { + following.emplace_back(Display(vocabulary, next)); + } } - return pragma; } + return keywords; + } - bool TypeMatch(const TC3Candidates& candidates) const { - return AnyOf(candidates.Rules, RuleAdapted(IsLikelyTypeStack)); + TMaybe<TLocalSyntaxContext::TPragma> PragmaMatch( + const TCursorTokenContext& context, const TC3Candidates& candidates) const { + if (!AnyOf(candidates.Rules, RuleAdapted(IsLikelyPragmaStack))) { + return Nothing(); } - TMaybe<TLocalSyntaxContext::TFunction> FunctionMatch( - const TCursorTokenContext& context, const TC3Candidates& candidates) const { - const bool isAnyFunction = AnyOf(candidates.Rules, RuleAdapted(IsLikelyFunctionStack)); - const bool isTableFunction = AnyOf(candidates.Rules, RuleAdapted(IsLikelyTableFunctionStack)); - if (!isAnyFunction && !isTableFunction) { - return Nothing(); - } + TLocalSyntaxContext::TPragma pragma; - TLocalSyntaxContext::TFunction function; - - if (TMaybe<TRichParsedToken> begin; - (begin = context.MatchCursorPrefix({"ID_PLAIN", "NAMESPACE"})) || - (begin = context.MatchCursorPrefix({"ID_PLAIN", "NAMESPACE", ""}))) { - function.Namespace = begin->Base->Content; - } + if (TMaybe<TRichParsedToken> begin; + (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT"})) || + (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT", ""}))) { + pragma.Namespace = begin->Base->Content; + } + return pragma; + } - function.ReturnType = ENodeKind::Any; - if (isTableFunction) { - function.ReturnType = ENodeKind::Table; - } + bool TypeMatch(const TC3Candidates& candidates) const { + return AnyOf(candidates.Rules, RuleAdapted(IsLikelyTypeStack)); + } - return function; + TMaybe<TLocalSyntaxContext::TFunction> FunctionMatch( + const TCursorTokenContext& context, const TC3Candidates& candidates) const { + const bool isAnyFunction = AnyOf(candidates.Rules, RuleAdapted(IsLikelyFunctionStack)); + const bool isTableFunction = AnyOf(candidates.Rules, RuleAdapted(IsLikelyTableFunctionStack)); + if (!isAnyFunction && !isTableFunction) { + return Nothing(); } - TMaybe<TLocalSyntaxContext::THint> HintMatch(const TC3Candidates& candidates) const { - // TODO(YQL-19747): detect local contexts with a single iteration through the candidates.Rules - auto rule = FindIf(candidates.Rules, RuleAdapted(IsLikelyHintStack)); - if (rule == std::end(candidates.Rules)) { - return Nothing(); - } - - auto stmt = StatementKindOf(rule->ParserCallStack); - if (stmt.Empty()) { - return Nothing(); - } + TLocalSyntaxContext::TFunction function; - return TLocalSyntaxContext::THint{ - .StatementKind = *stmt, - }; + if (TMaybe<TRichParsedToken> begin; + (begin = context.MatchCursorPrefix({"ID_PLAIN", "NAMESPACE"})) || + (begin = context.MatchCursorPrefix({"ID_PLAIN", "NAMESPACE", ""}))) { + function.Namespace = begin->Base->Content; } - TMaybe<TLocalSyntaxContext::TObject> ObjectMatch( - const TCursorTokenContext& context, const TC3Candidates& candidates) const { - TLocalSyntaxContext::TObject object; + function.ReturnType = ENodeKind::Any; + if (isTableFunction) { + function.ReturnType = ENodeKind::Table; + } - if (AnyOf(candidates.Rules, RuleAdapted(IsLikelyObjectRefStack))) { - object.Kinds.emplace(EObjectKind::Folder); - object.Kinds.emplace(EObjectKind::Unknown); - } + return function; + } - if (AnyOf(candidates.Rules, RuleAdapted(IsLikelyExistingTableStack))) { - object.Kinds.emplace(EObjectKind::Folder); - object.Kinds.emplace(EObjectKind::Table); - } + TMaybe<TLocalSyntaxContext::THint> HintMatch(const TC3Candidates& candidates) const { + // TODO(YQL-19747): detect local contexts with a single iteration through the candidates.Rules + auto rule = FindIf(candidates.Rules, RuleAdapted(IsLikelyHintStack)); + if (rule == std::end(candidates.Rules)) { + return Nothing(); + } - if (object.Kinds.empty() && !AnyOf(candidates.Rules, RuleAdapted(IsLikelyTableArgStack))) { - return Nothing(); - } + auto stmt = StatementKindOf(rule->ParserCallStack); + if (stmt.Empty()) { + return Nothing(); + } - if (TMaybe<TRichParsedToken> begin; - (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT"})) || - (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT", ""}))) { - object.Cluster = begin->Base->Content; - } + return TLocalSyntaxContext::THint{ + .StatementKind = *stmt, + }; + } - if (TMaybe<TRichParsedToken> begin; - (begin = context.MatchCursorPrefix({"ID_PLAIN", "COLON", "ID_PLAIN", "DOT"})) || - (begin = context.MatchCursorPrefix({"ID_PLAIN", "COLON", "ID_PLAIN", "DOT", ""}))) { - object.Provider = begin->Base->Content; - } + TMaybe<TLocalSyntaxContext::TObject> ObjectMatch( + const TCursorTokenContext& context, const TC3Candidates& candidates) const { + TLocalSyntaxContext::TObject object; - if (auto path = ObjectPath(context)) { - object.Path = *path; - } + if (AnyOf(candidates.Rules, RuleAdapted(IsLikelyObjectRefStack))) { + object.Kinds.emplace(EObjectKind::Folder); + object.Kinds.emplace(EObjectKind::Unknown); + } - return object; + if (AnyOf(candidates.Rules, RuleAdapted(IsLikelyExistingTableStack))) { + object.Kinds.emplace(EObjectKind::Folder); + object.Kinds.emplace(EObjectKind::Table); } - TMaybe<TString> ObjectPath(const TCursorTokenContext& context) const { - if (auto enclosing = context.Enclosing()) { - TString path = enclosing->Base->Content; - if (enclosing->Base->Name == "ID_QUOTED") { - path = Unquoted(std::move(path)); - enclosing->Position += 1; - } - path.resize(context.Cursor.Position - enclosing->Position); - return path; - } + if (object.Kinds.empty() && !AnyOf(candidates.Rules, RuleAdapted(IsLikelyTableArgStack))) { return Nothing(); } - TMaybe<TLocalSyntaxContext::TCluster> ClusterMatch( - const TCursorTokenContext& context, const TC3Candidates& candidates) const { - if (!AnyOf(candidates.Rules, RuleAdapted(IsLikelyClusterStack))) { - return Nothing(); - } + if (TMaybe<TRichParsedToken> begin; + (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT"})) || + (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT", ""}))) { + object.Cluster = begin->Base->Content; + } - TLocalSyntaxContext::TCluster cluster; - if (TMaybe<TRichParsedToken> begin; - (begin = context.MatchCursorPrefix({"ID_PLAIN", "COLON"})) || - (begin = context.MatchCursorPrefix({"ID_PLAIN", "COLON", ""}))) { - cluster.Provider = begin->Base->Content; - } - return cluster; + if (TMaybe<TRichParsedToken> begin; + (begin = context.MatchCursorPrefix({"ID_PLAIN", "COLON", "ID_PLAIN", "DOT"})) || + (begin = context.MatchCursorPrefix({"ID_PLAIN", "COLON", "ID_PLAIN", "DOT", ""}))) { + object.Provider = begin->Base->Content; } - TMaybe<TLocalSyntaxContext::TColumn> ColumnMatch( - const TCursorTokenContext& context, const TC3Candidates& candidates) const { - if (!AnyOf(candidates.Rules, RuleAdapted(IsLikelyColumnStack))) { - return Nothing(); - } + if (auto path = ObjectPath(context)) { + object.Path = *path; + } + + return object; + } - TLocalSyntaxContext::TColumn column; - if (TMaybe<TRichParsedToken> begin; - (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT"})) || - (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT", ""}))) { - column.Table = begin->Base->Content; - } else if (TMaybe<TRichParsedToken> begin; - (begin = context.MatchCursorPrefix({"ID_QUOTED", "DOT"})) || - (begin = context.MatchCursorPrefix({"ID_QUOTED", "DOT", ""}))) { - column.Table = Unquoted(begin->Base->Content); + TMaybe<TString> ObjectPath(const TCursorTokenContext& context) const { + if (auto enclosing = context.Enclosing()) { + TString path = enclosing->Base->Content; + if (enclosing->Base->Name == "ID_QUOTED") { + path = Unquoted(std::move(path)); + enclosing->Position += 1; } - return column; + path.resize(context.Cursor.Position - enclosing->Position); + return path; } + return Nothing(); + } - bool BindingMatch(const TC3Candidates& candidates) const { - return AnyOf(candidates.Rules, RuleAdapted(IsLikelyBindingStack)); + TMaybe<TLocalSyntaxContext::TCluster> ClusterMatch( + const TCursorTokenContext& context, const TC3Candidates& candidates) const { + if (!AnyOf(candidates.Rules, RuleAdapted(IsLikelyClusterStack))) { + return Nothing(); } - TLocalSyntaxContext::TQuotation Quotation(TCompletionInput input, const TCursorTokenContext& context) const { - TLocalSyntaxContext::TQuotation isQuoted; - if (auto enclosing = context.Enclosing(); - enclosing.Defined() && enclosing->Base->Name == "ID_QUOTED") { - isQuoted.AtLhs = true; - isQuoted.AtRhs = enclosing->End() <= input.Text.size(); - } - return isQuoted; - } - - TEditRange EditRange(const TCursorTokenContext& context, ERangeKind kind) const { - if (TMaybe<TRichParsedToken> begin; - kind == ERangeKind::Replace && - ((begin = context.MatchCursorPrefix({"DOLLAR"})) || - (begin = context.MatchCursorPrefix({"DOLLAR", ""})))) { - return { - .Begin = begin->Position, - .Length = context.Cursor.Position - begin->Position, - }; - } + TLocalSyntaxContext::TCluster cluster; + if (TMaybe<TRichParsedToken> begin; + (begin = context.MatchCursorPrefix({"ID_PLAIN", "COLON"})) || + (begin = context.MatchCursorPrefix({"ID_PLAIN", "COLON", ""}))) { + cluster.Provider = begin->Base->Content; + } + return cluster; + } - if (auto enclosing = context.Enclosing()) { - return EditRange(*enclosing, context.Cursor); - } + TMaybe<TLocalSyntaxContext::TColumn> ColumnMatch( + const TCursorTokenContext& context, const TC3Candidates& candidates) const { + if (!AnyOf(candidates.Rules, RuleAdapted(IsLikelyColumnStack))) { + return Nothing(); + } - return { - .Begin = context.Cursor.Position, - .Length = 0, - }; + TLocalSyntaxContext::TColumn column; + if (TMaybe<TRichParsedToken> begin; + (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT"})) || + (begin = context.MatchCursorPrefix({"ID_PLAIN", "DOT", ""}))) { + column.Table = begin->Base->Content; + } else if (TMaybe<TRichParsedToken> begin; + (begin = context.MatchCursorPrefix({"ID_QUOTED", "DOT"})) || + (begin = context.MatchCursorPrefix({"ID_QUOTED", "DOT", ""}))) { + column.Table = Unquoted(begin->Base->Content); } + return column; + } - TEditRange EditRange(const TRichParsedToken& token, const TCursor& cursor) const { - size_t begin = token.Position; - if (token.Base->Name == "NOT_EQUALS2" || - token.Base->Name == "ID_QUOTED") { - begin += 1; - } + bool BindingMatch(const TC3Candidates& candidates) const { + return AnyOf(candidates.Rules, RuleAdapted(IsLikelyBindingStack)); + } + TLocalSyntaxContext::TQuotation Quotation(TCompletionInput input, const TCursorTokenContext& context) const { + TLocalSyntaxContext::TQuotation isQuoted; + if (auto enclosing = context.Enclosing(); + enclosing.Defined() && enclosing->Base->Name == "ID_QUOTED") { + isQuoted.AtLhs = true; + isQuoted.AtRhs = enclosing->End() <= input.Text.size(); + } + return isQuoted; + } + + TEditRange EditRange(const TCursorTokenContext& context, ERangeKind kind) const { + if (TMaybe<TRichParsedToken> begin; + kind == ERangeKind::Replace && + ((begin = context.MatchCursorPrefix({"DOLLAR"})) || + (begin = context.MatchCursorPrefix({"DOLLAR", ""})))) { return { - .Begin = begin, - .Length = cursor.Position - begin, + .Begin = begin->Position, + .Length = context.Cursor.Position - begin->Position, }; } - const ISqlGrammar* Grammar_; - NSQLTranslation::ILexer::TPtr Lexer_; - TC3Engine<G> C3_; - }; - - class TLocalSyntaxAnalysis: public ILocalSyntaxAnalysis { - public: - TLocalSyntaxAnalysis( - TLexerSupplier lexer, - const THashSet<TString>& ignoredRules, - const THashMap<TString, THashSet<TString>>& disabledPreviousByToken, - const THashMap<TString, THashSet<TString>>& forcedPreviousByToken) - : DefaultEngine_(lexer, ignoredRules, disabledPreviousByToken, forcedPreviousByToken) - , AnsiEngine_(lexer, ignoredRules, disabledPreviousByToken, forcedPreviousByToken) - { + if (auto enclosing = context.Enclosing()) { + return EditRange(*enclosing, context.Cursor); } - TLocalSyntaxContext Analyze(TCompletionInput input) override { - auto isAnsiLexer = IsAnsiQuery(TString(input.Text)); - auto& engine = GetSpecializedEngine(isAnsiLexer); - return engine.Analyze(std::move(input)); - } + return { + .Begin = context.Cursor.Position, + .Length = 0, + }; + } - private: - ILocalSyntaxAnalysis& GetSpecializedEngine(bool isAnsiLexer) { - if (isAnsiLexer) { - return AnsiEngine_; - } - return DefaultEngine_; + TEditRange EditRange(const TRichParsedToken& token, const TCursor& cursor) const { + size_t begin = token.Position; + if (token.Base->Name == "NOT_EQUALS2" || + token.Base->Name == "ID_QUOTED") { + begin += 1; } - TSpecializedLocalSyntaxAnalysis</* IsAnsiLexer = */ false> DefaultEngine_; - TSpecializedLocalSyntaxAnalysis</* IsAnsiLexer = */ true> AnsiEngine_; - }; + return { + .Begin = begin, + .Length = cursor.Position - begin, + }; + } - ILocalSyntaxAnalysis::TPtr MakeLocalSyntaxAnalysis( + const ISqlGrammar* Grammar_; + NSQLTranslation::ILexer::TPtr Lexer_; + TC3Engine<G> C3_; +}; + +class TLocalSyntaxAnalysis: public ILocalSyntaxAnalysis { +public: + TLocalSyntaxAnalysis( TLexerSupplier lexer, const THashSet<TString>& ignoredRules, const THashMap<TString, THashSet<TString>>& disabledPreviousByToken, - const THashMap<TString, THashSet<TString>>& forcedPreviousByToken) { - return MakeHolder<TLocalSyntaxAnalysis>(lexer, ignoredRules, disabledPreviousByToken, forcedPreviousByToken); + const THashMap<TString, THashSet<TString>>& forcedPreviousByToken) + : DefaultEngine_(lexer, ignoredRules, disabledPreviousByToken, forcedPreviousByToken) + , AnsiEngine_(lexer, ignoredRules, disabledPreviousByToken, forcedPreviousByToken) + { + } + + TLocalSyntaxContext Analyze(TCompletionInput input) override { + auto isAnsiLexer = IsAnsiQuery(TString(input.Text)); + auto& engine = GetSpecializedEngine(isAnsiLexer); + return engine.Analyze(std::move(input)); } +private: + ILocalSyntaxAnalysis& GetSpecializedEngine(bool isAnsiLexer) { + if (isAnsiLexer) { + return AnsiEngine_; + } + return DefaultEngine_; + } + + TSpecializedLocalSyntaxAnalysis</* IsAnsiLexer = */ false> DefaultEngine_; + TSpecializedLocalSyntaxAnalysis</* IsAnsiLexer = */ true> AnsiEngine_; +}; + +ILocalSyntaxAnalysis::TPtr MakeLocalSyntaxAnalysis( + TLexerSupplier lexer, + const THashSet<TString>& ignoredRules, + const THashMap<TString, THashSet<TString>>& disabledPreviousByToken, + const THashMap<TString, THashSet<TString>>& forcedPreviousByToken) { + return MakeHolder<TLocalSyntaxAnalysis>(lexer, ignoredRules, disabledPreviousByToken, forcedPreviousByToken); +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/local/local.h b/yql/essentials/sql/v1/complete/analysis/local/local.h index e3f13a88a50..606020ebc24 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/local.h +++ b/yql/essentials/sql/v1/complete/analysis/local/local.h @@ -12,87 +12,87 @@ namespace NSQLComplete { - struct TEditRange { - size_t Begin = 0; - size_t Length = 0; +struct TEditRange { + size_t Begin = 0; + size_t Length = 0; +}; + +struct TLocalSyntaxContext { + using TKeywords = THashMap<TString, TVector<TString>>; + + struct TPragma { + TString Namespace; + }; + + struct TFunction { + TString Namespace; + ENodeKind ReturnType = ENodeKind::Any; + }; + + struct THint { + EStatementKind StatementKind; + }; + + struct TCluster { + TString Provider; + }; + + struct TObject { + TString Provider; + TString Cluster; + TString Path; + THashSet<EObjectKind> Kinds; + + bool HasCluster() const { + return !Cluster.empty(); + } + + bool IsDeferred() const { + return Kinds.empty(); + } }; - struct TLocalSyntaxContext { - using TKeywords = THashMap<TString, TVector<TString>>; - - struct TPragma { - TString Namespace; - }; - - struct TFunction { - TString Namespace; - ENodeKind ReturnType = ENodeKind::Any; - }; - - struct THint { - EStatementKind StatementKind; - }; - - struct TCluster { - TString Provider; - }; - - struct TObject { - TString Provider; - TString Cluster; - TString Path; - THashSet<EObjectKind> Kinds; - - bool HasCluster() const { - return !Cluster.empty(); - } - - bool IsDeferred() const { - return Kinds.empty(); - } - }; - - struct TColumn { - TString Table; - }; - - struct TQuotation { - bool AtLhs = false; - bool AtRhs = false; - - explicit operator bool() const { - return AtLhs || AtRhs; - } - }; - - TKeywords Keywords; - TMaybe<TPragma> Pragma; - bool Type = false; - TMaybe<TFunction> Function; - TMaybe<THint> Hint; - TMaybe<TObject> Object; - TMaybe<TCluster> Cluster; - TMaybe<TColumn> Column; - bool Binding = false; - - TQuotation IsQuoted; - TEditRange ReplaceRange; - TEditRange FilterRange; + struct TColumn { + TString Table; }; - // TODO(YQL-19747): Make it thread-safe to make ISqlCompletionEngine thread-safe. - class ILocalSyntaxAnalysis { - public: - using TPtr = THolder<ILocalSyntaxAnalysis>; + struct TQuotation { + bool AtLhs = false; + bool AtRhs = false; - virtual ~ILocalSyntaxAnalysis() = default; - virtual TLocalSyntaxContext Analyze(TCompletionInput input) = 0; + explicit operator bool() const { + return AtLhs || AtRhs; + } }; - ILocalSyntaxAnalysis::TPtr MakeLocalSyntaxAnalysis( - TLexerSupplier lexer, - const THashSet<TString>& ignoredRules, - const THashMap<TString, THashSet<TString>>& disabledPreviousByToken, - const THashMap<TString, THashSet<TString>>& forcedPreviousByToken); + TKeywords Keywords; + TMaybe<TPragma> Pragma; + bool Type = false; + TMaybe<TFunction> Function; + TMaybe<THint> Hint; + TMaybe<TObject> Object; + TMaybe<TCluster> Cluster; + TMaybe<TColumn> Column; + bool Binding = false; + + TQuotation IsQuoted; + TEditRange ReplaceRange; + TEditRange FilterRange; +}; + +// TODO(YQL-19747): Make it thread-safe to make ISqlCompletionEngine thread-safe. +class ILocalSyntaxAnalysis { +public: + using TPtr = THolder<ILocalSyntaxAnalysis>; + + virtual ~ILocalSyntaxAnalysis() = default; + virtual TLocalSyntaxContext Analyze(TCompletionInput input) = 0; +}; + +ILocalSyntaxAnalysis::TPtr MakeLocalSyntaxAnalysis( + TLexerSupplier lexer, + const THashSet<TString>& ignoredRules, + const THashMap<TString, THashSet<TString>>& disabledPreviousByToken, + const THashMap<TString, THashSet<TString>>& forcedPreviousByToken); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/local/parser_call_stack.cpp b/yql/essentials/sql/v1/complete/analysis/local/parser_call_stack.cpp index 9f0501f1968..f8dba3a3113 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/parser_call_stack.cpp +++ b/yql/essentials/sql/v1/complete/analysis/local/parser_call_stack.cpp @@ -13,151 +13,151 @@ namespace NSQLComplete { - const TVector<TRuleId> PreferredRules = { - RULE(Keyword), - RULE(Keyword_expr_uncompat), - RULE(Keyword_table_uncompat), - RULE(Keyword_select_uncompat), - RULE(Keyword_alter_uncompat), - RULE(Keyword_in_uncompat), - RULE(Keyword_window_uncompat), - RULE(Keyword_hint_uncompat), - RULE(Keyword_as_compat), - RULE(Keyword_compat), - RULE(Type_id), - - RULE(An_id_or_type), - RULE(An_id), - RULE(Id_expr), - RULE(Id_or_type), - RULE(Id_hint), - RULE(Opt_id_prefix_or_type), - RULE(Type_name_simple), - RULE(Type_name_composite), - RULE(Type_name_decimal), - RULE(Value_constructor), - }; - - TVector<std::string> Symbolized(const TParserCallStack& stack) { - const ISqlGrammar& grammar = GetSqlGrammar(); - - TVector<std::string> symbolized; - symbolized.reserve(stack.size()); - for (const TRuleId& rule : stack) { - symbolized.emplace_back(grammar.SymbolizedRule(rule)); +const TVector<TRuleId> PreferredRules = { + RULE(Keyword), + RULE(Keyword_expr_uncompat), + RULE(Keyword_table_uncompat), + RULE(Keyword_select_uncompat), + RULE(Keyword_alter_uncompat), + RULE(Keyword_in_uncompat), + RULE(Keyword_window_uncompat), + RULE(Keyword_hint_uncompat), + RULE(Keyword_as_compat), + RULE(Keyword_compat), + RULE(Type_id), + + RULE(An_id_or_type), + RULE(An_id), + RULE(Id_expr), + RULE(Id_or_type), + RULE(Id_hint), + RULE(Opt_id_prefix_or_type), + RULE(Type_name_simple), + RULE(Type_name_composite), + RULE(Type_name_decimal), + RULE(Value_constructor), +}; + +TVector<std::string> Symbolized(const TParserCallStack& stack) { + const ISqlGrammar& grammar = GetSqlGrammar(); + + TVector<std::string> symbolized; + symbolized.reserve(stack.size()); + for (const TRuleId& rule : stack) { + symbolized.emplace_back(grammar.SymbolizedRule(rule)); + } + return symbolized; +} + +bool EndsWith(const TParserCallStack& suffix, const TParserCallStack& stack) { + if (stack.size() < suffix.size()) { + return false; + } + const size_t prefixSize = stack.size() - suffix.size(); + return Equal(std::begin(stack) + prefixSize, std::end(stack), std::begin(suffix)); +} + +bool Contains(const TParserCallStack& sequence, const TParserCallStack& stack) { + return !std::ranges::search(stack, sequence).empty(); +} + +bool ContainsRule(TRuleId rule, const TParserCallStack& stack) { + return Find(stack, rule) != std::end(stack); +} + +bool IsLikelyPragmaStack(const TParserCallStack& stack) { + return EndsWith({RULE(Pragma_stmt), RULE(Opt_id_prefix_or_type)}, stack) || + EndsWith({RULE(Pragma_stmt), RULE(An_id)}, stack); +} + +bool IsLikelyTypeStack(const TParserCallStack& stack) { + return EndsWith({RULE(Type_name_simple)}, stack) || + EndsWith({RULE(Type_name_composite)}, stack) || + EndsWith({RULE(Type_name_decimal)}, stack) || + (Contains({RULE(Invoke_expr), + RULE(Named_expr_list), + RULE(Named_expr), + RULE(Expr)}, stack) && + (EndsWith({RULE(Atom_expr), + RULE(An_id_or_type)}, stack) || + EndsWith({RULE(Atom_expr), + RULE(Bind_parameter), + RULE(An_id_or_type)}, stack))); +} + +bool IsLikelyFunctionStack(const TParserCallStack& stack) { + return EndsWith({RULE(Unary_casual_subexpr), RULE(Id_expr)}, stack) || + EndsWith({RULE(Unary_casual_subexpr), + RULE(Atom_expr), + RULE(An_id_or_type)}, stack) || + EndsWith({RULE(Unary_casual_subexpr), + RULE(Atom_expr), + RULE(Bind_parameter), + RULE(An_id_or_type)}, stack) || + EndsWith({RULE(Atom_expr), RULE(Id_or_type)}, stack) || + EndsWith({RULE(Value_constructor)}, stack); +} + +bool IsLikelyTableFunctionStack(const TParserCallStack& stack) { + return EndsWith({RULE(Table_ref), RULE(An_id_expr), RULE(Id_expr)}, stack); +} + +bool IsLikelyHintStack(const TParserCallStack& stack) { + return ContainsRule(RULE(Id_hint), stack) || + Contains({RULE(External_call_param), RULE(An_id)}, stack); +} + +bool IsLikelyObjectRefStack(const TParserCallStack& stack) { + return Contains({RULE(Object_ref)}, stack); +} + +bool IsLikelyExistingTableStack(const TParserCallStack& stack) { + return !Contains({RULE(Create_table_stmt), + RULE(Simple_table_ref)}, stack) && + (Contains({RULE(Simple_table_ref), + RULE(Simple_table_ref_core), + RULE(Object_ref)}, stack) || + Contains({RULE(Single_source), + RULE(Table_ref), + RULE(Table_key), + RULE(Id_table_or_type)}, stack)); +} + +bool IsLikelyTableArgStack(const TParserCallStack& stack) { + return Contains({RULE(Table_arg)}, stack); +} + +bool IsLikelyClusterStack(const TParserCallStack& stack) { + return Contains({RULE(Cluster_expr)}, stack); +} + +bool IsLikelyColumnStack(const TParserCallStack& stack) { + return Contains({RULE(Select_core)}, stack) && + (Contains({RULE(Result_column)}, stack) || + Contains({RULE(Expr)}, stack) || + Contains({RULE(Sort_specification)}, stack)); +} + +bool IsLikelyBindingStack(const TParserCallStack& stack) { + return EndsWith({RULE(Bind_parameter), RULE(An_id_or_type)}, stack); +} + +TMaybe<EStatementKind> StatementKindOf(const TParserCallStack& stack) { + for (TRuleId rule : std::ranges::views::reverse(stack)) { + if (rule == RULE(Process_core) || rule == RULE(Reduce_core) || rule == RULE(Select_core)) { + return EStatementKind::Select; } - return symbolized; - } - - bool EndsWith(const TParserCallStack& suffix, const TParserCallStack& stack) { - if (stack.size() < suffix.size()) { - return false; - } - const size_t prefixSize = stack.size() - suffix.size(); - return Equal(std::begin(stack) + prefixSize, std::end(stack), std::begin(suffix)); - } - - bool Contains(const TParserCallStack& sequence, const TParserCallStack& stack) { - return !std::ranges::search(stack, sequence).empty(); - } - - bool ContainsRule(TRuleId rule, const TParserCallStack& stack) { - return Find(stack, rule) != std::end(stack); - } - - bool IsLikelyPragmaStack(const TParserCallStack& stack) { - return EndsWith({RULE(Pragma_stmt), RULE(Opt_id_prefix_or_type)}, stack) || - EndsWith({RULE(Pragma_stmt), RULE(An_id)}, stack); - } - - bool IsLikelyTypeStack(const TParserCallStack& stack) { - return EndsWith({RULE(Type_name_simple)}, stack) || - EndsWith({RULE(Type_name_composite)}, stack) || - EndsWith({RULE(Type_name_decimal)}, stack) || - (Contains({RULE(Invoke_expr), - RULE(Named_expr_list), - RULE(Named_expr), - RULE(Expr)}, stack) && - (EndsWith({RULE(Atom_expr), - RULE(An_id_or_type)}, stack) || - EndsWith({RULE(Atom_expr), - RULE(Bind_parameter), - RULE(An_id_or_type)}, stack))); - } - - bool IsLikelyFunctionStack(const TParserCallStack& stack) { - return EndsWith({RULE(Unary_casual_subexpr), RULE(Id_expr)}, stack) || - EndsWith({RULE(Unary_casual_subexpr), - RULE(Atom_expr), - RULE(An_id_or_type)}, stack) || - EndsWith({RULE(Unary_casual_subexpr), - RULE(Atom_expr), - RULE(Bind_parameter), - RULE(An_id_or_type)}, stack) || - EndsWith({RULE(Atom_expr), RULE(Id_or_type)}, stack) || - EndsWith({RULE(Value_constructor)}, stack); - } - - bool IsLikelyTableFunctionStack(const TParserCallStack& stack) { - return EndsWith({RULE(Table_ref), RULE(An_id_expr), RULE(Id_expr)}, stack); - } - - bool IsLikelyHintStack(const TParserCallStack& stack) { - return ContainsRule(RULE(Id_hint), stack) || - Contains({RULE(External_call_param), RULE(An_id)}, stack); - } - - bool IsLikelyObjectRefStack(const TParserCallStack& stack) { - return Contains({RULE(Object_ref)}, stack); - } - - bool IsLikelyExistingTableStack(const TParserCallStack& stack) { - return !Contains({RULE(Create_table_stmt), - RULE(Simple_table_ref)}, stack) && - (Contains({RULE(Simple_table_ref), - RULE(Simple_table_ref_core), - RULE(Object_ref)}, stack) || - Contains({RULE(Single_source), - RULE(Table_ref), - RULE(Table_key), - RULE(Id_table_or_type)}, stack)); - } - - bool IsLikelyTableArgStack(const TParserCallStack& stack) { - return Contains({RULE(Table_arg)}, stack); - } - - bool IsLikelyClusterStack(const TParserCallStack& stack) { - return Contains({RULE(Cluster_expr)}, stack); - } - - bool IsLikelyColumnStack(const TParserCallStack& stack) { - return Contains({RULE(Select_core)}, stack) && - (Contains({RULE(Result_column)}, stack) || - Contains({RULE(Expr)}, stack) || - Contains({RULE(Sort_specification)}, stack)); - } - - bool IsLikelyBindingStack(const TParserCallStack& stack) { - return EndsWith({RULE(Bind_parameter), RULE(An_id_or_type)}, stack); - } - - TMaybe<EStatementKind> StatementKindOf(const TParserCallStack& stack) { - for (TRuleId rule : std::ranges::views::reverse(stack)) { - if (rule == RULE(Process_core) || rule == RULE(Reduce_core) || rule == RULE(Select_core)) { - return EStatementKind::Select; - } - if (rule == RULE(Into_table_stmt)) { - return EStatementKind::Insert; - } + if (rule == RULE(Into_table_stmt)) { + return EStatementKind::Insert; } - return Nothing(); } + return Nothing(); +} - std::unordered_set<TRuleId> GetC3PreferredRules() { - std::unordered_set<TRuleId> preferredRules; - preferredRules.insert(std::begin(PreferredRules), std::end(PreferredRules)); - return preferredRules; - } +std::unordered_set<TRuleId> GetC3PreferredRules() { + std::unordered_set<TRuleId> preferredRules; + preferredRules.insert(std::begin(PreferredRules), std::end(PreferredRules)); + return preferredRules; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/local/parser_call_stack.h b/yql/essentials/sql/v1/complete/analysis/local/parser_call_stack.h index 66c87ebf17e..ab1014fc093 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/parser_call_stack.h +++ b/yql/essentials/sql/v1/complete/analysis/local/parser_call_stack.h @@ -7,30 +7,30 @@ namespace NSQLComplete { - bool IsLikelyPragmaStack(const TParserCallStack& stack); +bool IsLikelyPragmaStack(const TParserCallStack& stack); - bool IsLikelyTypeStack(const TParserCallStack& stack); +bool IsLikelyTypeStack(const TParserCallStack& stack); - bool IsLikelyFunctionStack(const TParserCallStack& stack); +bool IsLikelyFunctionStack(const TParserCallStack& stack); - bool IsLikelyTableFunctionStack(const TParserCallStack& stack); +bool IsLikelyTableFunctionStack(const TParserCallStack& stack); - bool IsLikelyHintStack(const TParserCallStack& stack); +bool IsLikelyHintStack(const TParserCallStack& stack); - bool IsLikelyObjectRefStack(const TParserCallStack& stack); +bool IsLikelyObjectRefStack(const TParserCallStack& stack); - bool IsLikelyExistingTableStack(const TParserCallStack& stack); +bool IsLikelyExistingTableStack(const TParserCallStack& stack); - bool IsLikelyTableArgStack(const TParserCallStack& stack); +bool IsLikelyTableArgStack(const TParserCallStack& stack); - bool IsLikelyClusterStack(const TParserCallStack& stack); +bool IsLikelyClusterStack(const TParserCallStack& stack); - bool IsLikelyColumnStack(const TParserCallStack& stack); +bool IsLikelyColumnStack(const TParserCallStack& stack); - bool IsLikelyBindingStack(const TParserCallStack& stack); +bool IsLikelyBindingStack(const TParserCallStack& stack); - TMaybe<EStatementKind> StatementKindOf(const TParserCallStack& stack); +TMaybe<EStatementKind> StatementKindOf(const TParserCallStack& stack); - std::unordered_set<TRuleId> GetC3PreferredRules(); +std::unordered_set<TRuleId> GetC3PreferredRules(); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/yql/cluster.cpp b/yql/essentials/sql/v1/complete/analysis/yql/cluster.cpp index 939cb7b25a7..49dad50c63d 100644 --- a/yql/essentials/sql/v1/complete/analysis/yql/cluster.cpp +++ b/yql/essentials/sql/v1/complete/analysis/yql/cluster.cpp @@ -4,26 +4,26 @@ namespace NSQLComplete { - TMaybe<TString> ToCluster(const NYql::TExprNode& node) { - if (!node.IsCallable("DataSource") && !node.IsCallable("DataSink")) { - return Nothing(); - } - if (node.ChildrenSize() == 2 && node.Child(1)->IsAtom()) { - return TString(node.Child(1)->Content()); - } +TMaybe<TString> ToCluster(const NYql::TExprNode& node) { + if (!node.IsCallable("DataSource") && !node.IsCallable("DataSink")) { return Nothing(); } + if (node.ChildrenSize() == 2 && node.Child(1)->IsAtom()) { + return TString(node.Child(1)->Content()); + } + return Nothing(); +} - THashSet<TString> CollectClusters(const NYql::TExprNode& root) { - THashSet<TString> clusters; - NYql::VisitExpr(root, [&](const NYql::TExprNode& node) -> bool { - if (TMaybe<TString> cluster = ToCluster(node)) { - clusters.emplace(std::move(*cluster)); - return true; - } +THashSet<TString> CollectClusters(const NYql::TExprNode& root) { + THashSet<TString> clusters; + NYql::VisitExpr(root, [&](const NYql::TExprNode& node) -> bool { + if (TMaybe<TString> cluster = ToCluster(node)) { + clusters.emplace(std::move(*cluster)); return true; - }); - return clusters; - } + } + return true; + }); + return clusters; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/yql/cluster.h b/yql/essentials/sql/v1/complete/analysis/yql/cluster.h index 07f07bf595e..50c4370e181 100644 --- a/yql/essentials/sql/v1/complete/analysis/yql/cluster.h +++ b/yql/essentials/sql/v1/complete/analysis/yql/cluster.h @@ -8,8 +8,8 @@ namespace NSQLComplete { - TMaybe<TString> ToCluster(const NYql::TExprNode& node); +TMaybe<TString> ToCluster(const NYql::TExprNode& node); - THashSet<TString> CollectClusters(const NYql::TExprNode& root); +THashSet<TString> CollectClusters(const NYql::TExprNode& root); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/yql/table.cpp b/yql/essentials/sql/v1/complete/analysis/yql/table.cpp index 351d09a2e48..db3e3c3112d 100644 --- a/yql/essentials/sql/v1/complete/analysis/yql/table.cpp +++ b/yql/essentials/sql/v1/complete/analysis/yql/table.cpp @@ -6,65 +6,65 @@ namespace NSQLComplete { - TMaybe<TString> ToTablePath(const NYql::TExprNode& node) { - if (!node.IsCallable("Key") || node.ChildrenSize() < 1) { - return Nothing(); - } - - const NYql::TExprNode* table = node.Child(0); - if (!table->IsList() || table->ChildrenSize() < 2) { - return Nothing(); - } +TMaybe<TString> ToTablePath(const NYql::TExprNode& node) { + if (!node.IsCallable("Key") || node.ChildrenSize() < 1) { + return Nothing(); + } - TStringBuf kind = table->Child(0)->Content(); - if (kind != "table" && kind != "tablescheme") { - return Nothing(); - } + const NYql::TExprNode* table = node.Child(0); + if (!table->IsList() || table->ChildrenSize() < 2) { + return Nothing(); + } - const NYql::TExprNode* string = table->Child(1); - if (!string->IsCallable("String") || string->ChildrenSize() < 1) { - return Nothing(); - } + TStringBuf kind = table->Child(0)->Content(); + if (kind != "table" && kind != "tablescheme") { + return Nothing(); + } - return TString(string->Child(0)->Content()); + const NYql::TExprNode* string = table->Child(1); + if (!string->IsCallable("String") || string->ChildrenSize() < 1) { + return Nothing(); } - THashSet<TString> ToTablePaths(const NYql::TExprNode& node) { - if (node.IsCallable("MrTableConcat")) { - THashSet<TString> paths; - for (const auto& child : node.Children()) { - if (auto path = ToTablePath(*child)) { - paths.emplace(std::move(*path)); - } - } - return paths; - } + return TString(string->Child(0)->Content()); +} - if (auto path = ToTablePath(node)) { - return {std::move(*path)}; +THashSet<TString> ToTablePaths(const NYql::TExprNode& node) { + if (node.IsCallable("MrTableConcat")) { + THashSet<TString> paths; + for (const auto& child : node.Children()) { + if (auto path = ToTablePath(*child)) { + paths.emplace(std::move(*path)); + } } - - return {}; + return paths; } - THashMap<TString, THashSet<TString>> CollectTablesByCluster(const NYql::TExprNode& node) { - THashMap<TString, THashSet<TString>> tablesByCluster; - NYql::VisitExpr(node, [&](const NYql::TExprNode& node) -> bool { - if (!node.IsCallable("Read!") && !node.IsCallable("Write!")) { - return true; - } - if (node.ChildrenSize() < 4) { - return true; - } + if (auto path = ToTablePath(node)) { + return {std::move(*path)}; + } - TString cluster = ToCluster(*node.Child(1)).GetOrElse(""); - for (TString table : ToTablePaths(*node.Child(2))) { - tablesByCluster[cluster].emplace(std::move(table)); - } + return {}; +} +THashMap<TString, THashSet<TString>> CollectTablesByCluster(const NYql::TExprNode& node) { + THashMap<TString, THashSet<TString>> tablesByCluster; + NYql::VisitExpr(node, [&](const NYql::TExprNode& node) -> bool { + if (!node.IsCallable("Read!") && !node.IsCallable("Write!")) { return true; - }); - return tablesByCluster; - } + } + if (node.ChildrenSize() < 4) { + return true; + } + + TString cluster = ToCluster(*node.Child(1)).GetOrElse(""); + for (TString table : ToTablePaths(*node.Child(2))) { + tablesByCluster[cluster].emplace(std::move(table)); + } + + return true; + }); + return tablesByCluster; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/yql/table.h b/yql/essentials/sql/v1/complete/analysis/yql/table.h index d9009026a42..3d15e38238f 100644 --- a/yql/essentials/sql/v1/complete/analysis/yql/table.h +++ b/yql/essentials/sql/v1/complete/analysis/yql/table.h @@ -9,8 +9,8 @@ namespace NSQLComplete { - TMaybe<TString> ToTablePath(const NYql::TExprNode& node); +TMaybe<TString> ToTablePath(const NYql::TExprNode& node); - THashMap<TString, THashSet<TString>> CollectTablesByCluster(const NYql::TExprNode& node); +THashMap<TString, THashSet<TString>> CollectTablesByCluster(const NYql::TExprNode& node); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/yql/yql.cpp b/yql/essentials/sql/v1/complete/analysis/yql/yql.cpp index 052d9a8840b..495e608afea 100644 --- a/yql/essentials/sql/v1/complete/analysis/yql/yql.cpp +++ b/yql/essentials/sql/v1/complete/analysis/yql/yql.cpp @@ -7,46 +7,46 @@ namespace NSQLComplete { - THashSet<TString> TYqlContext::Clusters() const { - auto keys = IterateKeys(TablesByCluster); - return {keys.begin(), keys.end()}; - } - - TMaybe<TYqlContext> IYqlAnalysis::Analyze(NYql::TAstNode& root, NYql::TIssues& issues) const { - NYql::TExprContext ctx; - NYql::TExprNode::TPtr expr; - if (!NYql::CompileExpr(root, expr, ctx, /* resolver = */ nullptr, /* urlListerManager = */ nullptr)) { - for (NYql::TIssue issue : ctx.IssueManager.GetIssues()) { - issues.AddIssue(std::move(issue)); - } - return Nothing(); +THashSet<TString> TYqlContext::Clusters() const { + auto keys = IterateKeys(TablesByCluster); + return {keys.begin(), keys.end()}; +} + +TMaybe<TYqlContext> IYqlAnalysis::Analyze(NYql::TAstNode& root, NYql::TIssues& issues) const { + NYql::TExprContext ctx; + NYql::TExprNode::TPtr expr; + if (!NYql::CompileExpr(root, expr, ctx, /* resolver = */ nullptr, /* urlListerManager = */ nullptr)) { + for (NYql::TIssue issue : ctx.IssueManager.GetIssues()) { + issues.AddIssue(std::move(issue)); } - return Analyze(expr, ctx); + return Nothing(); } + return Analyze(expr, ctx); +} - namespace { +namespace { - class TYqlAnalysis: public IYqlAnalysis { - public: - TYqlContext Analyze(NYql::TExprNode::TPtr root, NYql::TExprContext& ctx) const override { - Y_UNUSED(ctx); +class TYqlAnalysis: public IYqlAnalysis { +public: + TYqlContext Analyze(NYql::TExprNode::TPtr root, NYql::TExprContext& ctx) const override { + Y_UNUSED(ctx); - TYqlContext yqlCtx; + TYqlContext yqlCtx; - yqlCtx.TablesByCluster = CollectTablesByCluster(*root); + yqlCtx.TablesByCluster = CollectTablesByCluster(*root); - for (TString cluster : CollectClusters(*root)) { - Y_UNUSED(yqlCtx.TablesByCluster[std::move(cluster)]); - } + for (TString cluster : CollectClusters(*root)) { + Y_UNUSED(yqlCtx.TablesByCluster[std::move(cluster)]); + } - return yqlCtx; - } - }; + return yqlCtx; + } +}; - } // namespace +} // namespace - IYqlAnalysis::TPtr MakeYqlAnalysis() { - return new TYqlAnalysis(); - } +IYqlAnalysis::TPtr MakeYqlAnalysis() { + return new TYqlAnalysis(); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/yql/yql.h b/yql/essentials/sql/v1/complete/analysis/yql/yql.h index 6c97246885e..fd9cb0017cb 100644 --- a/yql/essentials/sql/v1/complete/analysis/yql/yql.h +++ b/yql/essentials/sql/v1/complete/analysis/yql/yql.h @@ -9,20 +9,20 @@ namespace NSQLComplete { - struct TYqlContext { - THashMap<TString, THashSet<TString>> TablesByCluster; +struct TYqlContext { + THashMap<TString, THashSet<TString>> TablesByCluster; - THashSet<TString> Clusters() const; - }; + THashSet<TString> Clusters() const; +}; - class IYqlAnalysis: public TThrRefBase { - public: - using TPtr = TIntrusivePtr<IYqlAnalysis>; +class IYqlAnalysis: public TThrRefBase { +public: + using TPtr = TIntrusivePtr<IYqlAnalysis>; - virtual TYqlContext Analyze(NYql::TExprNode::TPtr root, NYql::TExprContext& ctx) const = 0; - TMaybe<TYqlContext> Analyze(NYql::TAstNode& root, NYql::TIssues& issues) const; - }; + virtual TYqlContext Analyze(NYql::TExprNode::TPtr root, NYql::TExprContext& ctx) const = 0; + TMaybe<TYqlContext> Analyze(NYql::TAstNode& root, NYql::TIssues& issues) const; +}; - IYqlAnalysis::TPtr MakeYqlAnalysis(); +IYqlAnalysis::TPtr MakeYqlAnalysis(); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/yql/yql_ut.cpp b/yql/essentials/sql/v1/complete/analysis/yql/yql_ut.cpp index 233086d9ee4..7c9e1fa1a56 100644 --- a/yql/essentials/sql/v1/complete/analysis/yql/yql_ut.cpp +++ b/yql/essentials/sql/v1/complete/analysis/yql/yql_ut.cpp @@ -25,7 +25,7 @@ public: Settings_.SyntaxVersion = 1; Lexers_.Antlr4 = NSQLTranslationV1::MakeAntlr4LexerFactory(); - Parsers_.Antlr4 = NSQLTranslationV1::MakeAntlr4ParserFactory(/*isAmbiguityError=*/ true); + Parsers_.Antlr4 = NSQLTranslationV1::MakeAntlr4ParserFactory(/*isAmbiguityError=*/true); } NYql::TAstParseResult Parse(const TString& query) { @@ -52,8 +52,8 @@ TYqlContext Analyze(const TString& query) { Y_UNIT_TEST_SUITE(YqlAnalysisTests) { - Y_UNIT_TEST(NamesAreCollected) { - TString input = R"( +Y_UNIT_TEST(NamesAreCollected) { + TString input = R"( USE yt:socrates; SELECT * FROM Input; @@ -63,12 +63,12 @@ Y_UNIT_TEST_SUITE(YqlAnalysisTests) { INSERT INTO plato.Input (id) VALUES (1); )"; - THashMap<TString, THashSet<TString>> expected = { - {"socrates", {"Input", "Newbie"}}, - {"plato", {"Input"}}, - }; + THashMap<TString, THashSet<TString>> expected = { + {"socrates", {"Input", "Newbie"}}, + {"plato", {"Input"}}, + }; - UNIT_ASSERT_VALUES_EQUAL(Analyze(input).TablesByCluster, expected); - } + UNIT_ASSERT_VALUES_EQUAL(Analyze(input).TablesByCluster, expected); +} } // Y_UNIT_TEST_SUITE(YqlAnalysisTests) diff --git a/yql/essentials/sql/v1/complete/antlr4/c3i.h b/yql/essentials/sql/v1/complete/antlr4/c3i.h index b3fcaab7ae0..93a1ed04109 100644 --- a/yql/essentials/sql/v1/complete/antlr4/c3i.h +++ b/yql/essentials/sql/v1/complete/antlr4/c3i.h @@ -12,37 +12,37 @@ namespace NSQLComplete { - // std::vector is used to prevent copying a C3 output - struct TSuggestedToken { - TTokenId Number; - std::vector<TTokenId> Following; +// std::vector is used to prevent copying a C3 output +struct TSuggestedToken { + TTokenId Number; + std::vector<TTokenId> Following; +}; + +struct TMatchedRule { + TRuleId Index; + TParserCallStack ParserCallStack; +}; + +struct TC3Candidates { + TVector<TSuggestedToken> Tokens; + TVector<TMatchedRule> Rules; +}; + +class IC3Engine { +public: + using TPtr = THolder<IC3Engine>; + + // std::unordered_set is used to prevent copying into c3 core + struct TConfig { + std::unordered_set<TTokenId> IgnoredTokens; + std::unordered_set<TRuleId> PreferredRules; + std::unordered_set<TRuleId> IgnoredRules; + std::unordered_map<TTokenId, std::unordered_set<TTokenId>> DisabledPreviousByToken; + std::unordered_map<TTokenId, std::unordered_set<TTokenId>> ForcedPreviousByToken; }; - struct TMatchedRule { - TRuleId Index; - TParserCallStack ParserCallStack; - }; - - struct TC3Candidates { - TVector<TSuggestedToken> Tokens; - TVector<TMatchedRule> Rules; - }; - - class IC3Engine { - public: - using TPtr = THolder<IC3Engine>; - - // std::unordered_set is used to prevent copying into c3 core - struct TConfig { - std::unordered_set<TTokenId> IgnoredTokens; - std::unordered_set<TRuleId> PreferredRules; - std::unordered_set<TRuleId> IgnoredRules; - std::unordered_map<TTokenId, std::unordered_set<TTokenId>> DisabledPreviousByToken; - std::unordered_map<TTokenId, std::unordered_set<TTokenId>> ForcedPreviousByToken; - }; - - virtual ~IC3Engine() = default; - virtual TC3Candidates Complete(TStringBuf text, size_t caretTokenIndex) = 0; - }; + virtual ~IC3Engine() = default; + virtual TC3Candidates Complete(TStringBuf text, size_t caretTokenIndex) = 0; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/antlr4/c3t.h b/yql/essentials/sql/v1/complete/antlr4/c3t.h index d1c80867a59..6bea3f53b2b 100644 --- a/yql/essentials/sql/v1/complete/antlr4/c3t.h +++ b/yql/essentials/sql/v1/complete/antlr4/c3t.h @@ -17,118 +17,118 @@ namespace NSQLComplete { - template <class G> - class TC3Engine: public IC3Engine { - public: - explicit TC3Engine(TConfig config) - : Chars_() - , Lexer_(&Chars_) - , Tokens_(&Lexer_) - , Parser_(&Tokens_) - , CompletionCore_(&Parser_) - , IgnoredRules_(std::move(config.IgnoredRules)) - , DisabledPreviousByToken_(std::move(config.DisabledPreviousByToken)) - , ForcedPreviousByToken_(std::move(config.ForcedPreviousByToken)) - { - Lexer_.removeErrorListeners(); - Parser_.removeErrorListeners(); - - CompletionCore_.ignoredTokens = std::move(config.IgnoredTokens); - CompletionCore_.preferredRules = std::move(config.PreferredRules); - - for (TRuleId rule : IgnoredRules_) { - CompletionCore_.preferredRules.emplace(rule); - } - - PurifyForcedTokens(); - } - - TC3Candidates Complete(TStringBuf text, size_t caretTokenIndex) override { - Assign(text); - auto candidates = CompletionCore_.collectCandidates(caretTokenIndex); - return Converted(std::move(candidates), caretTokenIndex); +template <class G> +class TC3Engine: public IC3Engine { +public: + explicit TC3Engine(TConfig config) + : Chars_() + , Lexer_(&Chars_) + , Tokens_(&Lexer_) + , Parser_(&Tokens_) + , CompletionCore_(&Parser_) + , IgnoredRules_(std::move(config.IgnoredRules)) + , DisabledPreviousByToken_(std::move(config.DisabledPreviousByToken)) + , ForcedPreviousByToken_(std::move(config.ForcedPreviousByToken)) + { + Lexer_.removeErrorListeners(); + Parser_.removeErrorListeners(); + + CompletionCore_.ignoredTokens = std::move(config.IgnoredTokens); + CompletionCore_.preferredRules = std::move(config.PreferredRules); + + for (TRuleId rule : IgnoredRules_) { + CompletionCore_.preferredRules.emplace(rule); } - private: - void PurifyForcedTokens() { - for (auto it = ForcedPreviousByToken_.begin(); it != ForcedPreviousByToken_.end();) { - const auto& [token, previous] = *it; - if (previous.empty()) { - CompletionCore_.ignoredTokens.emplace(token); - it = ForcedPreviousByToken_.erase(it); - } else { - it = std::next(it); - } + PurifyForcedTokens(); + } + + TC3Candidates Complete(TStringBuf text, size_t caretTokenIndex) override { + Assign(text); + auto candidates = CompletionCore_.collectCandidates(caretTokenIndex); + return Converted(std::move(candidates), caretTokenIndex); + } + +private: + void PurifyForcedTokens() { + for (auto it = ForcedPreviousByToken_.begin(); it != ForcedPreviousByToken_.end();) { + const auto& [token, previous] = *it; + if (previous.empty()) { + CompletionCore_.ignoredTokens.emplace(token); + it = ForcedPreviousByToken_.erase(it); + } else { + it = std::next(it); } } + } - void Assign(TStringBuf prefix) { - Chars_.load(prefix.Data(), prefix.Size(), /* lenient = */ false); - Lexer_.reset(); - Tokens_.setTokenSource(&Lexer_); - Tokens_.fill(); - } - - TC3Candidates Converted(c3::CandidatesCollection candidates, size_t caretTokenIndex) { - TC3Candidates converted; + void Assign(TStringBuf prefix) { + Chars_.load(prefix.Data(), prefix.Size(), /* lenient = */ false); + Lexer_.reset(); + Tokens_.setTokenSource(&Lexer_); + Tokens_.fill(); + } - for (auto& [token, following] : candidates.tokens) { - if (IsIgnored(token, caretTokenIndex)) { - continue; - } + TC3Candidates Converted(c3::CandidatesCollection candidates, size_t caretTokenIndex) { + TC3Candidates converted; - converted.Tokens.emplace_back(token, std::move(following)); + for (auto& [token, following] : candidates.tokens) { + if (IsIgnored(token, caretTokenIndex)) { + continue; } - for (auto& [rule, data] : candidates.rules) { - if (IsIgnored(rule, data.ruleList)) { - continue; - } + converted.Tokens.emplace_back(token, std::move(following)); + } - converted.Rules.emplace_back(rule, std::move(data.ruleList)); - converted.Rules.back().ParserCallStack.emplace_back(rule); + for (auto& [rule, data] : candidates.rules) { + if (IsIgnored(rule, data.ruleList)) { + continue; } - return converted; + converted.Rules.emplace_back(rule, std::move(data.ruleList)); + converted.Rules.back().ParserCallStack.emplace_back(rule); } - bool IsIgnored(TTokenId token, size_t caretTokenIndex) { - auto previous = PreviousToken(caretTokenIndex); + return converted; + } - auto disabled = DisabledPreviousByToken_.find(token); - auto forced = ForcedPreviousByToken_.find(token); + bool IsIgnored(TTokenId token, size_t caretTokenIndex) { + auto previous = PreviousToken(caretTokenIndex); - return (disabled != DisabledPreviousByToken_.end() && disabled->second.contains(previous)) || - (forced != ForcedPreviousByToken_.end() && !forced->second.contains(previous)); - } + auto disabled = DisabledPreviousByToken_.find(token); + auto forced = ForcedPreviousByToken_.find(token); - bool IsIgnored(TRuleId head, const std::vector<TRuleId> tail) const { - return IgnoredRules_.contains(head) || - AnyOf(tail, [this](TRuleId r) { return IgnoredRules_.contains(r); }); - } + return (disabled != DisabledPreviousByToken_.end() && disabled->second.contains(previous)) || + (forced != ForcedPreviousByToken_.end() && !forced->second.contains(previous)); + } - TTokenId PreviousToken(size_t caretTokenIndex) { - ssize_t index = static_cast<ssize_t>(caretTokenIndex) - 1; - while (0 <= index && Tokens_.get(index)->getChannel() == antlr4::Token::HIDDEN_CHANNEL) { - --index; - } + bool IsIgnored(TRuleId head, const std::vector<TRuleId> tail) const { + return IgnoredRules_.contains(head) || + AnyOf(tail, [this](TRuleId r) { return IgnoredRules_.contains(r); }); + } - if (index < 0) { - return antlr4::Token::INVALID_TYPE; - } + TTokenId PreviousToken(size_t caretTokenIndex) { + ssize_t index = static_cast<ssize_t>(caretTokenIndex) - 1; + while (0 <= index && Tokens_.get(index)->getChannel() == antlr4::Token::HIDDEN_CHANNEL) { + --index; + } - return Tokens_.get(index)->getType(); + if (index < 0) { + return antlr4::Token::INVALID_TYPE; } - antlr4::ANTLRInputStream Chars_; - G::TLexer Lexer_; - antlr4::BufferedTokenStream Tokens_; - G::TParser Parser_; - c3::CodeCompletionCore CompletionCore_; + return Tokens_.get(index)->getType(); + } + + antlr4::ANTLRInputStream Chars_; + G::TLexer Lexer_; + antlr4::BufferedTokenStream Tokens_; + G::TParser Parser_; + c3::CodeCompletionCore CompletionCore_; - std::unordered_set<TRuleId> IgnoredRules_; - std::unordered_map<TTokenId, std::unordered_set<TTokenId>> DisabledPreviousByToken_; - std::unordered_map<TTokenId, std::unordered_set<TTokenId>> ForcedPreviousByToken_; - }; + std::unordered_set<TRuleId> IgnoredRules_; + std::unordered_map<TTokenId, std::unordered_set<TTokenId>> DisabledPreviousByToken_; + std::unordered_map<TTokenId, std::unordered_set<TTokenId>> ForcedPreviousByToken_; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/antlr4/defs.h b/yql/essentials/sql/v1/complete/antlr4/defs.h index 7f2991a8a74..adacf9ef5a2 100644 --- a/yql/essentials/sql/v1/complete/antlr4/defs.h +++ b/yql/essentials/sql/v1/complete/antlr4/defs.h @@ -7,12 +7,12 @@ namespace NSQLComplete { - using TTokenId = size_t; - using TRuleId = size_t; +using TTokenId = size_t; +using TRuleId = size_t; - constexpr TTokenId TOKEN_EOF = antlr4::Token::EOF; +constexpr TTokenId TOKEN_EOF = antlr4::Token::EOF; - // std::vector is used to prevent copying a C3 output - using TParserCallStack = std::vector<TRuleId>; +// std::vector is used to prevent copying a C3 output +using TParserCallStack = std::vector<TRuleId>; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/antlr4/pipeline.h b/yql/essentials/sql/v1/complete/antlr4/pipeline.h index 75fd2e5ba2c..5caceb73daa 100644 --- a/yql/essentials/sql/v1/complete/antlr4/pipeline.h +++ b/yql/essentials/sql/v1/complete/antlr4/pipeline.h @@ -2,12 +2,12 @@ namespace NSQLComplete { - template <class Lexer, class Parser> - struct TAntlrGrammar { - using TLexer = Lexer; - using TParser = Parser; +template <class Lexer, class Parser> +struct TAntlrGrammar { + using TLexer = Lexer; + using TParser = Parser; - TAntlrGrammar() = delete; - }; + TAntlrGrammar() = delete; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/antlr4/vocabulary.cpp b/yql/essentials/sql/v1/complete/antlr4/vocabulary.cpp index 0938ae3aca0..318f9857456 100644 --- a/yql/essentials/sql/v1/complete/antlr4/vocabulary.cpp +++ b/yql/essentials/sql/v1/complete/antlr4/vocabulary.cpp @@ -2,13 +2,13 @@ namespace NSQLComplete { - std::string Display(const antlr4::dfa::Vocabulary& vocabulary, TTokenId tokenType) { - auto name = vocabulary.getDisplayName(tokenType); - if (2 <= name.length() && name.starts_with('\'') && name.ends_with('\'')) { - name.erase(static_cast<std::string::size_type>(0), 1); - name.pop_back(); - } - return name; +std::string Display(const antlr4::dfa::Vocabulary& vocabulary, TTokenId tokenType) { + auto name = vocabulary.getDisplayName(tokenType); + if (2 <= name.length() && name.starts_with('\'') && name.ends_with('\'')) { + name.erase(static_cast<std::string::size_type>(0), 1); + name.pop_back(); } + return name; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/antlr4/vocabulary.h b/yql/essentials/sql/v1/complete/antlr4/vocabulary.h index deb67828800..155ecd97fff 100644 --- a/yql/essentials/sql/v1/complete/antlr4/vocabulary.h +++ b/yql/essentials/sql/v1/complete/antlr4/vocabulary.h @@ -8,6 +8,6 @@ namespace NSQLComplete { - std::string Display(const antlr4::dfa::Vocabulary& vocabulary, TTokenId tokenType); +std::string Display(const antlr4::dfa::Vocabulary& vocabulary, TTokenId tokenType); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/bench/main.cpp b/yql/essentials/sql/v1/complete/bench/main.cpp index f9cb52ee11f..a16d7592b3d 100644 --- a/yql/essentials/sql/v1/complete/bench/main.cpp +++ b/yql/essentials/sql/v1/complete/bench/main.cpp @@ -12,28 +12,28 @@ namespace NSQLComplete { - NSQLComplete::TLexerSupplier MakePureLexerSupplier() { - NSQLTranslationV1::TLexers lexers; - lexers.Antlr4Pure = NSQLTranslationV1::MakeAntlr4PureLexerFactory(); - lexers.Antlr4PureAnsi = NSQLTranslationV1::MakeAntlr4PureAnsiLexerFactory(); - return [lexers = std::move(lexers)](bool ansi) { - return NSQLTranslationV1::MakeLexer( - lexers, ansi, /* antlr4 = */ true, - NSQLTranslationV1::ELexerFlavor::Pure); - }; - } - - void BenchmarkComplete(benchmark::State& state) { - auto names = NSQLComplete::LoadDefaultNameSet(); - auto ranking = NSQLComplete::MakeDefaultRanking(); - auto service = MakeStaticNameService(std::move(names), std::move(ranking)); - auto engine = MakeSqlCompletionEngine(MakePureLexerSupplier(), std::move(service)); - - for (const auto _ : state) { - auto completion = engine->Complete({"SELECT "}); - benchmark::DoNotOptimize(completion); - } +NSQLComplete::TLexerSupplier MakePureLexerSupplier() { + NSQLTranslationV1::TLexers lexers; + lexers.Antlr4Pure = NSQLTranslationV1::MakeAntlr4PureLexerFactory(); + lexers.Antlr4PureAnsi = NSQLTranslationV1::MakeAntlr4PureAnsiLexerFactory(); + return [lexers = std::move(lexers)](bool ansi) { + return NSQLTranslationV1::MakeLexer( + lexers, ansi, /* antlr4 = */ true, + NSQLTranslationV1::ELexerFlavor::Pure); + }; +} + +void BenchmarkComplete(benchmark::State& state) { + auto names = NSQLComplete::LoadDefaultNameSet(); + auto ranking = NSQLComplete::MakeDefaultRanking(); + auto service = MakeStaticNameService(std::move(names), std::move(ranking)); + auto engine = MakeSqlCompletionEngine(MakePureLexerSupplier(), std::move(service)); + + for (const auto _ : state) { + auto completion = engine->Complete({"SELECT "}); + benchmark::DoNotOptimize(completion); } +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/check/check_complete.cpp b/yql/essentials/sql/v1/complete/check/check_complete.cpp index dbbc4b1e6c4..2ed7ccd835e 100644 --- a/yql/essentials/sql/v1/complete/check/check_complete.cpp +++ b/yql/essentials/sql/v1/complete/check/check_complete.cpp @@ -17,93 +17,93 @@ namespace NSQLComplete { - namespace { - - TLexerSupplier MakePureLexerSupplier() { - NSQLTranslationV1::TLexers lexers; - lexers.Antlr4Pure = NSQLTranslationV1::MakeAntlr4PureLexerFactory(); - lexers.Antlr4PureAnsi = NSQLTranslationV1::MakeAntlr4PureAnsiLexerFactory(); - return [lexers = std::move(lexers)](bool ansi) { - return NSQLTranslationV1::MakeLexer( - lexers, ansi, /* antlr4 = */ true, - NSQLTranslationV1::ELexerFlavor::Pure); - }; +namespace { + +TLexerSupplier MakePureLexerSupplier() { + NSQLTranslationV1::TLexers lexers; + lexers.Antlr4Pure = NSQLTranslationV1::MakeAntlr4PureLexerFactory(); + lexers.Antlr4PureAnsi = NSQLTranslationV1::MakeAntlr4PureAnsiLexerFactory(); + return [lexers = std::move(lexers)](bool ansi) { + return NSQLTranslationV1::MakeLexer( + lexers, ansi, /* antlr4 = */ true, + NSQLTranslationV1::ELexerFlavor::Pure); + }; +} + +INameService::TPtr MakeClusterNameService(const TYqlContext& ctx) { + THashSet<TString> clusterSet = ctx.Clusters(); + TVector<TString> clusterVec(begin(clusterSet), end(clusterSet)); + Sort(clusterVec); + + return MakeClusterNameService(MakeStaticClusterDiscovery(std::move(clusterVec))); +} + +INameService::TPtr MakeSchemaNameService(const TYqlContext& ctx) { + THashMap<TString, THashMap<TString, TVector<TFolderEntry>>> fs; + for (const auto& [cluster, tables] : ctx.TablesByCluster) { + for (TString table : tables) { + fs[cluster]["/"].push_back(TFolderEntry{ + .Type = TFolderEntry::Table, + .Name = std::move(table), + }); } + } - INameService::TPtr MakeClusterNameService(const TYqlContext& ctx) { - THashSet<TString> clusterSet = ctx.Clusters(); - TVector<TString> clusterVec(begin(clusterSet), end(clusterSet)); - Sort(clusterVec); - - return MakeClusterNameService(MakeStaticClusterDiscovery(std::move(clusterVec))); + return MakeSchemaNameService(MakeSimpleSchema(MakeStaticSimpleSchema({.Folders = std::move(fs)}))); +} + +} // namespace + +bool CheckComplete(TStringBuf query, TYqlContext ctx) { + constexpr size_t Seed = 97651231; + constexpr size_t Attempts = 64; + constexpr size_t MaxAttempts = 256; + SetRandomSeed(Seed); + + auto service = MakeUnionNameService( + { + MakeClusterNameService(ctx), + MakeSchemaNameService(ctx), + }, + MakeDefaultRanking()); + + auto engine = MakeSqlCompletionEngine( + MakePureLexerSupplier(), + std::move(service), + MakeYQLConfiguration()); + + for (size_t i = 0, j = 0; i < Attempts && j < MaxAttempts; ++j) { + size_t pos = RandomNumber<size_t>(query.size() + 1); + if (pos < query.size() && IsUTF8ContinuationByte(query.at(pos))) { + continue; } - INameService::TPtr MakeSchemaNameService(const TYqlContext& ctx) { - THashMap<TString, THashMap<TString, TVector<TFolderEntry>>> fs; - for (const auto& [cluster, tables] : ctx.TablesByCluster) { - for (TString table : tables) { - fs[cluster]["/"].push_back(TFolderEntry{ - .Type = TFolderEntry::Table, - .Name = std::move(table), - }); - } - } - - return MakeSchemaNameService(MakeSimpleSchema(MakeStaticSimpleSchema({.Folders = std::move(fs)}))); - } + TCompletionInput input = { + .Text = query, + .CursorPosition = pos, + }; - } // namespace - - bool CheckComplete(TStringBuf query, TYqlContext ctx) { - constexpr size_t Seed = 97651231; - constexpr size_t Attempts = 64; - constexpr size_t MaxAttempts = 256; - SetRandomSeed(Seed); - - auto service = MakeUnionNameService( - { - MakeClusterNameService(ctx), - MakeSchemaNameService(ctx), - }, - MakeDefaultRanking()); - - auto engine = MakeSqlCompletionEngine( - MakePureLexerSupplier(), - std::move(service), - MakeYQLConfiguration()); - - for (size_t i = 0, j = 0; i < Attempts && j < MaxAttempts; ++j) { - size_t pos = RandomNumber<size_t>(query.size() + 1); - if (pos < query.size() && IsUTF8ContinuationByte(query.at(pos))) { - continue; - } - - TCompletionInput input = { - .Text = query, - .CursorPosition = pos, - }; - - auto output = engine->Complete(input).ExtractValueSync(); - Y_DO_NOT_OPTIMIZE_AWAY(output); - - i += 1; - } + auto output = engine->Complete(input).ExtractValueSync(); + Y_DO_NOT_OPTIMIZE_AWAY(output); - return true; + i += 1; } - bool CheckComplete(TStringBuf query, NYql::TExprNode::TPtr root, NYql::TExprContext& ctx, NYql::TIssues& issues) try { - return CheckComplete(query, MakeYqlAnalysis()->Analyze(root, ctx)); - } catch (...) { - issues.AddIssue(FormatCurrentException()); - return false; - } - - bool CheckComplete(TStringBuf query, NYql::TAstNode& root, NYql::TIssues& issues) try { - return CheckComplete(query, MakeYqlAnalysis()->Analyze(root, issues).GetOrElse({})); - } catch (...) { - issues.AddIssue(FormatCurrentException()); - return false; - } + return true; +} + +bool CheckComplete(TStringBuf query, NYql::TExprNode::TPtr root, NYql::TExprContext& ctx, NYql::TIssues& issues) try { + return CheckComplete(query, MakeYqlAnalysis()->Analyze(root, ctx)); +} catch (...) { + issues.AddIssue(FormatCurrentException()); + return false; +} + +bool CheckComplete(TStringBuf query, NYql::TAstNode& root, NYql::TIssues& issues) try { + return CheckComplete(query, MakeYqlAnalysis()->Analyze(root, issues).GetOrElse({})); +} catch (...) { + issues.AddIssue(FormatCurrentException()); + return false; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/check/check_complete.h b/yql/essentials/sql/v1/complete/check/check_complete.h index 8ec0af40c5e..1d2ca818132 100644 --- a/yql/essentials/sql/v1/complete/check/check_complete.h +++ b/yql/essentials/sql/v1/complete/check/check_complete.h @@ -10,12 +10,12 @@ namespace NSQLComplete { - bool CheckComplete( - TStringBuf query, - NYql::TExprNode::TPtr root, - NYql::TExprContext& ctx, - NYql::TIssues& issues); +bool CheckComplete( + TStringBuf query, + NYql::TExprNode::TPtr root, + NYql::TExprContext& ctx, + NYql::TIssues& issues); - bool CheckComplete(TStringBuf query, NYql::TAstNode& root, NYql::TIssues& issues); +bool CheckComplete(TStringBuf query, NYql::TAstNode& root, NYql::TIssues& issues); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/check/check_complete_ut.cpp b/yql/essentials/sql/v1/complete/check/check_complete_ut.cpp index 3b4f28e0fd6..2857fd55277 100644 --- a/yql/essentials/sql/v1/complete/check/check_complete_ut.cpp +++ b/yql/essentials/sql/v1/complete/check/check_complete_ut.cpp @@ -13,34 +13,34 @@ using namespace NSQLComplete; Y_UNIT_TEST_SUITE(CheckTests) { - Y_UNIT_TEST(Runs) { - TString query = R"( +Y_UNIT_TEST(Runs) { + TString query = R"( SELECT * FROM (SELECT 1 AS x) )"; - NSQLTranslationV1::TLexers lexers = { - .Antlr4 = NSQLTranslationV1::MakeAntlr4LexerFactory(), - .Antlr4Ansi = NSQLTranslationV1::MakeAntlr4AnsiLexerFactory(), - }; + NSQLTranslationV1::TLexers lexers = { + .Antlr4 = NSQLTranslationV1::MakeAntlr4LexerFactory(), + .Antlr4Ansi = NSQLTranslationV1::MakeAntlr4AnsiLexerFactory(), + }; - NSQLTranslationV1::TParsers parsers = { - .Antlr4 = NSQLTranslationV1::MakeAntlr4ParserFactory(/*isAmbiguityError=*/ true), - .Antlr4Ansi = NSQLTranslationV1::MakeAntlr4AnsiParserFactory(/*isAmbiguityError=*/ true), - }; + NSQLTranslationV1::TParsers parsers = { + .Antlr4 = NSQLTranslationV1::MakeAntlr4ParserFactory(/*isAmbiguityError=*/true), + .Antlr4Ansi = NSQLTranslationV1::MakeAntlr4AnsiParserFactory(/*isAmbiguityError=*/true), + }; - NSQLTranslation::TTranslators translators( - /* V0 = */ nullptr, - /* V1 = */ NSQLTranslationV1::MakeTranslator(lexers, parsers), - /* PG = */ nullptr); + NSQLTranslation::TTranslators translators( + /* V0 = */ nullptr, + /* V1 = */ NSQLTranslationV1::MakeTranslator(lexers, parsers), + /* PG = */ nullptr); - google::protobuf::Arena arena; - NSQLTranslation::TTranslationSettings settings; - settings.Arena = &arena; + google::protobuf::Arena arena; + NSQLTranslation::TTranslationSettings settings; + settings.Arena = &arena; - NYql::TAstParseResult result = NSQLTranslation::SqlToYql(translators, query, settings); - Y_ENSURE(result.IsOk()); + NYql::TAstParseResult result = NSQLTranslation::SqlToYql(translators, query, settings); + Y_ENSURE(result.IsOk()); - Y_ENSURE(CheckComplete(query, *result.Root, result.Issues), result.Issues.ToString()); - } + Y_ENSURE(CheckComplete(query, *result.Root, result.Issues), result.Issues.ToString()); +} } // Y_UNIT_TEST_SUITE(CheckTests) diff --git a/yql/essentials/sql/v1/complete/configuration.cpp b/yql/essentials/sql/v1/complete/configuration.cpp index b1996beed0a..f8a9b1e9487 100644 --- a/yql/essentials/sql/v1/complete/configuration.cpp +++ b/yql/essentials/sql/v1/complete/configuration.cpp @@ -4,61 +4,61 @@ namespace NSQLComplete { - TConfiguration MakeConfiguration(THashSet<TString> allowedStmts) { - allowedStmts.emplace("sql_stmt"); +TConfiguration MakeConfiguration(THashSet<TString> allowedStmts) { + allowedStmts.emplace("sql_stmt"); - TConfiguration config; - for (const std::string& name : GetSqlGrammar().GetAllRules()) { - if (name.ends_with("_stmt") && !allowedStmts.contains(name)) { - config.IgnoredRules_.emplace(name); - } + TConfiguration config; + for (const std::string& name : GetSqlGrammar().GetAllRules()) { + if (name.ends_with("_stmt") && !allowedStmts.contains(name)) { + config.IgnoredRules_.emplace(name); } - return config; } + return config; +} - TConfiguration MakeYDBConfiguration() { - TConfiguration config; - config.IgnoredRules_ = { - "use_stmt", - "import_stmt", - "export_stmt", - }; - return config; - } +TConfiguration MakeYDBConfiguration() { + TConfiguration config; + config.IgnoredRules_ = { + "use_stmt", + "import_stmt", + "export_stmt", + }; + return config; +} - TConfiguration MakeYQLConfiguration() { - auto config = MakeConfiguration(/* allowedStmts = */ { - "lambda_stmt", - "declare_stmt", - "import_stmt", - "export_stmt", - "do_stmt", - "pragma_stmt", - "select_stmt", - "select_unparenthesized_stmt", - "into_table_stmt", - "values_stmt", - "drop_table_stmt", - "define_action_or_subquery_stmt", - "if_stmt", - "for_stmt", - "use_stmt", - "subselect_stmt", - "named_nodes_stmt", - "commit_stmt", - }); +TConfiguration MakeYQLConfiguration() { + auto config = MakeConfiguration(/* allowedStmts = */ { + "lambda_stmt", + "declare_stmt", + "import_stmt", + "export_stmt", + "do_stmt", + "pragma_stmt", + "select_stmt", + "select_unparenthesized_stmt", + "into_table_stmt", + "values_stmt", + "drop_table_stmt", + "define_action_or_subquery_stmt", + "if_stmt", + "for_stmt", + "use_stmt", + "subselect_stmt", + "named_nodes_stmt", + "commit_stmt", + }); - config.DisabledPreviousByToken_ = {}; + config.DisabledPreviousByToken_ = {}; - config.ForcedPreviousByToken_ = { - {"PARALLEL", {}}, - {"TABLESTORE", {}}, - {"FOR", {"EVALUATE"}}, - {"IF", {"EVALUATE"}}, - {"EXTERNAL", {"USING"}}, - }; + config.ForcedPreviousByToken_ = { + {"PARALLEL", {}}, + {"TABLESTORE", {}}, + {"FOR", {"EVALUATE"}}, + {"IF", {"EVALUATE"}}, + {"EXTERNAL", {"USING"}}, + }; - return config; - } + return config; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/configuration.h b/yql/essentials/sql/v1/complete/configuration.h index 620207bfcf2..437f21cb160 100644 --- a/yql/essentials/sql/v1/complete/configuration.h +++ b/yql/essentials/sql/v1/complete/configuration.h @@ -6,23 +6,23 @@ namespace NSQLComplete { - struct TConfiguration { - friend class TSqlCompletionEngine; - friend TConfiguration MakeYDBConfiguration(); - friend TConfiguration MakeYQLConfiguration(); - friend TConfiguration MakeConfiguration(THashSet<TString> allowedStmts); +struct TConfiguration { + friend class TSqlCompletionEngine; + friend TConfiguration MakeYDBConfiguration(); + friend TConfiguration MakeYQLConfiguration(); + friend TConfiguration MakeConfiguration(THashSet<TString> allowedStmts); - public: - size_t Limit = 256; +public: + size_t Limit = 256; - private: - THashSet<TString> IgnoredRules_; - THashMap<TString, THashSet<TString>> DisabledPreviousByToken_; - THashMap<TString, THashSet<TString>> ForcedPreviousByToken_; - }; +private: + THashSet<TString> IgnoredRules_; + THashMap<TString, THashSet<TString>> DisabledPreviousByToken_; + THashMap<TString, THashSet<TString>> ForcedPreviousByToken_; +}; - TConfiguration MakeYDBConfiguration(); +TConfiguration MakeYDBConfiguration(); - TConfiguration MakeYQLConfiguration(); +TConfiguration MakeYQLConfiguration(); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/core/environment.h b/yql/essentials/sql/v1/complete/core/environment.h index 0f0299a9353..07a08a7d7ad 100644 --- a/yql/essentials/sql/v1/complete/core/environment.h +++ b/yql/essentials/sql/v1/complete/core/environment.h @@ -7,10 +7,10 @@ namespace NSQLComplete { - struct TEnvironment { - // Given `{ "$x": "{ "Data": "foo" }" }`, - // it will contain `{ "$x": "foo" }` - THashMap<TString, NYT::TNode> Parameters; - }; +struct TEnvironment { + // Given `{ "$x": "{ "Data": "foo" }" }`, + // it will contain `{ "$x": "foo" }` + THashMap<TString, NYT::TNode> Parameters; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/core/input.cpp b/yql/essentials/sql/v1/complete/core/input.cpp index 8eca3a28ee8..0c0126c71ce 100644 --- a/yql/essentials/sql/v1/complete/core/input.cpp +++ b/yql/essentials/sql/v1/complete/core/input.cpp @@ -4,22 +4,22 @@ namespace NSQLComplete { - TCompletionInput SharpedInput(TString& text) { - constexpr char delim = '#'; +TCompletionInput SharpedInput(TString& text) { + constexpr char delim = '#'; - size_t pos = text.find_first_of(delim); - if (pos == TString::npos) { - return { - .Text = text, - }; - } - - Y_ENSURE(!TStringBuf(text).Tail(pos + 1).Contains(delim)); - text.erase(std::begin(text) + pos); + size_t pos = text.find_first_of(delim); + if (pos == TString::npos) { return { .Text = text, - .CursorPosition = pos, }; } + Y_ENSURE(!TStringBuf(text).Tail(pos + 1).Contains(delim)); + text.erase(std::begin(text) + pos); + return { + .Text = text, + .CursorPosition = pos, + }; +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/core/input.h b/yql/essentials/sql/v1/complete/core/input.h index 917ae5388c1..f64412181cb 100644 --- a/yql/essentials/sql/v1/complete/core/input.h +++ b/yql/essentials/sql/v1/complete/core/input.h @@ -4,16 +4,16 @@ namespace NSQLComplete { - struct TCompletionInput { - TStringBuf Text; - size_t CursorPosition = Text.length(); - }; +struct TCompletionInput { + TStringBuf Text; + size_t CursorPosition = Text.length(); +}; - struct TMaterializedInput { - TString Text; - size_t CursorPosition = Text.length(); - }; +struct TMaterializedInput { + TString Text; + size_t CursorPosition = Text.length(); +}; - TCompletionInput SharpedInput(TString& text Y_LIFETIME_BOUND); +TCompletionInput SharpedInput(TString& text Y_LIFETIME_BOUND); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/core/name.cpp b/yql/essentials/sql/v1/complete/core/name.cpp index 80a13ca773a..2caa488929d 100644 --- a/yql/essentials/sql/v1/complete/core/name.cpp +++ b/yql/essentials/sql/v1/complete/core/name.cpp @@ -7,22 +7,22 @@ namespace NSQLComplete { - bool operator<(const TTableId& lhs, const TTableId& rhs) { - return std::tie(lhs.Cluster, lhs.Path) < std::tie(rhs.Cluster, rhs.Path); - } +bool operator<(const TTableId& lhs, const TTableId& rhs) { + return std::tie(lhs.Cluster, lhs.Path) < std::tie(rhs.Cluster, rhs.Path); +} - TString LowerizeName(TStringBuf name) { - return ToLowerUTF8(name); - } +TString LowerizeName(TStringBuf name) { + return ToLowerUTF8(name); +} - TString NormalizeName(TStringBuf name) { - TString normalized(name); - TMaybe<NYql::TIssue> error = NYql::NormalizeName(NYql::TPosition(), normalized); - if (!error.Empty()) { - return LowerizeName(name); - } - return normalized; +TString NormalizeName(TStringBuf name) { + TString normalized(name); + TMaybe<NYql::TIssue> error = NYql::NormalizeName(NYql::TPosition(), normalized); + if (!error.Empty()) { + return LowerizeName(name); } + return normalized; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/core/name.h b/yql/essentials/sql/v1/complete/core/name.h index 367c532b3d0..80f0575dd29 100644 --- a/yql/essentials/sql/v1/complete/core/name.h +++ b/yql/essentials/sql/v1/complete/core/name.h @@ -5,58 +5,58 @@ namespace NSQLComplete { - enum class EObjectKind { - Folder, - Table, - Unknown, - }; - - enum class ENodeKind { - Any, - Table, - }; - - struct TTableId { - TString Cluster; - TString Path; - - friend bool operator<(const TTableId& lhs, const TTableId& rhs); - friend bool operator==(const TTableId& lhs, const TTableId& rhs) = default; - }; - - template <class T> - requires std::regular<T> && - requires(T x) { {x < x} -> std::convertible_to<bool>; } - struct TAliased: T { - TString Alias; - - TAliased(TString alias, T value) - : T(std::move(value)) - , Alias(std::move(alias)) - { - } - - TAliased(T value) - : T(std::move(value)) - { - } - - friend bool operator<(const TAliased& lhs, const TAliased& rhs) { - return std::tie(lhs.Alias, static_cast<const T&>(lhs)) < std::tie(rhs.Alias, static_cast<const T&>(rhs)); - } - - friend bool operator==(const TAliased& lhs, const TAliased& rhs) = default; - }; - - struct TColumnId { - TString TableAlias; - TString Name; - - friend bool operator<(const TColumnId& lhs, const TColumnId& rhs); - friend bool operator==(const TColumnId& lhs, const TColumnId& rhs) = default; - }; - - TString NormalizeName(TStringBuf name); +enum class EObjectKind { + Folder, + Table, + Unknown, +}; + +enum class ENodeKind { + Any, + Table, +}; + +struct TTableId { + TString Cluster; + TString Path; + + friend bool operator<(const TTableId& lhs, const TTableId& rhs); + friend bool operator==(const TTableId& lhs, const TTableId& rhs) = default; +}; + +template <class T> + requires std::regular<T> && + requires(T x) { {x < x} -> std::convertible_to<bool>; } +struct TAliased: T { + TString Alias; + + TAliased(TString alias, T value) + : T(std::move(value)) + , Alias(std::move(alias)) + { + } + + TAliased(T value) + : T(std::move(value)) + { + } + + friend bool operator<(const TAliased& lhs, const TAliased& rhs) { + return std::tie(lhs.Alias, static_cast<const T&>(lhs)) < std::tie(rhs.Alias, static_cast<const T&>(rhs)); + } + + friend bool operator==(const TAliased& lhs, const TAliased& rhs) = default; +}; + +struct TColumnId { + TString TableAlias; + TString Name; + + friend bool operator<(const TColumnId& lhs, const TColumnId& rhs); + friend bool operator==(const TColumnId& lhs, const TColumnId& rhs) = default; +}; + +TString NormalizeName(TStringBuf name); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/core/statement.h b/yql/essentials/sql/v1/complete/core/statement.h index d4c095a0e1f..eb0151084a3 100644 --- a/yql/essentials/sql/v1/complete/core/statement.h +++ b/yql/essentials/sql/v1/complete/core/statement.h @@ -2,9 +2,9 @@ namespace NSQLComplete { - enum class EStatementKind { - Select, - Insert, - }; +enum class EStatementKind { + Select, + Insert, +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/cache/byte_size.h b/yql/essentials/sql/v1/complete/name/cache/byte_size.h index feb3e8e7bf9..5828b263236 100644 --- a/yql/essentials/sql/v1/complete/name/cache/byte_size.h +++ b/yql/essentials/sql/v1/complete/name/cache/byte_size.h @@ -9,47 +9,47 @@ namespace NSQLComplete { - template <class T> - struct TByteSize; - - template <class T> - requires std::is_fundamental_v<T> - struct TByteSize<T> { - size_t operator()(const T& x) const noexcept { - return sizeof(x); - } - }; - - template <class T> - struct TByteSize<TVector<T>> { - size_t operator()(const TVector<T>& x) const noexcept { - size_t bytes = sizeof(x); - bytes = Accumulate(x, bytes, [](size_t acc, const T& x) { - return acc + TByteSize<T>()(x); - }); - bytes += x.capacity() * sizeof(T); - return bytes; - } - }; - - template <> - struct TByteSize<TString> { - size_t operator()(const TString& x) const noexcept { - return std::max(sizeof(x), sizeof(x) + x.capacity()); - } - }; - - template <class T> - struct TByteSize<TMaybe<T>> { - size_t operator()(const TMaybe<T>& x) const noexcept { - return x.Transform([](const T& x) { return TByteSize<T>()(x) - sizeof(T); }).GetOrElse(0) + - sizeof(TMaybe<T>); - } - }; - - template <class T> - concept CByteSized = requires(const T& x) { - { TByteSize<T>()(x) } -> std::convertible_to<std::size_t>; - }; +template <class T> +struct TByteSize; + +template <class T> + requires std::is_fundamental_v<T> +struct TByteSize<T> { + size_t operator()(const T& x) const noexcept { + return sizeof(x); + } +}; + +template <class T> +struct TByteSize<TVector<T>> { + size_t operator()(const TVector<T>& x) const noexcept { + size_t bytes = sizeof(x); + bytes = Accumulate(x, bytes, [](size_t acc, const T& x) { + return acc + TByteSize<T>()(x); + }); + bytes += x.capacity() * sizeof(T); + return bytes; + } +}; + +template <> +struct TByteSize<TString> { + size_t operator()(const TString& x) const noexcept { + return std::max(sizeof(x), sizeof(x) + x.capacity()); + } +}; + +template <class T> +struct TByteSize<TMaybe<T>> { + size_t operator()(const TMaybe<T>& x) const noexcept { + return x.Transform([](const T& x) { return TByteSize<T>()(x) - sizeof(T); }).GetOrElse(0) + + sizeof(TMaybe<T>); + } +}; + +template <class T> +concept CByteSized = requires(const T& x) { + { TByteSize<T>()(x) } -> std::convertible_to<std::size_t>; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/cache/cache.h b/yql/essentials/sql/v1/complete/name/cache/cache.h index 357989edc50..f98e820d3ce 100644 --- a/yql/essentials/sql/v1/complete/name/cache/cache.h +++ b/yql/essentials/sql/v1/complete/name/cache/cache.h @@ -9,34 +9,34 @@ namespace NSQLComplete { - namespace NPrivate { +namespace NPrivate { - template <class T> - concept CHashable = requires(const T& x) { - { THash<T>()(x) } -> std::convertible_to<std::size_t>; - }; +template <class T> +concept CHashable = requires(const T& x) { + { THash<T>()(x) } -> std::convertible_to<std::size_t>; +}; - template <class T> - concept CCacheKey = std::regular<T> && CHashable<T> && CByteSized<T>; +template <class T> +concept CCacheKey = std::regular<T> && CHashable<T> && CByteSized<T>; - template <class T> - concept CCacheValue = std::copyable<T> && CByteSized<T>; +template <class T> +concept CCacheValue = std::copyable<T> && CByteSized<T>; - }; // namespace NPrivate +}; // namespace NPrivate - template <NPrivate::CCacheKey TKey, NPrivate::CCacheValue TValue> - class ICache: public TThrRefBase { - public: - using TPtr = TIntrusivePtr<ICache>; +template <NPrivate::CCacheKey TKey, NPrivate::CCacheValue TValue> +class ICache: public TThrRefBase { +public: + using TPtr = TIntrusivePtr<ICache>; - struct TEntry { - TMaybe<TValue> Value = Nothing(); - bool IsExpired = true; - }; - - virtual ~ICache() = default; - virtual NThreading::TFuture<TEntry> Get(const TKey& key) const = 0; - virtual NThreading::TFuture<void> Update(const TKey& key, TValue value) const = 0; + struct TEntry { + TMaybe<TValue> Value = Nothing(); + bool IsExpired = true; }; + virtual ~ICache() = default; + virtual NThreading::TFuture<TEntry> Get(const TKey& key) const = 0; + virtual NThreading::TFuture<void> Update(const TKey& key, TValue value) const = 0; +}; + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/cache/cached.h b/yql/essentials/sql/v1/complete/name/cache/cached.h index 80edb159e5a..e2c4a43abad 100644 --- a/yql/essentials/sql/v1/complete/name/cache/cached.h +++ b/yql/essentials/sql/v1/complete/name/cache/cached.h @@ -4,64 +4,64 @@ namespace NSQLComplete { - template <NPrivate::CCacheKey TKey, NPrivate::CCacheValue TValue> - class TCachedQuery { - public: - using TFunc = std::function<NThreading::TFuture<TValue>(const TKey& key)>; +template <NPrivate::CCacheKey TKey, NPrivate::CCacheValue TValue> +class TCachedQuery { +public: + using TFunc = std::function<NThreading::TFuture<TValue>(const TKey& key)>; - TCachedQuery(ICache<TKey, TValue>::TPtr cache, TFunc query) - : Cache_(std::move(cache)) - , Query_(std::move(query)) - { - } + TCachedQuery(ICache<TKey, TValue>::TPtr cache, TFunc query) + : Cache_(std::move(cache)) + , Query_(std::move(query)) + { + } - NThreading::TFuture<TValue> operator()(TKey key) const { - auto promise = NThreading::NewPromise<TValue>(); - Cache_->Get(key).Apply([cache = Cache_, - query = Query_, - key = std::move(key), - promise](auto f) mutable { - typename ICache<TKey, TValue>::TEntry entry; + NThreading::TFuture<TValue> operator()(TKey key) const { + auto promise = NThreading::NewPromise<TValue>(); + Cache_->Get(key).Apply([cache = Cache_, + query = Query_, + key = std::move(key), + promise](auto f) mutable { + typename ICache<TKey, TValue>::TEntry entry; + try { + entry = f.ExtractValue(); + } catch (...) { + promise.SetException(std::current_exception()); + return; + } + + if (!entry.IsExpired) { + Y_ENSURE(entry.Value.Defined()); + promise.SetValue(std::move(*entry.Value)); + return; + } + + bool isEmpty = entry.Value.Empty(); + if (!isEmpty) { + promise.SetValue(std::move(*entry.Value)); + } + + query(key).Apply([cache, key = std::move(key), isEmpty, promise](auto f) mutable { + TValue value; try { - entry = f.ExtractValue(); + value = f.ExtractValue(); } catch (...) { promise.SetException(std::current_exception()); return; } - if (!entry.IsExpired) { - Y_ENSURE(entry.Value.Defined()); - promise.SetValue(std::move(*entry.Value)); - return; - } - - bool isEmpty = entry.Value.Empty(); - if (!isEmpty) { - promise.SetValue(std::move(*entry.Value)); + if (isEmpty) { + promise.SetValue(value); } - query(key).Apply([cache, key = std::move(key), isEmpty, promise](auto f) mutable { - TValue value; - try { - value = f.ExtractValue(); - } catch (...) { - promise.SetException(std::current_exception()); - return; - } - - if (isEmpty) { - promise.SetValue(value); - } - - cache->Update(key, std::move(value)); - }); + cache->Update(key, std::move(value)); }); - return promise; - } + }); + return promise; + } - private: - ICache<TKey, TValue>::TPtr Cache_; - TFunc Query_; - }; +private: + ICache<TKey, TValue>::TPtr Cache_; + TFunc Query_; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/cache/cached_ut.cpp b/yql/essentials/sql/v1/complete/name/cache/cached_ut.cpp index 912b104d781..a6c5e5d6387 100644 --- a/yql/essentials/sql/v1/complete/name/cache/cached_ut.cpp +++ b/yql/essentials/sql/v1/complete/name/cache/cached_ut.cpp @@ -35,81 +35,81 @@ public: Y_UNIT_TEST_SUITE(CachedQueryTests) { - Y_UNIT_TEST(OnEmpty_WhenGet_ThenWaitUntilReceived) { - auto cache = MakeLocalCache<TString, TString>( - NMonotonic::CreateDefaultMonotonicTimeProvider(), {.TTL = TDuration::Zero()}); - auto cached = TCachedQuery<TString, TString>(cache, [&](const TString& key) { - return NThreading::MakeFuture<TString>(key); - }); - - TString value = cached("1").GetValueSync(); - - UNIT_ASSERT_VALUES_EQUAL(value, "1"); - } - - Y_UNIT_TEST(OnExpired_WhenApplied_ThenDefferedUpdateAndReturnOld) { - size_t queried = 0; - auto cache = MakeLocalCache<TString, TString>( - NMonotonic::CreateDefaultMonotonicTimeProvider(), {.TTL = TDuration::Zero()}); - auto cached = TCachedQuery<TString, TString>(cache, [&](const TString& key) { - queried += 1; - return NThreading::MakeFuture<TString>(key); - }); - cache->Update("1", "2"); - - TString value = cached("1").GetValueSync(); - - UNIT_ASSERT_VALUES_EQUAL(value, "2"); - UNIT_ASSERT_VALUES_EQUAL(queried, 1); - UNIT_ASSERT_VALUES_EQUAL(cached("1").GetValueSync(), "1"); - } - - Y_UNIT_TEST(OnQueryError_WhenApplied_ThenNoDeadlock) { - size_t queried = 0; - auto cache = MakeLocalCache<TString, TString>( - NMonotonic::CreateDefaultMonotonicTimeProvider(), {.TTL = TDuration::Zero()}); - auto cached = TCachedQuery<TString, TString>(cache, [&](const TString&) { - queried += 1; - try { - ythrow yexception() << "T_T"; - } catch (...) { - return NThreading::MakeErrorFuture<TString>(std::current_exception()); - } - }); - - UNIT_ASSERT_EXCEPTION(cached("1").GetValueSync(), yexception); - UNIT_ASSERT_EXCEPTION(cached("1").GetValueSync(), yexception); - UNIT_ASSERT_VALUES_EQUAL(queried, 2); - } - - Y_UNIT_TEST(OnFailingCacheGet_WhenApplied_ThenNoDeadlock) { - size_t queried = 0; - auto cache = MakeIntrusive<TFailableCache>(); - auto cached = TCachedQuery<TString, TString>(cache, [&](const TString& key) { - queried += 1; - return NThreading::MakeFuture<TString>(key); - }); - - cache->IsGetFailing = true; - - UNIT_ASSERT_EXCEPTION(cached("1").GetValueSync(), yexception); - UNIT_ASSERT_VALUES_EQUAL(queried, 0); - } - - Y_UNIT_TEST(OnFailingCacheUpdate_WhenApplied_ThenNoErrorAndNotCached) { - size_t queried = 0; - auto cache = MakeIntrusive<TFailableCache>(); - auto cached = TCachedQuery<TString, TString>(cache, [&](const TString& key) { - queried += 1; - return NThreading::MakeFuture<TString>(key); - }); - - cache->IsExpired = true; - cache->IsUpdateFailing = true; - - UNIT_ASSERT_VALUES_EQUAL(cached("1").GetValueSync(), "1"); - UNIT_ASSERT_VALUES_EQUAL(cached("1").GetValueSync(), "1"); - UNIT_ASSERT_VALUES_EQUAL(queried, 2); - } +Y_UNIT_TEST(OnEmpty_WhenGet_ThenWaitUntilReceived) { + auto cache = MakeLocalCache<TString, TString>( + NMonotonic::CreateDefaultMonotonicTimeProvider(), {.TTL = TDuration::Zero()}); + auto cached = TCachedQuery<TString, TString>(cache, [&](const TString& key) { + return NThreading::MakeFuture<TString>(key); + }); + + TString value = cached("1").GetValueSync(); + + UNIT_ASSERT_VALUES_EQUAL(value, "1"); +} + +Y_UNIT_TEST(OnExpired_WhenApplied_ThenDefferedUpdateAndReturnOld) { + size_t queried = 0; + auto cache = MakeLocalCache<TString, TString>( + NMonotonic::CreateDefaultMonotonicTimeProvider(), {.TTL = TDuration::Zero()}); + auto cached = TCachedQuery<TString, TString>(cache, [&](const TString& key) { + queried += 1; + return NThreading::MakeFuture<TString>(key); + }); + cache->Update("1", "2"); + + TString value = cached("1").GetValueSync(); + + UNIT_ASSERT_VALUES_EQUAL(value, "2"); + UNIT_ASSERT_VALUES_EQUAL(queried, 1); + UNIT_ASSERT_VALUES_EQUAL(cached("1").GetValueSync(), "1"); +} + +Y_UNIT_TEST(OnQueryError_WhenApplied_ThenNoDeadlock) { + size_t queried = 0; + auto cache = MakeLocalCache<TString, TString>( + NMonotonic::CreateDefaultMonotonicTimeProvider(), {.TTL = TDuration::Zero()}); + auto cached = TCachedQuery<TString, TString>(cache, [&](const TString&) { + queried += 1; + try { + ythrow yexception() << "T_T"; + } catch (...) { + return NThreading::MakeErrorFuture<TString>(std::current_exception()); + } + }); + + UNIT_ASSERT_EXCEPTION(cached("1").GetValueSync(), yexception); + UNIT_ASSERT_EXCEPTION(cached("1").GetValueSync(), yexception); + UNIT_ASSERT_VALUES_EQUAL(queried, 2); +} + +Y_UNIT_TEST(OnFailingCacheGet_WhenApplied_ThenNoDeadlock) { + size_t queried = 0; + auto cache = MakeIntrusive<TFailableCache>(); + auto cached = TCachedQuery<TString, TString>(cache, [&](const TString& key) { + queried += 1; + return NThreading::MakeFuture<TString>(key); + }); + + cache->IsGetFailing = true; + + UNIT_ASSERT_EXCEPTION(cached("1").GetValueSync(), yexception); + UNIT_ASSERT_VALUES_EQUAL(queried, 0); +} + +Y_UNIT_TEST(OnFailingCacheUpdate_WhenApplied_ThenNoErrorAndNotCached) { + size_t queried = 0; + auto cache = MakeIntrusive<TFailableCache>(); + auto cached = TCachedQuery<TString, TString>(cache, [&](const TString& key) { + queried += 1; + return NThreading::MakeFuture<TString>(key); + }); + + cache->IsExpired = true; + cache->IsUpdateFailing = true; + + UNIT_ASSERT_VALUES_EQUAL(cached("1").GetValueSync(), "1"); + UNIT_ASSERT_VALUES_EQUAL(cached("1").GetValueSync(), "1"); + UNIT_ASSERT_VALUES_EQUAL(queried, 2); +} } // Y_UNIT_TEST_SUITE(CachedQueryTests) diff --git a/yql/essentials/sql/v1/complete/name/cache/local/cache.h b/yql/essentials/sql/v1/complete/name/cache/local/cache.h index b5149caa608..c65b7492025 100644 --- a/yql/essentials/sql/v1/complete/name/cache/local/cache.h +++ b/yql/essentials/sql/v1/complete/name/cache/local/cache.h @@ -9,105 +9,105 @@ namespace NSQLComplete { - struct TLocalCacheConfig { - size_t ByteCapacity = 1 * 1024 * 1024; - TDuration TTL = TDuration::Seconds(8); +struct TLocalCacheConfig { + size_t ByteCapacity = 1 * 1024 * 1024; + TDuration TTL = TDuration::Seconds(8); +}; + +namespace NPrivate { + +template <CCacheValue TValue> +struct TLocalCacheCell { + TValue Value; + NMonotonic::TMonotonic Deadline; + size_t KeyByteSize = 0; + size_t CellByteSize = 0; +}; + +template <CCacheKey TKey, CCacheValue TValue> +class TLocalCache: public ICache<TKey, TValue> { +private: + using TEntry = ICache<TKey, TValue>::TEntry; + using TCell = TLocalCacheCell<TValue>; + + struct TLRUSizeProvider { + size_t operator()(const TCell& x) noexcept { + const size_t listItemContent = x.CellByteSize; + const size_t listItemPtrs = sizeof(TIntrusiveListItem<void>); + const size_t listItem = listItemContent + listItemPtrs; + + const size_t cacheIndexKey = x.KeyByteSize; + const size_t cacheIndexListItemPtr = sizeof(void*); + const size_t cacheIndexEntry = cacheIndexKey + cacheIndexListItemPtr; + + return listItem + cacheIndexEntry; + } }; - namespace NPrivate { + using TStorage = TLRUCache<TKey, TCell, TNoopDelete, TLRUSizeProvider>; - template <CCacheValue TValue> - struct TLocalCacheCell { - TValue Value; - NMonotonic::TMonotonic Deadline; - size_t KeyByteSize = 0; - size_t CellByteSize = 0; - }; +public: + TLocalCache(TIntrusivePtr<NMonotonic::IMonotonicTimeProvider> clock, TLocalCacheConfig config) + : Clock_(std::move(clock)) + , Config_(std::move(config)) + , Origin_(/* maxSize = */ Config_.ByteCapacity) + { + } - template <CCacheKey TKey, CCacheValue TValue> - class TLocalCache: public ICache<TKey, TValue> { - private: - using TEntry = ICache<TKey, TValue>::TEntry; - using TCell = TLocalCacheCell<TValue>; - - struct TLRUSizeProvider { - size_t operator()(const TCell& x) noexcept { - const size_t listItemContent = x.CellByteSize; - const size_t listItemPtrs = sizeof(TIntrusiveListItem<void>); - const size_t listItem = listItemContent + listItemPtrs; - - const size_t cacheIndexKey = x.KeyByteSize; - const size_t cacheIndexListItemPtr = sizeof(void*); - const size_t cacheIndexEntry = cacheIndexKey + cacheIndexListItemPtr; - - return listItem + cacheIndexEntry; - } - }; - - using TStorage = TLRUCache<TKey, TCell, TNoopDelete, TLRUSizeProvider>; - - public: - TLocalCache(TIntrusivePtr<NMonotonic::IMonotonicTimeProvider> clock, TLocalCacheConfig config) - : Clock_(std::move(clock)) - , Config_(std::move(config)) - , Origin_(/* maxSize = */ Config_.ByteCapacity) - { - } + NThreading::TFuture<TEntry> Get(const TKey& key) const override { + TEntry entry; - NThreading::TFuture<TEntry> Get(const TKey& key) const override { - TEntry entry; + with_lock (Mutex_) { + if (auto it = Origin_.Find(key); it != Origin_.End()) { + entry.Value = it->Value; + entry.IsExpired = (it->Deadline <= Clock_->Now()); + } + } - with_lock (Mutex_) { - if (auto it = Origin_.Find(key); it != Origin_.End()) { - entry.Value = it->Value; - entry.IsExpired = (it->Deadline <= Clock_->Now()); - } - } + return NThreading::MakeFuture(std::move(entry)); + } - return NThreading::MakeFuture(std::move(entry)); - } + NThreading::TFuture<void> Update(const TKey& key, TValue value) const override { + TCell cell = { + .Value = std::move(value), + .Deadline = Clock_->Now() + Config_.TTL, + .KeyByteSize = TByteSize<TKey>()(key), + }; - NThreading::TFuture<void> Update(const TKey& key, TValue value) const override { - TCell cell = { - .Value = std::move(value), - .Deadline = Clock_->Now() + Config_.TTL, - .KeyByteSize = TByteSize<TKey>()(key), - }; + cell.CellByteSize = + TByteSize<TValue>()(cell.Value) + + sizeof(cell.Deadline) + + cell.KeyByteSize; - cell.CellByteSize = - TByteSize<TValue>()(cell.Value) + - sizeof(cell.Deadline) + - cell.KeyByteSize; + with_lock (Mutex_) { + Origin_.Update(key, std::move(cell)); + } - with_lock (Mutex_) { - Origin_.Update(key, std::move(cell)); - } + return NThreading::MakeFuture(); + } - return NThreading::MakeFuture(); - } +private: + TIntrusivePtr<NMonotonic::IMonotonicTimeProvider> Clock_; + TLocalCacheConfig Config_; - private: - TIntrusivePtr<NMonotonic::IMonotonicTimeProvider> Clock_; - TLocalCacheConfig Config_; + TMutex Mutex_; + mutable TStorage Origin_; +}; - TMutex Mutex_; - mutable TStorage Origin_; - }; +} // namespace NPrivate - } // namespace NPrivate +template <NPrivate::CCacheKey TKey, NPrivate::CCacheValue TValue> +ICache<TKey, TValue>::TPtr MakeLocalCache( + TIntrusivePtr<NMonotonic::IMonotonicTimeProvider> clock, + TLocalCacheConfig config) { + return new NPrivate::TLocalCache<TKey, TValue>(std::move(clock), std::move(config)); +} - template <NPrivate::CCacheKey TKey, NPrivate::CCacheValue TValue> - ICache<TKey, TValue>::TPtr MakeLocalCache( - TIntrusivePtr<NMonotonic::IMonotonicTimeProvider> clock, - TLocalCacheConfig config) { - return new NPrivate::TLocalCache<TKey, TValue>(std::move(clock), std::move(config)); +template <NPrivate::CCacheValue TValue> +struct TByteSize<NPrivate::TLocalCacheCell<TValue>> { + size_t operator()(const NPrivate::TLocalCacheCell<TValue>& x) const noexcept { + return x.CellByteSize; } - - template <NPrivate::CCacheValue TValue> - struct TByteSize<NPrivate::TLocalCacheCell<TValue>> { - size_t operator()(const NPrivate::TLocalCacheCell<TValue>& x) const noexcept { - return x.CellByteSize; - } - }; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/cache/local/cache_ut.cpp b/yql/essentials/sql/v1/complete/name/cache/local/cache_ut.cpp index c518dadf271..589d1d0d2b2 100644 --- a/yql/essentials/sql/v1/complete/name/cache/local/cache_ut.cpp +++ b/yql/essentials/sql/v1/complete/name/cache/local/cache_ut.cpp @@ -31,12 +31,12 @@ struct TFat { namespace NSQLComplete { - template <> - struct TByteSize<TFat> { - size_t operator()(const TFat&) const noexcept { - return 10'000; - } - }; +template <> +struct TByteSize<TFat> { + size_t operator()(const TFat&) const noexcept { + return 10'000; + } +}; } // namespace NSQLComplete @@ -74,143 +74,143 @@ TIntrusivePtr<TPausedClock> MakePausedClock() { Y_UNIT_TEST_SUITE(LocalCacheTests) { - Y_UNIT_TEST(OnEmpty_WhenGet_ThenReturnedExpiredDefault) { - auto cache = MakeLocalCache<TString, TString>( - NMonotonic::CreateDefaultMonotonicTimeProvider(), {}); +Y_UNIT_TEST(OnEmpty_WhenGet_ThenReturnedExpiredDefault) { + auto cache = MakeLocalCache<TString, TString>( + NMonotonic::CreateDefaultMonotonicTimeProvider(), {}); - auto entry = cache->Get("1").GetValueSync(); + auto entry = cache->Get("1").GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(entry.Value, Nothing()); - UNIT_ASSERT_VALUES_EQUAL(entry.IsExpired, true); - } + UNIT_ASSERT_VALUES_EQUAL(entry.Value, Nothing()); + UNIT_ASSERT_VALUES_EQUAL(entry.IsExpired, true); +} - Y_UNIT_TEST(OnEmpty_WhenUpdate_ThenReturnedNew) { - auto cache = MakeLocalCache<TString, TString>( - NMonotonic::CreateDefaultMonotonicTimeProvider(), {}); +Y_UNIT_TEST(OnEmpty_WhenUpdate_ThenReturnedNew) { + auto cache = MakeLocalCache<TString, TString>( + NMonotonic::CreateDefaultMonotonicTimeProvider(), {}); - cache->Update("1", "1").GetValueSync(); + cache->Update("1", "1").GetValueSync(); - auto entry = cache->Get("1").GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(entry.Value, "1"); - UNIT_ASSERT_VALUES_EQUAL(entry.IsExpired, false); - } + auto entry = cache->Get("1").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(entry.Value, "1"); + UNIT_ASSERT_VALUES_EQUAL(entry.IsExpired, false); +} - Y_UNIT_TEST(OnExistingKey_WhenUpdate_ThenReturnedNew) { - auto cache = MakeLocalCache<TString, TString>( - NMonotonic::CreateDefaultMonotonicTimeProvider(), {}); - cache->Update("1", "1"); +Y_UNIT_TEST(OnExistingKey_WhenUpdate_ThenReturnedNew) { + auto cache = MakeLocalCache<TString, TString>( + NMonotonic::CreateDefaultMonotonicTimeProvider(), {}); + cache->Update("1", "1"); - cache->Update("1", "2").GetValueSync(); + cache->Update("1", "2").GetValueSync(); - auto entry = cache->Get("1").GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(entry.Value, "2"); - UNIT_ASSERT_VALUES_EQUAL(entry.IsExpired, false); - } + auto entry = cache->Get("1").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(entry.Value, "2"); + UNIT_ASSERT_VALUES_EQUAL(entry.IsExpired, false); +} - Y_UNIT_TEST(OnExistingKey_WhenExpires_ThenReturnedOld) { - auto clock = MakePausedClock(); - auto cache = MakeLocalCache<TString, TString>(clock, {.TTL = TDuration::Minutes(2)}); - cache->Update("1", "1"); +Y_UNIT_TEST(OnExistingKey_WhenExpires_ThenReturnedOld) { + auto clock = MakePausedClock(); + auto cache = MakeLocalCache<TString, TString>(clock, {.TTL = TDuration::Minutes(2)}); + cache->Update("1", "1"); - clock->Skip(TDuration::Minutes(2) + TDuration::Seconds(1)); + clock->Skip(TDuration::Minutes(2) + TDuration::Seconds(1)); - auto entry = cache->Get("1").GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(entry.Value, "1"); - UNIT_ASSERT_VALUES_EQUAL(entry.IsExpired, true); - } + auto entry = cache->Get("1").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(entry.Value, "1"); + UNIT_ASSERT_VALUES_EQUAL(entry.IsExpired, true); +} - Y_UNIT_TEST(OnExistingKey_WhenGetResultExtracted_ThenItIsCopied) { - auto cache = MakeLocalCache<TString, TString>( - NMonotonic::CreateDefaultMonotonicTimeProvider(), {}); - cache->Update("1", TString(128, '1')); +Y_UNIT_TEST(OnExistingKey_WhenGetResultExtracted_ThenItIsCopied) { + auto cache = MakeLocalCache<TString, TString>( + NMonotonic::CreateDefaultMonotonicTimeProvider(), {}); + cache->Update("1", TString(128, '1')); - cache->Get("1").ExtractValueSync(); + cache->Get("1").ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(cache->Get("1").ExtractValueSync().Value, TString(128, '1')); - UNIT_ASSERT_VALUES_EQUAL(cache->Get("1").ExtractValueSync().Value, TString(128, '1')); - } + UNIT_ASSERT_VALUES_EQUAL(cache->Get("1").ExtractValueSync().Value, TString(128, '1')); + UNIT_ASSERT_VALUES_EQUAL(cache->Get("1").ExtractValueSync().Value, TString(128, '1')); +} - Y_UNIT_TEST(OnFull_WhenFatAdded_ThenSomeKeyIsEvicted) { - const size_t Overhead = TByteSize<TFat>()({}) / 10; +Y_UNIT_TEST(OnFull_WhenFatAdded_ThenSomeKeyIsEvicted) { + const size_t Overhead = TByteSize<TFat>()({}) / 10; - auto cache = MakeLocalCache<int, TFat>( - NMonotonic::CreateDefaultMonotonicTimeProvider(), - {.ByteCapacity = 4 * TByteSize<TFat>()({}) + Overhead}); - cache->Update(1, {}); - cache->Update(2, {}); - cache->Update(3, {}); - cache->Update(4, {}); + auto cache = MakeLocalCache<int, TFat>( + NMonotonic::CreateDefaultMonotonicTimeProvider(), + {.ByteCapacity = 4 * TByteSize<TFat>()({}) + Overhead}); + cache->Update(1, {}); + cache->Update(2, {}); + cache->Update(3, {}); + cache->Update(4, {}); - cache->Update(5, {}); + cache->Update(5, {}); - size_t evicted = 0; - for (auto x : {1, 2, 3, 4, 5}) { - if (cache->Get(x).GetValueSync().IsExpired) { - evicted += 1; - } + size_t evicted = 0; + for (auto x : {1, 2, 3, 4, 5}) { + if (cache->Get(x).GetValueSync().IsExpired) { + evicted += 1; } - - UNIT_ASSERT_VALUES_EQUAL(evicted, 1); } - Y_UNIT_TEST(OnFull_WhenFatAdded_ThenKeyAndOverheadAreAccounted) { - const size_t Overhead = TByteSize<TFat>()({}) / 10; + UNIT_ASSERT_VALUES_EQUAL(evicted, 1); +} - auto cache = MakeLocalCache<TFat, TFat>( - NMonotonic::CreateDefaultMonotonicTimeProvider(), - {.ByteCapacity = 3 * 4 * TByteSize<TFat>()({}) + Overhead}); - cache->Update(TFat{1}, {}); - cache->Update(TFat{2}, {}); - cache->Update(TFat{3}, {}); - cache->Update(TFat{4}, {}); +Y_UNIT_TEST(OnFull_WhenFatAdded_ThenKeyAndOverheadAreAccounted) { + const size_t Overhead = TByteSize<TFat>()({}) / 10; - cache->Update(TFat{5}, {}); + auto cache = MakeLocalCache<TFat, TFat>( + NMonotonic::CreateDefaultMonotonicTimeProvider(), + {.ByteCapacity = 3 * 4 * TByteSize<TFat>()({}) + Overhead}); + cache->Update(TFat{1}, {}); + cache->Update(TFat{2}, {}); + cache->Update(TFat{3}, {}); + cache->Update(TFat{4}, {}); - size_t evicted = 0; - for (auto x : {TFat{1}, TFat{2}, TFat{3}, TFat{4}, TFat{5}}) { - if (cache->Get(x).GetValueSync().IsExpired) { - evicted += 1; - } + cache->Update(TFat{5}, {}); + + size_t evicted = 0; + for (auto x : {TFat{1}, TFat{2}, TFat{3}, TFat{4}, TFat{5}}) { + if (cache->Get(x).GetValueSync().IsExpired) { + evicted += 1; } + } + + UNIT_ASSERT_VALUES_EQUAL(evicted, 1); +} + +Y_UNIT_TEST(WhenRandomlyAccessed_ThenDoesNotDie) { + constexpr size_t Iterations = 1024 * 1024; + SetRandomSeed(1); + + auto cache = MakeLocalCache<TString, TString>( + NMonotonic::CreateDefaultMonotonicTimeProvider(), {.ByteCapacity = 64, .TTL = TDuration::MilliSeconds(1)}); - UNIT_ASSERT_VALUES_EQUAL(evicted, 1); + for (auto&& a : GenerateRandomActions(Iterations)) { + if (a.IsGet) { + Y_DO_NOT_OPTIMIZE_AWAY(cache->Get(a.Key)); + } else { + Y_DO_NOT_OPTIMIZE_AWAY(cache->Update(a.Key, std::move(a.Value))); + } } +} - Y_UNIT_TEST(WhenRandomlyAccessed_ThenDoesNotDie) { - constexpr size_t Iterations = 1024 * 1024; - SetRandomSeed(1); +Y_UNIT_TEST(WhenConcurrentlyAccessed_ThenDoesNotDie) { + constexpr size_t Threads = 8; + constexpr size_t Iterations = Threads * 16 * 1024; + SetRandomSeed(1); - auto cache = MakeLocalCache<TString, TString>( - NMonotonic::CreateDefaultMonotonicTimeProvider(), {.ByteCapacity = 64, .TTL = TDuration::MilliSeconds(1)}); + auto cache = MakeLocalCache<TString, TString>( + NMonotonic::CreateDefaultMonotonicTimeProvider(), {.ByteCapacity = 64, .TTL = TDuration::MilliSeconds(1)}); - for (auto&& a : GenerateRandomActions(Iterations)) { + auto pool = CreateThreadPool(Threads); + for (auto&& a : GenerateRandomActions(Iterations)) { + Y_ENSURE(pool->AddFunc([cache, a = std::move(a)] { if (a.IsGet) { Y_DO_NOT_OPTIMIZE_AWAY(cache->Get(a.Key)); } else { Y_DO_NOT_OPTIMIZE_AWAY(cache->Update(a.Key, std::move(a.Value))); } - } - } - - Y_UNIT_TEST(WhenConcurrentlyAccessed_ThenDoesNotDie) { - constexpr size_t Threads = 8; - constexpr size_t Iterations = Threads * 16 * 1024; - SetRandomSeed(1); - - auto cache = MakeLocalCache<TString, TString>( - NMonotonic::CreateDefaultMonotonicTimeProvider(), {.ByteCapacity = 64, .TTL = TDuration::MilliSeconds(1)}); - - auto pool = CreateThreadPool(Threads); - for (auto&& a : GenerateRandomActions(Iterations)) { - Y_ENSURE(pool->AddFunc([cache, a = std::move(a)] { - if (a.IsGet) { - Y_DO_NOT_OPTIMIZE_AWAY(cache->Get(a.Key)); - } else { - Y_DO_NOT_OPTIMIZE_AWAY(cache->Update(a.Key, std::move(a.Value))); - } - })); - } - pool->Stop(); + })); } + pool->Stop(); +} } // Y_UNIT_TEST_SUITE(LocalCacheTests) diff --git a/yql/essentials/sql/v1/complete/name/cluster/discovery.h b/yql/essentials/sql/v1/complete/name/cluster/discovery.h index 90592793ea7..14a464cf60c 100644 --- a/yql/essentials/sql/v1/complete/name/cluster/discovery.h +++ b/yql/essentials/sql/v1/complete/name/cluster/discovery.h @@ -6,14 +6,14 @@ namespace NSQLComplete { - using TClusterList = TVector<TString>; +using TClusterList = TVector<TString>; - class IClusterDiscovery: public TThrRefBase { - public: - using TPtr = TIntrusivePtr<IClusterDiscovery>; +class IClusterDiscovery: public TThrRefBase { +public: + using TPtr = TIntrusivePtr<IClusterDiscovery>; - ~IClusterDiscovery() override = default; - virtual NThreading::TFuture<TClusterList> Query() const = 0; - }; + ~IClusterDiscovery() override = default; + virtual NThreading::TFuture<TClusterList> Query() const = 0; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/cluster/static/discovery.cpp b/yql/essentials/sql/v1/complete/name/cluster/static/discovery.cpp index 7caee64c182..29fa148303b 100644 --- a/yql/essentials/sql/v1/complete/name/cluster/static/discovery.cpp +++ b/yql/essentials/sql/v1/complete/name/cluster/static/discovery.cpp @@ -2,27 +2,27 @@ namespace NSQLComplete { - namespace { +namespace { - class TClusterDiscovery: public IClusterDiscovery { - public: - explicit TClusterDiscovery(TVector<TString> instances) - : ClusterList_(std::move(instances)) - { - } +class TClusterDiscovery: public IClusterDiscovery { +public: + explicit TClusterDiscovery(TVector<TString> instances) + : ClusterList_(std::move(instances)) + { + } - NThreading::TFuture<TClusterList> Query() const override { - return NThreading::MakeFuture(ClusterList_); - } + NThreading::TFuture<TClusterList> Query() const override { + return NThreading::MakeFuture(ClusterList_); + } - private: - TVector<TString> ClusterList_; - }; +private: + TVector<TString> ClusterList_; +}; - } // namespace +} // namespace - IClusterDiscovery::TPtr MakeStaticClusterDiscovery(TVector<TString> instances) { - return new TClusterDiscovery(std::move(instances)); - } +IClusterDiscovery::TPtr MakeStaticClusterDiscovery(TVector<TString> instances) { + return new TClusterDiscovery(std::move(instances)); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/cluster/static/discovery.h b/yql/essentials/sql/v1/complete/name/cluster/static/discovery.h index bfad0eed62f..2989cd6f6f7 100644 --- a/yql/essentials/sql/v1/complete/name/cluster/static/discovery.h +++ b/yql/essentials/sql/v1/complete/name/cluster/static/discovery.h @@ -4,6 +4,6 @@ namespace NSQLComplete { - IClusterDiscovery::TPtr MakeStaticClusterDiscovery(TVector<TString> instances); +IClusterDiscovery::TPtr MakeStaticClusterDiscovery(TVector<TString> instances); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/schema.cpp b/yql/essentials/sql/v1/complete/name/object/schema.cpp index 86c2a0f36a6..d31565e1cee 100644 --- a/yql/essentials/sql/v1/complete/name/object/schema.cpp +++ b/yql/essentials/sql/v1/complete/name/object/schema.cpp @@ -2,10 +2,10 @@ namespace NSQLComplete { - THashSet<TString> TFolderEntry::KnownTypes = { - TFolderEntry::Folder, - TFolderEntry::Table, - }; +THashSet<TString> TFolderEntry::KnownTypes = { + TFolderEntry::Folder, + TFolderEntry::Table, +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/schema.h b/yql/essentials/sql/v1/complete/name/object/schema.h index e3af2df024d..4bcabff8efa 100644 --- a/yql/essentials/sql/v1/complete/name/object/schema.h +++ b/yql/essentials/sql/v1/complete/name/object/schema.h @@ -9,61 +9,61 @@ namespace NSQLComplete { - struct TFolderEntry { - static constexpr const char* Folder = "Folder"; - static constexpr const char* Table = "Table"; - - static THashSet<TString> KnownTypes; - - TString Type; - TString Name; - - friend bool operator==(const TFolderEntry& lhs, const TFolderEntry& rhs) = default; - }; - - struct TListFilter { - TMaybe<THashSet<TString>> Types; - bool IsUnknownAllowed = false; - }; - - struct TListRequest { - TString Cluster; - - // `Path` structure is defined by a `System`. - // Can end with a folder entry name hint. - // For example, `/local/exa` lists a folder `/local`, - // but can rank and filter entries by a hint `exa`. - TString Path; - - TListFilter Filter; - size_t Limit = 128; - }; - - struct TListResponse { - size_t NameHintLength = 0; - TVector<TFolderEntry> Entries; - }; - - struct TDescribeTableRequest { - TString TableCluster; - TString TablePath; - TString ColumnPrefix; - size_t ColumnsLimit = 128; // TODO: introduce default limit constant - }; - - struct TDescribeTableResponse { - bool IsExisting = false; - TVector<TString> Columns; - }; - - class ISchema: public TThrRefBase { - public: - using TPtr = TIntrusivePtr<ISchema>; - - virtual NThreading::TFuture<TListResponse> List(const TListRequest& request) const = 0; - - virtual NThreading::TFuture<TDescribeTableResponse> - Describe(const TDescribeTableRequest& request) const = 0; - }; +struct TFolderEntry { + static constexpr const char* Folder = "Folder"; + static constexpr const char* Table = "Table"; + + static THashSet<TString> KnownTypes; + + TString Type; + TString Name; + + friend bool operator==(const TFolderEntry& lhs, const TFolderEntry& rhs) = default; +}; + +struct TListFilter { + TMaybe<THashSet<TString>> Types; + bool IsUnknownAllowed = false; +}; + +struct TListRequest { + TString Cluster; + + // `Path` structure is defined by a `System`. + // Can end with a folder entry name hint. + // For example, `/local/exa` lists a folder `/local`, + // but can rank and filter entries by a hint `exa`. + TString Path; + + TListFilter Filter; + size_t Limit = 128; +}; + +struct TListResponse { + size_t NameHintLength = 0; + TVector<TFolderEntry> Entries; +}; + +struct TDescribeTableRequest { + TString TableCluster; + TString TablePath; + TString ColumnPrefix; + size_t ColumnsLimit = 128; // TODO: introduce default limit constant +}; + +struct TDescribeTableResponse { + bool IsExisting = false; + TVector<TString> Columns; +}; + +class ISchema: public TThrRefBase { +public: + using TPtr = TIntrusivePtr<ISchema>; + + virtual NThreading::TFuture<TListResponse> List(const TListRequest& request) const = 0; + + virtual NThreading::TFuture<TDescribeTableResponse> + Describe(const TDescribeTableRequest& request) const = 0; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/simple/cached/key.h b/yql/essentials/sql/v1/complete/name/object/simple/cached/key.h index 79c6736042d..aab55247a84 100644 --- a/yql/essentials/sql/v1/complete/name/object/simple/cached/key.h +++ b/yql/essentials/sql/v1/complete/name/object/simple/cached/key.h @@ -8,41 +8,41 @@ namespace NSQLComplete { - struct TSchemaDescribeCacheKey { - TString Zone; - TString Cluster; - TString Path; - - friend bool operator==( - const TSchemaDescribeCacheKey& lhs, - const TSchemaDescribeCacheKey& rhs) = default; - }; - - template <> - struct TByteSize<TSchemaDescribeCacheKey> { - size_t operator()(const TSchemaDescribeCacheKey& x) const noexcept { - return sizeof(x) + - TByteSize<TString>()(x.Zone) + - TByteSize<TString>()(x.Cluster) + - TByteSize<TString>()(x.Path); - } - }; - - template <> - struct TByteSize<TFolderEntry> { - size_t operator()(const TFolderEntry& x) const noexcept { - return sizeof(x) + - TByteSize<TString>()(x.Type) + - TByteSize<TString>()(x.Name); - } - }; - - template <> - struct TByteSize<TTableDetails> { - size_t operator()(const TTableDetails& x) const noexcept { - return TByteSize<TVector<TString>>()(x.Columns); - } - }; +struct TSchemaDescribeCacheKey { + TString Zone; + TString Cluster; + TString Path; + + friend bool operator==( + const TSchemaDescribeCacheKey& lhs, + const TSchemaDescribeCacheKey& rhs) = default; +}; + +template <> +struct TByteSize<TSchemaDescribeCacheKey> { + size_t operator()(const TSchemaDescribeCacheKey& x) const noexcept { + return sizeof(x) + + TByteSize<TString>()(x.Zone) + + TByteSize<TString>()(x.Cluster) + + TByteSize<TString>()(x.Path); + } +}; + +template <> +struct TByteSize<TFolderEntry> { + size_t operator()(const TFolderEntry& x) const noexcept { + return sizeof(x) + + TByteSize<TString>()(x.Type) + + TByteSize<TString>()(x.Name); + } +}; + +template <> +struct TByteSize<TTableDetails> { + size_t operator()(const TTableDetails& x) const noexcept { + return TByteSize<TVector<TString>>()(x.Columns); + } +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/simple/cached/schema.cpp b/yql/essentials/sql/v1/complete/name/object/simple/cached/schema.cpp index 77abd97c576..47f567c1180 100644 --- a/yql/essentials/sql/v1/complete/name/object/simple/cached/schema.cpp +++ b/yql/essentials/sql/v1/complete/name/object/simple/cached/schema.cpp @@ -4,63 +4,63 @@ namespace NSQLComplete { - namespace { +namespace { - class TSimpleSchema: public ISimpleSchema { - public: - TSimpleSchema( - TSchemaCaches caches, - TString Zone, - ISimpleSchema::TPtr Origin) - : Zone_(std::move(Zone)) - , Origin_(std::move(Origin)) - , QueryList_(std::move(caches.List), [origin = Origin_](const TSchemaDescribeCacheKey& key) { - return origin->List(key.Cluster, key.Path); - }) - , QueryDescribeTable_(std::move(caches.DescribeTable), [origin = Origin_](const TSchemaDescribeCacheKey& key) { - return origin->DescribeTable(key.Cluster, key.Path); - }) - { - } +class TSimpleSchema: public ISimpleSchema { +public: + TSimpleSchema( + TSchemaCaches caches, + TString Zone, + ISimpleSchema::TPtr Origin) + : Zone_(std::move(Zone)) + , Origin_(std::move(Origin)) + , QueryList_(std::move(caches.List), [origin = Origin_](const TSchemaDescribeCacheKey& key) { + return origin->List(key.Cluster, key.Path); + }) + , QueryDescribeTable_(std::move(caches.DescribeTable), [origin = Origin_](const TSchemaDescribeCacheKey& key) { + return origin->DescribeTable(key.Cluster, key.Path); + }) + { + } - TSplittedPath Split(TStringBuf path) const override { - return Origin_->Split(path); - } + TSplittedPath Split(TStringBuf path) const override { + return Origin_->Split(path); + } - NThreading::TFuture<TVector<TFolderEntry>> - List(TString cluster, TString folder) const override { - return QueryList_({ - .Zone = Zone_, - .Cluster = std::move(cluster), - .Path = std::move(folder), - }); - } + NThreading::TFuture<TVector<TFolderEntry>> + List(TString cluster, TString folder) const override { + return QueryList_({ + .Zone = Zone_, + .Cluster = std::move(cluster), + .Path = std::move(folder), + }); + } - NThreading::TFuture<TMaybe<TTableDetails>> - DescribeTable(const TString& cluster, const TString& path) const override { - return QueryDescribeTable_({ - .Zone = Zone_, - .Cluster = cluster, - .Path = path, - }); - } + NThreading::TFuture<TMaybe<TTableDetails>> + DescribeTable(const TString& cluster, const TString& path) const override { + return QueryDescribeTable_({ + .Zone = Zone_, + .Cluster = cluster, + .Path = path, + }); + } - private: - TString Zone_; - ISimpleSchema::TPtr Origin_; - TCachedQuery<TSchemaDescribeCacheKey, TVector<TFolderEntry>> QueryList_; - TCachedQuery<TSchemaDescribeCacheKey, TMaybe<TTableDetails>> QueryDescribeTable_; - }; +private: + TString Zone_; + ISimpleSchema::TPtr Origin_; + TCachedQuery<TSchemaDescribeCacheKey, TVector<TFolderEntry>> QueryList_; + TCachedQuery<TSchemaDescribeCacheKey, TMaybe<TTableDetails>> QueryDescribeTable_; +}; - } // namespace +} // namespace - ISimpleSchema::TPtr MakeCachedSimpleSchema( - ISchemaListCache::TPtr cache, TString zone, ISimpleSchema::TPtr origin) { - return new TSimpleSchema({.List = std::move(cache)}, std::move(zone), std::move(origin)); - } +ISimpleSchema::TPtr MakeCachedSimpleSchema( + ISchemaListCache::TPtr cache, TString zone, ISimpleSchema::TPtr origin) { + return new TSimpleSchema({.List = std::move(cache)}, std::move(zone), std::move(origin)); +} - ISimpleSchema::TPtr MakeCachedSimpleSchema(TSchemaCaches caches, TString zone, ISimpleSchema::TPtr origin) { - return new TSimpleSchema(std::move(caches), std::move(zone), std::move(origin)); - } +ISimpleSchema::TPtr MakeCachedSimpleSchema(TSchemaCaches caches, TString zone, ISimpleSchema::TPtr origin) { + return new TSimpleSchema(std::move(caches), std::move(zone), std::move(origin)); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/simple/cached/schema.h b/yql/essentials/sql/v1/complete/name/object/simple/cached/schema.h index 4ad428f3cf4..6181143b086 100644 --- a/yql/essentials/sql/v1/complete/name/object/simple/cached/schema.h +++ b/yql/essentials/sql/v1/complete/name/object/simple/cached/schema.h @@ -8,19 +8,19 @@ namespace NSQLComplete { - using ISchemaListCache = ICache<TSchemaDescribeCacheKey, TVector<TFolderEntry>>; - using ISchemaDescribeTableCache = ICache<TSchemaDescribeCacheKey, TMaybe<TTableDetails>>; +using ISchemaListCache = ICache<TSchemaDescribeCacheKey, TVector<TFolderEntry>>; +using ISchemaDescribeTableCache = ICache<TSchemaDescribeCacheKey, TMaybe<TTableDetails>>; - struct TSchemaCaches { - ISchemaListCache::TPtr List; - ISchemaDescribeTableCache::TPtr DescribeTable; - }; +struct TSchemaCaches { + ISchemaListCache::TPtr List; + ISchemaDescribeTableCache::TPtr DescribeTable; +}; - // TODO(YQL-19747): deprecated, migrate YDB CLI - ISimpleSchema::TPtr MakeCachedSimpleSchema( - ISchemaListCache::TPtr cache, TString zone, ISimpleSchema::TPtr origin); +// TODO(YQL-19747): deprecated, migrate YDB CLI +ISimpleSchema::TPtr MakeCachedSimpleSchema( + ISchemaListCache::TPtr cache, TString zone, ISimpleSchema::TPtr origin); - ISimpleSchema::TPtr MakeCachedSimpleSchema( - TSchemaCaches caches, TString zone, ISimpleSchema::TPtr origin); +ISimpleSchema::TPtr MakeCachedSimpleSchema( + TSchemaCaches caches, TString zone, ISimpleSchema::TPtr origin); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/simple/schema.cpp b/yql/essentials/sql/v1/complete/name/object/simple/schema.cpp index e13d1c0cfcb..f86036ebfca 100644 --- a/yql/essentials/sql/v1/complete/name/object/simple/schema.cpp +++ b/yql/essentials/sql/v1/complete/name/object/simple/schema.cpp @@ -6,134 +6,134 @@ namespace NSQLComplete { - namespace { - - class TSimpleSchema: public ISchema { - private: - static auto FilterEntriesByName(TString name) { - return [name = std::move(name)](auto f) { - TVector<TFolderEntry> entries = f.ExtractValue(); - EraseIf(entries, [prefix = TCaseInsensitiveStringBuf(name)](const TFolderEntry& entry) { - return !TCaseInsensitiveStringBuf(entry.Name).StartsWith(prefix); - }); - return entries; - }; - } - - static auto FilterEntriesByTypes(const TListFilter& filter) { - return [filter](auto f) mutable { - TVector<TFolderEntry> entries = f.ExtractValue(); - EraseIf(entries, [filter = std::move(filter)](const TFolderEntry& entry) { - const bool isKnownType = TFolderEntry::KnownTypes.contains(entry.Type); - return ( - (isKnownType && - filter.Types && - !filter.Types->contains(entry.Type)) || - (!isKnownType && - !filter.IsUnknownAllowed)); - }); - return entries; - }; - } - - static auto CropEntries(size_t limit) { - return [limit](auto f) { - TVector<TFolderEntry> entries = f.ExtractValue(); - entries.crop(limit); - return entries; - }; - } - - static auto ToListResponse(TStringBuf name) { - const auto length = name.length(); - return [length](auto f) { - return TListResponse{ - .NameHintLength = length, - .Entries = f.ExtractValue(), - }; - }; - } - - static auto FilterColumnsByName(TString name) { - return [name = std::move(name)](auto f) { - return f.ExtractValue().Transform([&](auto&& table) { - EraseIf(table.Columns, [prefix = TCaseInsensitiveStringBuf(name)](const TString& name) { - return !TCaseInsensitiveStringBuf(name).StartsWith(prefix); - }); - return table; - }); - }; - } - - static auto CropColumns(size_t limit) { - return [limit](auto f) { - return f.ExtractValue().Transform([&](auto&& table) { - table.Columns.crop(limit); - return table; - }); - }; - } - - static auto ToTableDescribeResponse() { - return [](auto f) { - TMaybe<TTableDetails> table = f.ExtractValue(); - return TDescribeTableResponse{ - .IsExisting = table.Defined(), - .Columns = table - .Transform([](auto&& table) { return table.Columns; }) - .GetOrElse({}), - }; - }; - } - - public: - explicit TSimpleSchema(ISimpleSchema::TPtr simple) - : Simple_(std::move(simple)) - { - } - - NThreading::TFuture<TListResponse> List(const TListRequest& request) const override { - auto [path, name] = Simple_->Split(request.Path); - return Simple_->List(request.Cluster, TString(path)) - .Apply(FilterEntriesByName(TString(name))) - .Apply(FilterEntriesByTypes(request.Filter)) - .Apply(CropEntries(request.Limit)) - .Apply(ToListResponse(name)); - } - - NThreading::TFuture<TDescribeTableResponse> - Describe(const TDescribeTableRequest& request) const override { - return Simple_ - ->DescribeTable(request.TableCluster, request.TablePath) - .Apply(FilterColumnsByName(TString(request.ColumnPrefix))) - .Apply(CropColumns(request.ColumnsLimit)) - .Apply(ToTableDescribeResponse()); - } - - private: - ISimpleSchema::TPtr Simple_; +namespace { + +class TSimpleSchema: public ISchema { +private: + static auto FilterEntriesByName(TString name) { + return [name = std::move(name)](auto f) { + TVector<TFolderEntry> entries = f.ExtractValue(); + EraseIf(entries, [prefix = TCaseInsensitiveStringBuf(name)](const TFolderEntry& entry) { + return !TCaseInsensitiveStringBuf(entry.Name).StartsWith(prefix); + }); + return entries; }; + } + + static auto FilterEntriesByTypes(const TListFilter& filter) { + return [filter](auto f) mutable { + TVector<TFolderEntry> entries = f.ExtractValue(); + EraseIf(entries, [filter = std::move(filter)](const TFolderEntry& entry) { + const bool isKnownType = TFolderEntry::KnownTypes.contains(entry.Type); + return ( + (isKnownType && + filter.Types && + !filter.Types->contains(entry.Type)) || + (!isKnownType && + !filter.IsUnknownAllowed)); + }); + return entries; + }; + } + + static auto CropEntries(size_t limit) { + return [limit](auto f) { + TVector<TFolderEntry> entries = f.ExtractValue(); + entries.crop(limit); + return entries; + }; + } + + static auto ToListResponse(TStringBuf name) { + const auto length = name.length(); + return [length](auto f) { + return TListResponse{ + .NameHintLength = length, + .Entries = f.ExtractValue(), + }; + }; + } + + static auto FilterColumnsByName(TString name) { + return [name = std::move(name)](auto f) { + return f.ExtractValue().Transform([&](auto&& table) { + EraseIf(table.Columns, [prefix = TCaseInsensitiveStringBuf(name)](const TString& name) { + return !TCaseInsensitiveStringBuf(name).StartsWith(prefix); + }); + return table; + }); + }; + } - } // namespace + static auto CropColumns(size_t limit) { + return [limit](auto f) { + return f.ExtractValue().Transform([&](auto&& table) { + table.Columns.crop(limit); + return table; + }); + }; + } - NThreading::TFuture<TVector<TFolderEntry>> - ISimpleSchema::List(TString folder) const { - return List(/* cluster = */ "", std::move(folder)); + static auto ToTableDescribeResponse() { + return [](auto f) { + TMaybe<TTableDetails> table = f.ExtractValue(); + return TDescribeTableResponse{ + .IsExisting = table.Defined(), + .Columns = table + .Transform([](auto&& table) { return table.Columns; }) + .GetOrElse({}), + }; + }; } - NThreading::TFuture<TVector<TFolderEntry>> - ISimpleSchema::List(TString /* cluster */, TString folder) const { - return List(std::move(folder)); +public: + explicit TSimpleSchema(ISimpleSchema::TPtr simple) + : Simple_(std::move(simple)) + { } - NThreading::TFuture<TMaybe<TTableDetails>> - ISimpleSchema::DescribeTable(const TString& cluster, const TString& path) const { - Y_UNUSED(cluster, path); - return NThreading::MakeFuture<TMaybe<TTableDetails>>(Nothing()); + NThreading::TFuture<TListResponse> List(const TListRequest& request) const override { + auto [path, name] = Simple_->Split(request.Path); + return Simple_->List(request.Cluster, TString(path)) + .Apply(FilterEntriesByName(TString(name))) + .Apply(FilterEntriesByTypes(request.Filter)) + .Apply(CropEntries(request.Limit)) + .Apply(ToListResponse(name)); } - ISchema::TPtr MakeSimpleSchema(ISimpleSchema::TPtr simple) { - return ISchema::TPtr(new TSimpleSchema(std::move(simple))); + NThreading::TFuture<TDescribeTableResponse> + Describe(const TDescribeTableRequest& request) const override { + return Simple_ + ->DescribeTable(request.TableCluster, request.TablePath) + .Apply(FilterColumnsByName(TString(request.ColumnPrefix))) + .Apply(CropColumns(request.ColumnsLimit)) + .Apply(ToTableDescribeResponse()); } +private: + ISimpleSchema::TPtr Simple_; +}; + +} // namespace + +NThreading::TFuture<TVector<TFolderEntry>> +ISimpleSchema::List(TString folder) const { + return List(/* cluster = */ "", std::move(folder)); +} + +NThreading::TFuture<TVector<TFolderEntry>> +ISimpleSchema::List(TString /* cluster */, TString folder) const { + return List(std::move(folder)); +} + +NThreading::TFuture<TMaybe<TTableDetails>> +ISimpleSchema::DescribeTable(const TString& cluster, const TString& path) const { + Y_UNUSED(cluster, path); + return NThreading::MakeFuture<TMaybe<TTableDetails>>(Nothing()); +} + +ISchema::TPtr MakeSimpleSchema(ISimpleSchema::TPtr simple) { + return ISchema::TPtr(new TSimpleSchema(std::move(simple))); +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/simple/schema.h b/yql/essentials/sql/v1/complete/name/object/simple/schema.h index 2bdb428b191..e6024035107 100644 --- a/yql/essentials/sql/v1/complete/name/object/simple/schema.h +++ b/yql/essentials/sql/v1/complete/name/object/simple/schema.h @@ -4,33 +4,33 @@ namespace NSQLComplete { - struct TSplittedPath { - TStringBuf Path; - TStringBuf NameHint; - }; +struct TSplittedPath { + TStringBuf Path; + TStringBuf NameHint; +}; - struct TTableDetails { - TVector<TString> Columns; - }; +struct TTableDetails { + TVector<TString> Columns; +}; - class ISimpleSchema: public TThrRefBase { - public: - using TPtr = TIntrusivePtr<ISimpleSchema>; +class ISimpleSchema: public TThrRefBase { +public: + using TPtr = TIntrusivePtr<ISimpleSchema>; - ~ISimpleSchema() override = default; + ~ISimpleSchema() override = default; - virtual TSplittedPath Split(TStringBuf path) const = 0; + virtual TSplittedPath Split(TStringBuf path) const = 0; - // TODO(YQL-19747): Deprecated, use List(cluster, folder) instead. - virtual NThreading::TFuture<TVector<TFolderEntry>> List(TString folder) const; + // TODO(YQL-19747): Deprecated, use List(cluster, folder) instead. + virtual NThreading::TFuture<TVector<TFolderEntry>> List(TString folder) const; - virtual NThreading::TFuture<TVector<TFolderEntry>> - List(TString cluster, TString folder) const; + virtual NThreading::TFuture<TVector<TFolderEntry>> + List(TString cluster, TString folder) const; - virtual NThreading::TFuture<TMaybe<TTableDetails>> - DescribeTable(const TString& cluster, const TString& path) const; - }; + virtual NThreading::TFuture<TMaybe<TTableDetails>> + DescribeTable(const TString& cluster, const TString& path) const; +}; - ISchema::TPtr MakeSimpleSchema(ISimpleSchema::TPtr simple); +ISchema::TPtr MakeSimpleSchema(ISimpleSchema::TPtr simple); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/simple/schema_ut.cpp b/yql/essentials/sql/v1/complete/name/object/simple/schema_ut.cpp index e74b81913aa..346c2c5f920 100644 --- a/yql/essentials/sql/v1/complete/name/object/simple/schema_ut.cpp +++ b/yql/essentials/sql/v1/complete/name/object/simple/schema_ut.cpp @@ -8,118 +8,118 @@ using namespace NSQLComplete; Y_UNIT_TEST_SUITE(StaticSchemaTests) { - ISchema::TPtr MakeStaticSchemaUT() { - THashMap<TString, THashMap<TString, TVector<TFolderEntry>>> fs = { - {"", {{"/", {{"Folder", "local"}, - {"Folder", "test"}, - {"Folder", "prod"}}}, - {"/local/", {{"Table", "example"}, - {"Table", "account"}, - {"Table", "abacaba"}}}, - {"/test/", {{"Folder", "service"}, - {"Table", "meta"}}}, - {"/test/service/", {{"Table", "example"}}}}}, +ISchema::TPtr MakeStaticSchemaUT() { + THashMap<TString, THashMap<TString, TVector<TFolderEntry>>> fs = { + {"", {{"/", {{"Folder", "local"}, + {"Folder", "test"}, + {"Folder", "prod"}}}, + {"/local/", {{"Table", "example"}, + {"Table", "account"}, + {"Table", "abacaba"}}}, + {"/test/", {{"Folder", "service"}, + {"Table", "meta"}}}, + {"/test/service/", {{"Table", "example"}}}}}, + }; + return MakeSimpleSchema(MakeStaticSimpleSchema({.Folders = std::move(fs)})); +} + +Y_UNIT_TEST(ListFolderBasic) { + auto schema = MakeStaticSchemaUT(); + { + TVector<TFolderEntry> expected = { + {"Folder", "local"}, + {"Folder", "test"}, + {"Folder", "prod"}, }; - return MakeSimpleSchema(MakeStaticSimpleSchema({.Folders = std::move(fs)})); + UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/"}).GetValueSync().Entries, expected); } - - Y_UNIT_TEST(ListFolderBasic) { - auto schema = MakeStaticSchemaUT(); - { - TVector<TFolderEntry> expected = { - {"Folder", "local"}, - {"Folder", "test"}, - {"Folder", "prod"}, - }; - UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/"}).GetValueSync().Entries, expected); - } - { - TVector<TFolderEntry> expected = { - {"Table", "example"}, - {"Table", "account"}, - {"Table", "abacaba"}, - }; - UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/local/"}).GetValueSync().Entries, expected); - } - { - TVector<TFolderEntry> expected = { - {"Folder", "service"}, - {"Table", "meta"}, - }; - UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/test/"}).GetValueSync().Entries, expected); - } - { - TVector<TFolderEntry> expected = { - {"Table", "example"}}; - UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/test/service/"}).GetValueSync().Entries, expected); - } + { + TVector<TFolderEntry> expected = { + {"Table", "example"}, + {"Table", "account"}, + {"Table", "abacaba"}, + }; + UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/local/"}).GetValueSync().Entries, expected); } - - Y_UNIT_TEST(ListFolderHint) { - auto schema = MakeStaticSchemaUT(); - { - TVector<TFolderEntry> expected = { - {"Folder", "local"}, - }; - auto actual = schema->List({.Path = "/l"}).GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected); - UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 1); - } - { - TVector<TFolderEntry> expected = { - {"Table", "account"}, - {"Table", "abacaba"}, - }; - auto actual = schema->List({.Path = "/local/a"}).GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected); - UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 1); - } - { - TVector<TFolderEntry> expected = { - {"Folder", "service"}, - }; - auto actual = schema->List({.Path = "/test/service"}).GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected); - UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 7); - } + { + TVector<TFolderEntry> expected = { + {"Folder", "service"}, + {"Table", "meta"}, + }; + UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/test/"}).GetValueSync().Entries, expected); } + { + TVector<TFolderEntry> expected = { + {"Table", "example"}}; + UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/test/service/"}).GetValueSync().Entries, expected); + } +} - Y_UNIT_TEST(ListFolderFilterByType) { - auto schema = MakeStaticSchemaUT(); - { - TVector<TFolderEntry> expected = { - {"Folder", "service"}, - }; - TListRequest request = { - .Path = "/test/", - .Filter = { - .Types = THashSet<TString>{"Folder"}, - }, - }; - UNIT_ASSERT_VALUES_EQUAL(schema->List(request).GetValueSync().Entries, expected); - } - { - TVector<TFolderEntry> expected = { - {"Table", "meta"}, - }; - TListRequest request = { - .Path = "/test/", - .Filter = { - .Types = THashSet<TString>{"Table"}, - }, - }; - UNIT_ASSERT_VALUES_EQUAL(schema->List(request).GetValueSync().Entries, expected); - } +Y_UNIT_TEST(ListFolderHint) { + auto schema = MakeStaticSchemaUT(); + { + TVector<TFolderEntry> expected = { + {"Folder", "local"}, + }; + auto actual = schema->List({.Path = "/l"}).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected); + UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 1); + } + { + TVector<TFolderEntry> expected = { + {"Table", "account"}, + {"Table", "abacaba"}, + }; + auto actual = schema->List({.Path = "/local/a"}).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected); + UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 1); } + { + TVector<TFolderEntry> expected = { + {"Folder", "service"}, + }; + auto actual = schema->List({.Path = "/test/service"}).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected); + UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 7); + } +} - Y_UNIT_TEST(ListFolderLimit) { - auto schema = MakeStaticSchemaUT(); - UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 0}).GetValueSync().Entries.size(), 0); - UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 1}).GetValueSync().Entries.size(), 1); - UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 2}).GetValueSync().Entries.size(), 2); - UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 3}).GetValueSync().Entries.size(), 3); - UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 4}).GetValueSync().Entries.size(), 3); - UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 5}).GetValueSync().Entries.size(), 3); +Y_UNIT_TEST(ListFolderFilterByType) { + auto schema = MakeStaticSchemaUT(); + { + TVector<TFolderEntry> expected = { + {"Folder", "service"}, + }; + TListRequest request = { + .Path = "/test/", + .Filter = { + .Types = THashSet<TString>{"Folder"}, + }, + }; + UNIT_ASSERT_VALUES_EQUAL(schema->List(request).GetValueSync().Entries, expected); } + { + TVector<TFolderEntry> expected = { + {"Table", "meta"}, + }; + TListRequest request = { + .Path = "/test/", + .Filter = { + .Types = THashSet<TString>{"Table"}, + }, + }; + UNIT_ASSERT_VALUES_EQUAL(schema->List(request).GetValueSync().Entries, expected); + } +} + +Y_UNIT_TEST(ListFolderLimit) { + auto schema = MakeStaticSchemaUT(); + UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 0}).GetValueSync().Entries.size(), 0); + UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 1}).GetValueSync().Entries.size(), 1); + UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 2}).GetValueSync().Entries.size(), 2); + UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 3}).GetValueSync().Entries.size(), 3); + UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 4}).GetValueSync().Entries.size(), 3); + UNIT_ASSERT_VALUES_EQUAL(schema->List({.Path = "/", .Limit = 5}).GetValueSync().Entries.size(), 3); +} } // Y_UNIT_TEST_SUITE(StaticSchemaTests) diff --git a/yql/essentials/sql/v1/complete/name/object/simple/static/schema.cpp b/yql/essentials/sql/v1/complete/name/object/simple/static/schema.cpp index d413ee859f0..c138aff31dc 100644 --- a/yql/essentials/sql/v1/complete/name/object/simple/static/schema.cpp +++ b/yql/essentials/sql/v1/complete/name/object/simple/static/schema.cpp @@ -4,86 +4,86 @@ namespace NSQLComplete { - namespace { - - class TSimpleSchema: public ISimpleSchema { - public: - explicit TSimpleSchema( - THashMap<TString, THashMap<TString, TVector<TFolderEntry>>> folders, - THashMap<TString, THashMap<TString, TTableDetails>> tables) - : Folders_(std::move(folders)) - , Tables_(std::move(tables)) - { - for (const auto& [_, paths] : Folders_) { - for (const auto& [k, _] : paths) { - Y_ENSURE(k.StartsWith("/"), k << " must start with the '/'"); - Y_ENSURE(k.EndsWith("/"), k << " must end with the '/'"); - } - } - - for (const auto& [_, paths] : Tables_) { - for (const auto& [k, _] : paths) { - Y_ENSURE(k.StartsWith("/"), k << " must start with the '/'"); - Y_ENSURE(!k.EndsWith("/"), k << " must not end with the '/'"); - } - } +namespace { + +class TSimpleSchema: public ISimpleSchema { +public: + explicit TSimpleSchema( + THashMap<TString, THashMap<TString, TVector<TFolderEntry>>> folders, + THashMap<TString, THashMap<TString, TTableDetails>> tables) + : Folders_(std::move(folders)) + , Tables_(std::move(tables)) + { + for (const auto& [_, paths] : Folders_) { + for (const auto& [k, _] : paths) { + Y_ENSURE(k.StartsWith("/"), k << " must start with the '/'"); + Y_ENSURE(k.EndsWith("/"), k << " must end with the '/'"); } + } - TSplittedPath Split(TStringBuf path) const override { - size_t pos = path.find_last_of('/'); - if (pos == TString::npos) { - return {"", path}; - } - - TStringBuf head, tail; - TStringBuf(path).SplitAt(pos + 1, head, tail); - return {head, tail}; + for (const auto& [_, paths] : Tables_) { + for (const auto& [k, _] : paths) { + Y_ENSURE(k.StartsWith("/"), k << " must start with the '/'"); + Y_ENSURE(!k.EndsWith("/"), k << " must not end with the '/'"); } + } + } - NThreading::TFuture<TVector<TFolderEntry>> List(TString cluster, TString folder) const override { - TVector<TFolderEntry> entries; - - const THashMap<TString, TVector<TFolderEntry>>* tables = nullptr; - const TVector<TFolderEntry>* items = nullptr; - if ((tables = Folders_.FindPtr(cluster)) && - (items = tables->FindPtr(Qualified(folder)))) { - entries = *items; - } + TSplittedPath Split(TStringBuf path) const override { + size_t pos = path.find_last_of('/'); + if (pos == TString::npos) { + return {"", path}; + } - return NThreading::MakeFuture(std::move(entries)); - } + TStringBuf head, tail; + TStringBuf(path).SplitAt(pos + 1, head, tail); + return {head, tail}; + } - NThreading::TFuture<TMaybe<TTableDetails>> - DescribeTable(const TString& cluster, const TString& path) const override { - auto* tables = Tables_.FindPtr(cluster); - if (tables == nullptr) { - return NThreading::MakeFuture<TMaybe<TTableDetails>>(Nothing()); - } + NThreading::TFuture<TVector<TFolderEntry>> List(TString cluster, TString folder) const override { + TVector<TFolderEntry> entries; - auto* details = tables->FindPtr(Qualified(path)); - if (details == nullptr) { - return NThreading::MakeFuture<TMaybe<TTableDetails>>(Nothing()); - } + const THashMap<TString, TVector<TFolderEntry>>* tables = nullptr; + const TVector<TFolderEntry>* items = nullptr; + if ((tables = Folders_.FindPtr(cluster)) && + (items = tables->FindPtr(Qualified(folder)))) { + entries = *items; + } - return NThreading::MakeFuture<TMaybe<TTableDetails>>(*details); - } + return NThreading::MakeFuture(std::move(entries)); + } - private: - TString Qualified(TString path) const { - if (!path.StartsWith('/')) { - path.prepend('/'); - } - return path; - } + NThreading::TFuture<TMaybe<TTableDetails>> + DescribeTable(const TString& cluster, const TString& path) const override { + auto* tables = Tables_.FindPtr(cluster); + if (tables == nullptr) { + return NThreading::MakeFuture<TMaybe<TTableDetails>>(Nothing()); + } - THashMap<TString, THashMap<TString, TVector<TFolderEntry>>> Folders_; - THashMap<TString, THashMap<TString, TTableDetails>> Tables_; - }; + auto* details = tables->FindPtr(Qualified(path)); + if (details == nullptr) { + return NThreading::MakeFuture<TMaybe<TTableDetails>>(Nothing()); + } - } // namespace + return NThreading::MakeFuture<TMaybe<TTableDetails>>(*details); + } - ISimpleSchema::TPtr MakeStaticSimpleSchema(TSchemaData data) { - return new TSimpleSchema(std::move(data.Folders), std::move(data.Tables)); +private: + TString Qualified(TString path) const { + if (!path.StartsWith('/')) { + path.prepend('/'); + } + return path; } + THashMap<TString, THashMap<TString, TVector<TFolderEntry>>> Folders_; + THashMap<TString, THashMap<TString, TTableDetails>> Tables_; +}; + +} // namespace + +ISimpleSchema::TPtr MakeStaticSimpleSchema(TSchemaData data) { + return new TSimpleSchema(std::move(data.Folders), std::move(data.Tables)); +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/simple/static/schema.h b/yql/essentials/sql/v1/complete/name/object/simple/static/schema.h index 0fdf8f00d9b..b288933fdee 100644 --- a/yql/essentials/sql/v1/complete/name/object/simple/static/schema.h +++ b/yql/essentials/sql/v1/complete/name/object/simple/static/schema.h @@ -6,11 +6,11 @@ namespace NSQLComplete { - struct TSchemaData { - THashMap<TString, THashMap<TString, TVector<TFolderEntry>>> Folders; - THashMap<TString, THashMap<TString, TTableDetails>> Tables; - }; +struct TSchemaData { + THashMap<TString, THashMap<TString, TVector<TFolderEntry>>> Folders; + THashMap<TString, THashMap<TString, TTableDetails>> Tables; +}; - ISimpleSchema::TPtr MakeStaticSimpleSchema(TSchemaData data); +ISimpleSchema::TPtr MakeStaticSimpleSchema(TSchemaData data); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/simple/static/schema_json.cpp b/yql/essentials/sql/v1/complete/name/object/simple/static/schema_json.cpp index 9e0723e5255..dba0330ea8c 100644 --- a/yql/essentials/sql/v1/complete/name/object/simple/static/schema_json.cpp +++ b/yql/essentials/sql/v1/complete/name/object/simple/static/schema_json.cpp @@ -9,105 +9,105 @@ namespace NSQLComplete { - namespace { - - TString PathString(const TVector<TString>& path) { - return "/" + JoinSeq("/", path); - } - - const NJson::TJsonValue& Expect( - const TVector<TString>& path, - const NJson::TJsonValue::TMapType& json, - TStringBuf key) { - if (!json.contains(key)) { - ythrow yexception() << "At " << PathString(path) << " expected " << key; - } - return json.at(key); - } - - const NJson::TJsonValue::TMapType& ExpectMap( - const TVector<TString>& path, - const NJson::TJsonValue& json) { - if (!json.IsMap()) { - ythrow yexception() << "At " << PathString(path) << " expected Map"; - } - return json.GetMapSafe(); - } - - const NJson::TJsonValue::TMapType& ExpectMap( - const TVector<TString>& path, - const NJson::TJsonValue::TMapType& json, - TStringBuf key) { - Expect(path, json, key); - return ExpectMap(path, json.at(key)); - } - - TString Parse( - const TString& cluster, - const NJson::TJsonValue::TMapType& json, - TSchemaData& data, - TVector<TString>& path); - - void ParseFolder( - const TString& cluster, - const NJson::TJsonValue::TMapType& json, - TSchemaData& data, - TVector<TString>& path) { - for (const auto& [name, entry] : ExpectMap(path, json, "entries")) { - path.emplace_back(name); - TString type = Parse(cluster, ExpectMap(path, entry), data, path); - path.pop_back(); - - TStringBuf suffix = (!path.empty()) ? "/" : ""; - data.Folders[cluster][PathString(path) + suffix].emplace_back(type, name); - } - } - - void ParseTable( - const TString& cluster, - const NJson::TJsonValue::TMapType& json, - TSchemaData& data, - TVector<TString>& path) { - for (const auto& [name, _] : ExpectMap(path, json, "columns")) { - data.Tables[cluster][PathString(path)].Columns.emplace_back(name); - } - } - - TString Parse( - const TString& cluster, - const NJson::TJsonValue::TMapType& json, - TSchemaData& data, - TVector<TString>& path) { - auto type = Expect(path, json, "type"); - - if (type == TFolderEntry::Folder) { - ParseFolder(cluster, json, data, path); - return TFolderEntry::Folder; - } - - if (type == TFolderEntry::Table) { - ParseTable(cluster, json, data, path); - return TFolderEntry::Table; - } - - if (!type.IsString()) { - ythrow yexception() << "Unexpected type: " << type; - } - - return type.GetStringSafe(); - } - - } // namespace - - ISimpleSchema::TPtr MakeStaticSimpleSchema(const NJson::TJsonMap& json) { - TSchemaData data; - - for (const auto& [cluster, tree] : json.GetMap()) { - TVector<TString> path; - ParseFolder(cluster, tree.GetMapSafe(), data, path); - } - - return MakeStaticSimpleSchema(std::move(data)); +namespace { + +TString PathString(const TVector<TString>& path) { + return "/" + JoinSeq("/", path); +} + +const NJson::TJsonValue& Expect( + const TVector<TString>& path, + const NJson::TJsonValue::TMapType& json, + TStringBuf key) { + if (!json.contains(key)) { + ythrow yexception() << "At " << PathString(path) << " expected " << key; } + return json.at(key); +} + +const NJson::TJsonValue::TMapType& ExpectMap( + const TVector<TString>& path, + const NJson::TJsonValue& json) { + if (!json.IsMap()) { + ythrow yexception() << "At " << PathString(path) << " expected Map"; + } + return json.GetMapSafe(); +} + +const NJson::TJsonValue::TMapType& ExpectMap( + const TVector<TString>& path, + const NJson::TJsonValue::TMapType& json, + TStringBuf key) { + Expect(path, json, key); + return ExpectMap(path, json.at(key)); +} + +TString Parse( + const TString& cluster, + const NJson::TJsonValue::TMapType& json, + TSchemaData& data, + TVector<TString>& path); + +void ParseFolder( + const TString& cluster, + const NJson::TJsonValue::TMapType& json, + TSchemaData& data, + TVector<TString>& path) { + for (const auto& [name, entry] : ExpectMap(path, json, "entries")) { + path.emplace_back(name); + TString type = Parse(cluster, ExpectMap(path, entry), data, path); + path.pop_back(); + + TStringBuf suffix = (!path.empty()) ? "/" : ""; + data.Folders[cluster][PathString(path) + suffix].emplace_back(type, name); + } +} + +void ParseTable( + const TString& cluster, + const NJson::TJsonValue::TMapType& json, + TSchemaData& data, + TVector<TString>& path) { + for (const auto& [name, _] : ExpectMap(path, json, "columns")) { + data.Tables[cluster][PathString(path)].Columns.emplace_back(name); + } +} + +TString Parse( + const TString& cluster, + const NJson::TJsonValue::TMapType& json, + TSchemaData& data, + TVector<TString>& path) { + auto type = Expect(path, json, "type"); + + if (type == TFolderEntry::Folder) { + ParseFolder(cluster, json, data, path); + return TFolderEntry::Folder; + } + + if (type == TFolderEntry::Table) { + ParseTable(cluster, json, data, path); + return TFolderEntry::Table; + } + + if (!type.IsString()) { + ythrow yexception() << "Unexpected type: " << type; + } + + return type.GetStringSafe(); +} + +} // namespace + +ISimpleSchema::TPtr MakeStaticSimpleSchema(const NJson::TJsonMap& json) { + TSchemaData data; + + for (const auto& [cluster, tree] : json.GetMap()) { + TVector<TString> path; + ParseFolder(cluster, tree.GetMapSafe(), data, path); + } + + return MakeStaticSimpleSchema(std::move(data)); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/simple/static/schema_json.h b/yql/essentials/sql/v1/complete/name/object/simple/static/schema_json.h index 83b053791ee..e1647dec832 100644 --- a/yql/essentials/sql/v1/complete/name/object/simple/static/schema_json.h +++ b/yql/essentials/sql/v1/complete/name/object/simple/static/schema_json.h @@ -6,6 +6,6 @@ namespace NSQLComplete { - ISimpleSchema::TPtr MakeStaticSimpleSchema(const NJson::TJsonMap& json); +ISimpleSchema::TPtr MakeStaticSimpleSchema(const NJson::TJsonMap& json); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/binding/name_service.cpp b/yql/essentials/sql/v1/complete/name/service/binding/name_service.cpp index 6d4e5d15318..4f35ae365d1 100644 --- a/yql/essentials/sql/v1/complete/name/service/binding/name_service.cpp +++ b/yql/essentials/sql/v1/complete/name/service/binding/name_service.cpp @@ -4,52 +4,52 @@ namespace NSQLComplete { - namespace { - - class TNameService: public INameService { - public: - explicit TNameService(TVector<TString> names) - : Index_(BuildNameIndex(std::move(names), NormalizeName)) - { - } - - NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { - if (request.Constraints.IsEmpty()) { - return NThreading::MakeFuture<TNameResponse>({}); - } - - TVector<TStringBuf> filtered = - FilteredByPrefix(request.Prefix, Index_, NormalizeName); - filtered.crop(request.Limit); - - return NThreading::MakeFuture<TNameResponse>({ - .RankedNames = Transform(filtered), - }); - } - - private: - static TVector<TGenericName> Transform(TVector<TStringBuf> names) { - TVector<TGenericName> generic; - generic.reserve(names.size()); - for (TStringBuf name : names) { - generic.emplace_back(Transform(name)); - } - return generic; - } - - static TGenericName Transform(TStringBuf name) { - TBindingName unknown; - unknown.Identifier = name; - return unknown; - } - - TNameIndex Index_; - }; - - } // namespace - - INameService::TPtr MakeBindingNameService(TVector<TString> names) { - return new TNameService(std::move(names)); +namespace { + +class TNameService: public INameService { +public: + explicit TNameService(TVector<TString> names) + : Index_(BuildNameIndex(std::move(names), NormalizeName)) + { + } + + NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { + if (request.Constraints.IsEmpty()) { + return NThreading::MakeFuture<TNameResponse>({}); + } + + TVector<TStringBuf> filtered = + FilteredByPrefix(request.Prefix, Index_, NormalizeName); + filtered.crop(request.Limit); + + return NThreading::MakeFuture<TNameResponse>({ + .RankedNames = Transform(filtered), + }); + } + +private: + static TVector<TGenericName> Transform(TVector<TStringBuf> names) { + TVector<TGenericName> generic; + generic.reserve(names.size()); + for (TStringBuf name : names) { + generic.emplace_back(Transform(name)); + } + return generic; + } + + static TGenericName Transform(TStringBuf name) { + TBindingName unknown; + unknown.Identifier = name; + return unknown; } + TNameIndex Index_; +}; + +} // namespace + +INameService::TPtr MakeBindingNameService(TVector<TString> names) { + return new TNameService(std::move(names)); +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/binding/name_service.h b/yql/essentials/sql/v1/complete/name/service/binding/name_service.h index 4c9de468a93..610c66dbe3b 100644 --- a/yql/essentials/sql/v1/complete/name/service/binding/name_service.h +++ b/yql/essentials/sql/v1/complete/name/service/binding/name_service.h @@ -6,6 +6,6 @@ namespace NSQLComplete { - INameService::TPtr MakeBindingNameService(TVector<TString> names); +INameService::TPtr MakeBindingNameService(TVector<TString> names); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/cluster/name_service.cpp b/yql/essentials/sql/v1/complete/name/service/cluster/name_service.cpp index c65484627f0..b5e6e00b224 100644 --- a/yql/essentials/sql/v1/complete/name/service/cluster/name_service.cpp +++ b/yql/essentials/sql/v1/complete/name/service/cluster/name_service.cpp @@ -6,79 +6,79 @@ namespace NSQLComplete { - namespace { - - class TNameService: public INameService { - private: - static auto FilterByName(TString name) { - return [name = std::move(name)](auto f) { - TClusterList clusters = f.ExtractValue(); - EraseIf(clusters, [prefix = TCaseInsensitiveStringBuf(name)](const TString& instance) { - return !TCaseInsensitiveStringBuf(instance).StartsWith(prefix); - }); - return clusters; - }; - } - - static auto Crop(size_t limit) { - return [limit](auto f) { - TClusterList clusters = f.ExtractValue(); - clusters.crop(limit); - return clusters; - }; - } +namespace { + +class TNameService: public INameService { +private: + static auto FilterByName(TString name) { + return [name = std::move(name)](auto f) { + TClusterList clusters = f.ExtractValue(); + EraseIf(clusters, [prefix = TCaseInsensitiveStringBuf(name)](const TString& instance) { + return !TCaseInsensitiveStringBuf(instance).StartsWith(prefix); + }); + return clusters; + }; + } - static auto ToResponse(TNameConstraints constraints) { - return [constraints = std::move(constraints)](auto f) { - TClusterList clusters = f.ExtractValue(); + static auto Crop(size_t limit) { + return [limit](auto f) { + TClusterList clusters = f.ExtractValue(); + clusters.crop(limit); + return clusters; + }; + } - TNameResponse response; - response.RankedNames.reserve(clusters.size()); + static auto ToResponse(TNameConstraints constraints) { + return [constraints = std::move(constraints)](auto f) { + TClusterList clusters = f.ExtractValue(); - for (auto& cluster : clusters) { - TClusterName name; - name.Identifier = std::move(cluster); - response.RankedNames.emplace_back(std::move(name)); - } + TNameResponse response; + response.RankedNames.reserve(clusters.size()); - response.RankedNames = constraints.Unqualified(std::move(response.RankedNames)); - return response; - }; + for (auto& cluster : clusters) { + TClusterName name; + name.Identifier = std::move(cluster); + response.RankedNames.emplace_back(std::move(name)); } - public: - explicit TNameService(IClusterDiscovery::TPtr discovery) - : Discovery_(std::move(discovery)) - { - } + response.RankedNames = constraints.Unqualified(std::move(response.RankedNames)); + return response; + }; + } - NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { - if (!request.Constraints.Cluster) { - return NThreading::MakeFuture<TNameResponse>({}); - } +public: + explicit TNameService(IClusterDiscovery::TPtr discovery) + : Discovery_(std::move(discovery)) + { + } - return Discovery_->Query() - .Apply(FilterByName(QualifiedClusterName(request))) - .Apply(Crop(request.Limit)) - .Apply(ToResponse(request.Constraints)); - } + NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { + if (!request.Constraints.Cluster) { + return NThreading::MakeFuture<TNameResponse>({}); + } - private: - static TString QualifiedClusterName(const TNameRequest& request) { - TClusterName cluster; - cluster.Identifier = request.Prefix; + return Discovery_->Query() + .Apply(FilterByName(QualifiedClusterName(request))) + .Apply(Crop(request.Limit)) + .Apply(ToResponse(request.Constraints)); + } - TGenericName generic = request.Constraints.Qualified(cluster); - return std::get<TClusterName>(std::move(generic)).Identifier; - } +private: + static TString QualifiedClusterName(const TNameRequest& request) { + TClusterName cluster; + cluster.Identifier = request.Prefix; - IClusterDiscovery::TPtr Discovery_; - }; + TGenericName generic = request.Constraints.Qualified(cluster); + return std::get<TClusterName>(std::move(generic)).Identifier; + } - } // namespace + IClusterDiscovery::TPtr Discovery_; +}; - INameService::TPtr MakeClusterNameService(IClusterDiscovery::TPtr discovery) { - return new TNameService(std::move(discovery)); - } +} // namespace + +INameService::TPtr MakeClusterNameService(IClusterDiscovery::TPtr discovery) { + return new TNameService(std::move(discovery)); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/cluster/name_service.h b/yql/essentials/sql/v1/complete/name/service/cluster/name_service.h index a57eabc0d2b..d5c628f1126 100644 --- a/yql/essentials/sql/v1/complete/name/service/cluster/name_service.h +++ b/yql/essentials/sql/v1/complete/name/service/cluster/name_service.h @@ -5,6 +5,6 @@ namespace NSQLComplete { - INameService::TPtr MakeClusterNameService(IClusterDiscovery::TPtr discovery); +INameService::TPtr MakeClusterNameService(IClusterDiscovery::TPtr discovery); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/column/name_service.cpp b/yql/essentials/sql/v1/complete/name/service/column/name_service.cpp index bb302fac672..c6670377670 100644 --- a/yql/essentials/sql/v1/complete/name/service/column/name_service.cpp +++ b/yql/essentials/sql/v1/complete/name/service/column/name_service.cpp @@ -4,92 +4,92 @@ namespace NSQLComplete { - namespace { - - class TNameService: public INameService { - public: - explicit TNameService(TVector<TColumnId> columns) { - TSchemaData data; - for (auto& column : columns) { - Tables_.emplace(column.TableAlias); - - data.Tables[""]["/" + Escaped(column.TableAlias)] - .Columns - .emplace_back(std::move(column.Name)); - } +namespace { - Schema_ = MakeSimpleSchema(MakeStaticSimpleSchema(std::move(data))); - } +class TNameService: public INameService { +public: + explicit TNameService(TVector<TColumnId> columns) { + TSchemaData data; + for (auto& column : columns) { + Tables_.emplace(column.TableAlias); - NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { - if (!request.Constraints.Column) { - return NThreading::MakeFuture<TNameResponse>({}); - } + data.Tables[""]["/" + Escaped(column.TableAlias)] + .Columns + .emplace_back(std::move(column.Name)); + } - TNameResponse response; - - for (const TString& tableName : Tables_) { - const auto& withoutByTableAlias = request.Constraints.Column->WithoutByTableAlias; - - THashSet<TString> without; - if (auto it = withoutByTableAlias.find(tableName); it != withoutByTableAlias.end()) { - without.insert(begin(it->second), end(it->second)); - } - if (auto it = withoutByTableAlias.find(""); it != withoutByTableAlias.end()) { - without.insert(begin(it->second), end(it->second)); - } - - TString columnPrefix = request.Prefix; - if (tableName.StartsWith(request.Prefix)) { - columnPrefix = ""; - } - - TDescribeTableRequest describeRequest = { - .TableCluster = "", - .TablePath = Escaped(tableName), - .ColumnPrefix = columnPrefix, - .ColumnsLimit = request.Limit, - }; - - TDescribeTableResponse table = - Schema_ - ->Describe(std::move(describeRequest)) - .ExtractValue(); - - Y_ENSURE(table.IsExisting); - for (TString& column : table.Columns) { - if (without.contains(column)) { - continue; - } - - TColumnName name; - name.TableAlias = tableName; - name.Identifier = std::move(column); - - response.RankedNames.emplace_back(std::move(name)); - } - } + Schema_ = MakeSimpleSchema(MakeStaticSimpleSchema(std::move(data))); + } - response.RankedNames.crop(request.Limit); + NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { + if (!request.Constraints.Column) { + return NThreading::MakeFuture<TNameResponse>({}); + } - return NThreading::MakeFuture(std::move(response)); + TNameResponse response; + + for (const TString& tableName : Tables_) { + const auto& withoutByTableAlias = request.Constraints.Column->WithoutByTableAlias; + + THashSet<TString> without; + if (auto it = withoutByTableAlias.find(tableName); it != withoutByTableAlias.end()) { + without.insert(begin(it->second), end(it->second)); + } + if (auto it = withoutByTableAlias.find(""); it != withoutByTableAlias.end()) { + without.insert(begin(it->second), end(it->second)); } - private: - static TString Escaped(TString tableName) { - // Saves when name is empty - tableName.prepend("table_"); - return tableName; + TString columnPrefix = request.Prefix; + if (tableName.StartsWith(request.Prefix)) { + columnPrefix = ""; } - THashSet<TString> Tables_; - ISchema::TPtr Schema_; - }; + TDescribeTableRequest describeRequest = { + .TableCluster = "", + .TablePath = Escaped(tableName), + .ColumnPrefix = columnPrefix, + .ColumnsLimit = request.Limit, + }; + + TDescribeTableResponse table = + Schema_ + ->Describe(std::move(describeRequest)) + .ExtractValue(); + + Y_ENSURE(table.IsExisting); + for (TString& column : table.Columns) { + if (without.contains(column)) { + continue; + } - } // namespace + TColumnName name; + name.TableAlias = tableName; + name.Identifier = std::move(column); - INameService::TPtr MakeColumnNameService(TVector<TColumnId> columns) { - return new TNameService(std::move(columns)); + response.RankedNames.emplace_back(std::move(name)); + } + } + + response.RankedNames.crop(request.Limit); + + return NThreading::MakeFuture(std::move(response)); + } + +private: + static TString Escaped(TString tableName) { + // Saves when name is empty + tableName.prepend("table_"); + return tableName; } + THashSet<TString> Tables_; + ISchema::TPtr Schema_; +}; + +} // namespace + +INameService::TPtr MakeColumnNameService(TVector<TColumnId> columns) { + return new TNameService(std::move(columns)); +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/column/name_service.h b/yql/essentials/sql/v1/complete/name/service/column/name_service.h index 51d3239748a..e13f8e85937 100644 --- a/yql/essentials/sql/v1/complete/name/service/column/name_service.h +++ b/yql/essentials/sql/v1/complete/name/service/column/name_service.h @@ -5,6 +5,6 @@ namespace NSQLComplete { - INameService::TPtr MakeColumnNameService(TVector<TColumnId> columns); +INameService::TPtr MakeColumnNameService(TVector<TColumnId> columns); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/column/replicating.cpp b/yql/essentials/sql/v1/complete/name/service/column/replicating.cpp index ef2d39969d5..309a033f9de 100644 --- a/yql/essentials/sql/v1/complete/name/service/column/replicating.cpp +++ b/yql/essentials/sql/v1/complete/name/service/column/replicating.cpp @@ -8,78 +8,78 @@ namespace NSQLComplete { - namespace { - - class TNameService: public INameService { - public: - TNameService(INameService::TPtr origin, IRanking::TPtr ranking) - : Origin_(std::move(origin)) - , Ranking_(std::move(ranking)) - { - } +namespace { + +class TNameService: public INameService { +public: + TNameService(INameService::TPtr origin, IRanking::TPtr ranking) + : Origin_(std::move(origin)) + , Ranking_(std::move(ranking)) + { + } + + NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const final { + NThreading::TFuture<TNameResponse> response = Origin_->Lookup(request); - NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const final { - NThreading::TFuture<TNameResponse> response = Origin_->Lookup(request); + if (!request.Constraints.Column || request.Constraints.Column->TableAlias) { + return response; + } - if (!request.Constraints.Column || request.Constraints.Column->TableAlias) { - return response; - } + return std::move(response).Apply([request, ranking = Ranking_](auto f) -> TNameResponse { + TNameResponse response = f.ExtractValue(); - return std::move(response).Apply([request, ranking = Ranking_](auto f) -> TNameResponse { - TNameResponse response = f.ExtractValue(); + TVector<TGenericName> replicatable = ReplicatableColumns(response.RankedNames, request.Prefix); + std::ranges::move(std::move(replicatable), std::back_inserter(response.RankedNames)); - TVector<TGenericName> replicatable = ReplicatableColumns(response.RankedNames, request.Prefix); - std::ranges::move(std::move(replicatable), std::back_inserter(response.RankedNames)); + ranking->CropToSortedPrefix(response.RankedNames, request.Constraints, request.Limit); - ranking->CropToSortedPrefix(response.RankedNames, request.Constraints, request.Limit); + return response; + }); + } - return response; - }); +private: + static TVector<TGenericName> ReplicatableColumns(const TVector<TGenericName>& names, TStringBuf prefix) { + THashMap<TString, size_t> references; + for (const TGenericName& name : names) { + if (!std::holds_alternative<TColumnName>(name)) { + continue; } - private: - static TVector<TGenericName> ReplicatableColumns(const TVector<TGenericName>& names, TStringBuf prefix) { - THashMap<TString, size_t> references; - for (const TGenericName& name : names) { - if (!std::holds_alternative<TColumnName>(name)) { - continue; - } - - const TColumnName& column = std::get<TColumnName>(name); - if (column.TableAlias.empty()) { - continue; - } - - references[column.Identifier] += 1; - } - - TVector<TGenericName> replicatable; - for (auto& [column, count] : references) { - if (count != 1) { - continue; - } - - // TODO(YQL-19747): introduce a single source of truth of filtration policy - if (!TCaseInsensitiveStringBuf(column).StartsWith(prefix)) { - continue; - } - - TColumnName name; - name.Identifier = column; - replicatable.emplace_back(std::move(name)); - } - - return replicatable; + const TColumnName& column = std::get<TColumnName>(name); + if (column.TableAlias.empty()) { + continue; } - INameService::TPtr Origin_; - IRanking::TPtr Ranking_; - }; + references[column.Identifier] += 1; + } - } // namespace + TVector<TGenericName> replicatable; + for (auto& [column, count] : references) { + if (count != 1) { + continue; + } - INameService::TPtr MakeColumnReplicatingService(INameService::TPtr origin, IRanking::TPtr ranking) { - return new TNameService(std::move(origin), std::move(ranking)); + // TODO(YQL-19747): introduce a single source of truth of filtration policy + if (!TCaseInsensitiveStringBuf(column).StartsWith(prefix)) { + continue; + } + + TColumnName name; + name.Identifier = column; + replicatable.emplace_back(std::move(name)); + } + + return replicatable; } + INameService::TPtr Origin_; + IRanking::TPtr Ranking_; +}; + +} // namespace + +INameService::TPtr MakeColumnReplicatingService(INameService::TPtr origin, IRanking::TPtr ranking) { + return new TNameService(std::move(origin), std::move(ranking)); +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/column/replicating.h b/yql/essentials/sql/v1/complete/name/service/column/replicating.h index 120d08cc264..3ecb7f4b778 100644 --- a/yql/essentials/sql/v1/complete/name/service/column/replicating.h +++ b/yql/essentials/sql/v1/complete/name/service/column/replicating.h @@ -5,6 +5,6 @@ namespace NSQLComplete { - INameService::TPtr MakeColumnReplicatingService(INameService::TPtr origin, IRanking::TPtr ranking); +INameService::TPtr MakeColumnReplicatingService(INameService::TPtr origin, IRanking::TPtr ranking); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/docs/documentation.cpp b/yql/essentials/sql/v1/complete/name/service/docs/documentation.cpp index 921b9462371..f68d2153276 100644 --- a/yql/essentials/sql/v1/complete/name/service/docs/documentation.cpp +++ b/yql/essentials/sql/v1/complete/name/service/docs/documentation.cpp @@ -4,59 +4,59 @@ namespace NSQLComplete { - namespace { - - class TStaticDocumentation: public IDocumentation { - public: - explicit TStaticDocumentation(TDocByNormalizedNameMap docs) - : Docs_(std::move(docs)) - { - } - - TMaybe<TString> Lookup(TStringBuf name) const override { - if (auto* ptr = Docs_.FindPtr(Normalized(name))) { - return *ptr; - } - return Nothing(); - } - - private: - TString Normalized(TStringBuf name) const { - return NormalizeName(name); - } - - TDocByNormalizedNameMap Docs_; - }; - - class TReservedDocumentation: public IDocumentation { - public: - TReservedDocumentation( - IDocumentation::TPtr primary, IDocumentation::TPtr fallback) - : Primary_(std::move(primary)) - , Fallback_(std::move(fallback)) - { - } - - TMaybe<TString> Lookup(TStringBuf name) const override { - return Primary_->Lookup(name).Or([name, f = Fallback_] { - return f->Lookup(name); - }); - } - - private: - IDocumentation::TPtr Primary_; - IDocumentation::TPtr Fallback_; - }; - - } // namespace - - IDocumentation::TPtr MakeStaticDocumentation(TDocByNormalizedNameMap docs) { - return new TStaticDocumentation(std::move(docs)); +namespace { + +class TStaticDocumentation: public IDocumentation { +public: + explicit TStaticDocumentation(TDocByNormalizedNameMap docs) + : Docs_(std::move(docs)) + { + } + + TMaybe<TString> Lookup(TStringBuf name) const override { + if (auto* ptr = Docs_.FindPtr(Normalized(name))) { + return *ptr; + } + return Nothing(); + } + +private: + TString Normalized(TStringBuf name) const { + return NormalizeName(name); + } + + TDocByNormalizedNameMap Docs_; +}; + +class TReservedDocumentation: public IDocumentation { +public: + TReservedDocumentation( + IDocumentation::TPtr primary, IDocumentation::TPtr fallback) + : Primary_(std::move(primary)) + , Fallback_(std::move(fallback)) + { } - IDocumentation::TPtr MakeReservedDocumentation( - IDocumentation::TPtr primary, IDocumentation::TPtr fallback) { - return new TReservedDocumentation(std::move(primary), std::move(fallback)); + TMaybe<TString> Lookup(TStringBuf name) const override { + return Primary_->Lookup(name).Or([name, f = Fallback_] { + return f->Lookup(name); + }); } +private: + IDocumentation::TPtr Primary_; + IDocumentation::TPtr Fallback_; +}; + +} // namespace + +IDocumentation::TPtr MakeStaticDocumentation(TDocByNormalizedNameMap docs) { + return new TStaticDocumentation(std::move(docs)); +} + +IDocumentation::TPtr MakeReservedDocumentation( + IDocumentation::TPtr primary, IDocumentation::TPtr fallback) { + return new TReservedDocumentation(std::move(primary), std::move(fallback)); +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/docs/documentation.h b/yql/essentials/sql/v1/complete/name/service/docs/documentation.h index 1ba1319e195..e557ae2e2cd 100644 --- a/yql/essentials/sql/v1/complete/name/service/docs/documentation.h +++ b/yql/essentials/sql/v1/complete/name/service/docs/documentation.h @@ -5,18 +5,18 @@ namespace NSQLComplete { - class IDocumentation: public TThrRefBase { - public: - using TPtr = TIntrusivePtr<IDocumentation>; +class IDocumentation: public TThrRefBase { +public: + using TPtr = TIntrusivePtr<IDocumentation>; - virtual TMaybe<TString> Lookup(TStringBuf name) const = 0; - }; + virtual TMaybe<TString> Lookup(TStringBuf name) const = 0; +}; - using TDocByNormalizedNameMap = THashMap<TString, TString>; +using TDocByNormalizedNameMap = THashMap<TString, TString>; - IDocumentation::TPtr MakeStaticDocumentation(TDocByNormalizedNameMap docs); +IDocumentation::TPtr MakeStaticDocumentation(TDocByNormalizedNameMap docs); - IDocumentation::TPtr MakeReservedDocumentation( - IDocumentation::TPtr primary, IDocumentation::TPtr fallback); +IDocumentation::TPtr MakeReservedDocumentation( + IDocumentation::TPtr primary, IDocumentation::TPtr fallback); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/docs/name_service.cpp b/yql/essentials/sql/v1/complete/name/service/docs/name_service.cpp index 9506a223198..823264c176e 100644 --- a/yql/essentials/sql/v1/complete/name/service/docs/name_service.cpp +++ b/yql/essentials/sql/v1/complete/name/service/docs/name_service.cpp @@ -2,45 +2,45 @@ namespace NSQLComplete { - namespace { - - class TNameService: public INameService { - public: - TNameService(IDocumentation::TPtr docs, INameService::TPtr origin) - : Docs_(std::move(docs)) - , Origin_(std::move(origin)) - { - } +namespace { + +class TNameService: public INameService { +public: + TNameService(IDocumentation::TPtr docs, INameService::TPtr origin) + : Docs_(std::move(docs)) + , Origin_(std::move(origin)) + { + } - NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { - return Origin_->Lookup(request).Apply([docs = Docs_, constraints = request.Constraints](auto f) { - TNameResponse response = f.ExtractValue(); - for (TGenericName& name : response.RankedNames) { - name = std::visit([&](auto&& name) -> TGenericName { - using T = std::decay_t<decltype(name)>; - - if constexpr (std::is_base_of_v<TDescribed, T> && - std::is_base_of_v<TIdentifier, T>) { - T qualified = std::get<T>(constraints.Qualified(name)); - name.Description = docs->Lookup(qualified.Identifier); - } - - return std::move(name); - }, std::move(name)); + NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { + return Origin_->Lookup(request).Apply([docs = Docs_, constraints = request.Constraints](auto f) { + TNameResponse response = f.ExtractValue(); + for (TGenericName& name : response.RankedNames) { + name = std::visit([&](auto&& name) -> TGenericName { + using T = std::decay_t<decltype(name)>; + + if constexpr (std::is_base_of_v<TDescribed, T> && + std::is_base_of_v<TIdentifier, T>) { + T qualified = std::get<T>(constraints.Qualified(name)); + name.Description = docs->Lookup(qualified.Identifier); } - return response; - }); + + return std::move(name); + }, std::move(name)); } + return response; + }); + } - private: - IDocumentation::TPtr Docs_; - INameService::TPtr Origin_; - }; +private: + IDocumentation::TPtr Docs_; + INameService::TPtr Origin_; +}; - } // namespace +} // namespace - INameService::TPtr MakeDocumentingNameService(IDocumentation::TPtr docs, INameService::TPtr origin) { - return new TNameService(std::move(docs), std::move(origin)); - } +INameService::TPtr MakeDocumentingNameService(IDocumentation::TPtr docs, INameService::TPtr origin) { + return new TNameService(std::move(docs), std::move(origin)); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/docs/name_service.h b/yql/essentials/sql/v1/complete/name/service/docs/name_service.h index db5abdc3acb..3bfa8a7bb1e 100644 --- a/yql/essentials/sql/v1/complete/name/service/docs/name_service.h +++ b/yql/essentials/sql/v1/complete/name/service/docs/name_service.h @@ -6,6 +6,6 @@ namespace NSQLComplete { - INameService::TPtr MakeDocumentingNameService(IDocumentation::TPtr docs, INameService::TPtr origin); +INameService::TPtr MakeDocumentingNameService(IDocumentation::TPtr docs, INameService::TPtr origin); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/impatient/name_service.cpp b/yql/essentials/sql/v1/complete/name/service/impatient/name_service.cpp index 11005b78f83..14ca930552f 100644 --- a/yql/essentials/sql/v1/complete/name/service/impatient/name_service.cpp +++ b/yql/essentials/sql/v1/complete/name/service/impatient/name_service.cpp @@ -2,31 +2,31 @@ namespace NSQLComplete { - namespace { - - class TNameService: public INameService { - public: - explicit TNameService(INameService::TPtr origin) - : Origin_(std::move(origin)) - { - } - - NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { - auto future = Origin_->Lookup(request); - if (future.IsReady()) { - return future; - } - return NThreading::MakeFuture<TNameResponse>({}); - } - - private: - INameService::TPtr Origin_; - }; - - } // namespace - - INameService::TPtr MakeImpatientNameService(INameService::TPtr origin) { - return new TNameService(std::move(origin)); +namespace { + +class TNameService: public INameService { +public: + explicit TNameService(INameService::TPtr origin) + : Origin_(std::move(origin)) + { + } + + NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { + auto future = Origin_->Lookup(request); + if (future.IsReady()) { + return future; + } + return NThreading::MakeFuture<TNameResponse>({}); } +private: + INameService::TPtr Origin_; +}; + +} // namespace + +INameService::TPtr MakeImpatientNameService(INameService::TPtr origin) { + return new TNameService(std::move(origin)); +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/impatient/name_service.h b/yql/essentials/sql/v1/complete/name/service/impatient/name_service.h index b6f02508118..54060f1cc96 100644 --- a/yql/essentials/sql/v1/complete/name/service/impatient/name_service.h +++ b/yql/essentials/sql/v1/complete/name/service/impatient/name_service.h @@ -4,6 +4,6 @@ namespace NSQLComplete { - INameService::TPtr MakeImpatientNameService(INameService::TPtr origin); +INameService::TPtr MakeImpatientNameService(INameService::TPtr origin); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/name_service.cpp b/yql/essentials/sql/v1/complete/name/service/name_service.cpp index be02583a7f3..d8138e79aab 100644 --- a/yql/essentials/sql/v1/complete/name/service/name_service.cpp +++ b/yql/essentials/sql/v1/complete/name/service/name_service.cpp @@ -2,67 +2,67 @@ namespace NSQLComplete { - namespace { +namespace { - void SetPrefix(TString& name, TStringBuf delimeter, const TNamespaced& namespaced) { - if (namespaced.Namespace.empty()) { - return; - } - - name.prepend(delimeter); - name.prepend(namespaced.Namespace); - } +void SetPrefix(TString& name, TStringBuf delimeter, const TNamespaced& namespaced) { + if (namespaced.Namespace.empty()) { + return; + } - void FixPrefix(TString& name, TStringBuf delimeter, const TNamespaced& namespaced) { - if (namespaced.Namespace.empty()) { - return; - } + name.prepend(delimeter); + name.prepend(namespaced.Namespace); +} - name.remove(0, namespaced.Namespace.size() + delimeter.size()); - } +void FixPrefix(TString& name, TStringBuf delimeter, const TNamespaced& namespaced) { + if (namespaced.Namespace.empty()) { + return; + } - } // namespace + name.remove(0, namespaced.Namespace.size() + delimeter.size()); +} - TGenericName TNameConstraints::Qualified(TGenericName unqualified) const { - return std::visit([&](auto&& name) -> TGenericName { - using T = std::decay_t<decltype(name)>; - if constexpr (std::is_same_v<T, TPragmaName>) { - SetPrefix(name.Identifier, ".", *Pragma); - } else if constexpr (std::is_same_v<T, TFunctionName>) { - SetPrefix(name.Identifier, "::", *Function); - } else if constexpr (std::is_same_v<T, TClusterName>) { - SetPrefix(name.Identifier, ":", *Cluster); - } - return name; - }, std::move(unqualified)); - } +} // namespace - TGenericName TNameConstraints::Unqualified(TGenericName qualified) const { - return std::visit([&](auto&& name) -> TGenericName { - using T = std::decay_t<decltype(name)>; - if constexpr (std::is_same_v<T, TPragmaName>) { - FixPrefix(name.Identifier, ".", *Pragma); - } else if constexpr (std::is_same_v<T, TFunctionName>) { - FixPrefix(name.Identifier, "::", *Function); - } else if constexpr (std::is_same_v<T, TClusterName>) { - FixPrefix(name.Identifier, ":", *Cluster); - } - return name; - }, std::move(qualified)); - } +TGenericName TNameConstraints::Qualified(TGenericName unqualified) const { + return std::visit([&](auto&& name) -> TGenericName { + using T = std::decay_t<decltype(name)>; + if constexpr (std::is_same_v<T, TPragmaName>) { + SetPrefix(name.Identifier, ".", *Pragma); + } else if constexpr (std::is_same_v<T, TFunctionName>) { + SetPrefix(name.Identifier, "::", *Function); + } else if constexpr (std::is_same_v<T, TClusterName>) { + SetPrefix(name.Identifier, ":", *Cluster); + } + return name; + }, std::move(unqualified)); +} - TVector<TGenericName> TNameConstraints::Qualified(TVector<TGenericName> unqualified) const { - for (auto& name : unqualified) { - name = Qualified(std::move(name)); +TGenericName TNameConstraints::Unqualified(TGenericName qualified) const { + return std::visit([&](auto&& name) -> TGenericName { + using T = std::decay_t<decltype(name)>; + if constexpr (std::is_same_v<T, TPragmaName>) { + FixPrefix(name.Identifier, ".", *Pragma); + } else if constexpr (std::is_same_v<T, TFunctionName>) { + FixPrefix(name.Identifier, "::", *Function); + } else if constexpr (std::is_same_v<T, TClusterName>) { + FixPrefix(name.Identifier, ":", *Cluster); } - return unqualified; + return name; + }, std::move(qualified)); +} + +TVector<TGenericName> TNameConstraints::Qualified(TVector<TGenericName> unqualified) const { + for (auto& name : unqualified) { + name = Qualified(std::move(name)); } + return unqualified; +} - TVector<TGenericName> TNameConstraints::Unqualified(TVector<TGenericName> qualified) const { - for (auto& name : qualified) { - name = Unqualified(std::move(name)); - } - return qualified; +TVector<TGenericName> TNameConstraints::Unqualified(TVector<TGenericName> qualified) const { + for (auto& name : qualified) { + name = Unqualified(std::move(name)); } + return qualified; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/name_service.h b/yql/essentials/sql/v1/complete/name/service/name_service.h index 9b3d01e2fab..8487d96a6f1 100644 --- a/yql/essentials/sql/v1/complete/name/service/name_service.h +++ b/yql/essentials/sql/v1/complete/name/service/name_service.h @@ -12,147 +12,147 @@ namespace NSQLComplete { - struct TIdentifier { - TString Identifier; - }; +struct TIdentifier { + TString Identifier; +}; - struct TNamespaced { - TString Namespace; - }; +struct TNamespaced { + TString Namespace; +}; - struct TDescribed { - TMaybe<TString> Description; - }; +struct TDescribed { + TMaybe<TString> Description; +}; - struct TKeyword { - TString Content; - }; +struct TKeyword { + TString Content; +}; - struct TPragmaName: TIdentifier { - struct TConstraints: TNamespaced {}; - }; - - struct TTypeName: TIdentifier, TDescribed { - struct TConstraints {}; +struct TPragmaName: TIdentifier { + struct TConstraints: TNamespaced {}; +}; - enum class EKind { - Simple, - Container, - Parameterized, - }; +struct TTypeName: TIdentifier, TDescribed { + struct TConstraints {}; - EKind Kind = EKind::Simple; + enum class EKind { + Simple, + Container, + Parameterized, }; - struct TFunctionName: TIdentifier, TDescribed { - struct TConstraints: TNamespaced { - ENodeKind ReturnType; - }; - }; + EKind Kind = EKind::Simple; +}; - struct THintName: TIdentifier { - struct TConstraints { - EStatementKind Statement; - }; +struct TFunctionName: TIdentifier, TDescribed { + struct TConstraints: TNamespaced { + ENodeKind ReturnType; }; +}; - struct TObjectNameConstraints { - TString Provider; - TString Cluster; - THashSet<EObjectKind> Kinds; +struct THintName: TIdentifier { + struct TConstraints { + EStatementKind Statement; }; +}; - struct TFolderName: TIdentifier { - }; +struct TObjectNameConstraints { + TString Provider; + TString Cluster; + THashSet<EObjectKind> Kinds; +}; - struct TTableName: TIdentifier { - }; +struct TFolderName: TIdentifier { +}; - struct TClusterName: TIdentifier { - struct TConstraints: TNamespaced {}; - }; +struct TTableName: TIdentifier { +}; - struct TColumnName: TIdentifier { - struct TConstraints { - TString TableAlias; - TVector<TAliased<TTableId>> Tables; - THashMap<TString, THashSet<TString>> WithoutByTableAlias; - }; +struct TClusterName: TIdentifier { + struct TConstraints: TNamespaced {}; +}; +struct TColumnName: TIdentifier { + struct TConstraints { TString TableAlias; - }; - - struct TBindingName: TIdentifier { - }; - - struct TUnknownName { - TString Content; - TString Type; - }; - - using TGenericName = std::variant< - TKeyword, - TPragmaName, - TTypeName, - TFunctionName, - THintName, - TFolderName, - TTableName, - TClusterName, - TColumnName, - TBindingName, - TUnknownName>; - - struct TNameConstraints { - TMaybe<TPragmaName::TConstraints> Pragma; - TMaybe<TTypeName::TConstraints> Type; - TMaybe<TFunctionName::TConstraints> Function; - TMaybe<THintName::TConstraints> Hint; - TMaybe<TObjectNameConstraints> Object; - TMaybe<TClusterName::TConstraints> Cluster; - TMaybe<TColumnName::TConstraints> Column; - - bool IsEmpty() const { - return !Pragma && - !Type && - !Function && - !Hint && - !Object && - !Cluster && - !Column; - } - - TGenericName Qualified(TGenericName unqualified) const; - TGenericName Unqualified(TGenericName qualified) const; - TVector<TGenericName> Qualified(TVector<TGenericName> unqualified) const; - TVector<TGenericName> Unqualified(TVector<TGenericName> qualified) const; - }; - - struct TNameRequest { - TVector<TString> Keywords; - TNameConstraints Constraints; - TString Prefix = ""; - size_t Limit = 128; - - bool IsEmpty() const { - return Keywords.empty() && Constraints.IsEmpty(); - } - }; - - struct TNameResponse { - TVector<TGenericName> RankedNames; - TMaybe<size_t> NameHintLength = Nothing(); - - bool IsEmpty() const { - return RankedNames.empty(); - } - }; - - class INameService: public TThrRefBase { - public: - using TPtr = TIntrusivePtr<INameService>; - - virtual NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const = 0; - }; + TVector<TAliased<TTableId>> Tables; + THashMap<TString, THashSet<TString>> WithoutByTableAlias; + }; + + TString TableAlias; +}; + +struct TBindingName: TIdentifier { +}; + +struct TUnknownName { + TString Content; + TString Type; +}; + +using TGenericName = std::variant< + TKeyword, + TPragmaName, + TTypeName, + TFunctionName, + THintName, + TFolderName, + TTableName, + TClusterName, + TColumnName, + TBindingName, + TUnknownName>; + +struct TNameConstraints { + TMaybe<TPragmaName::TConstraints> Pragma; + TMaybe<TTypeName::TConstraints> Type; + TMaybe<TFunctionName::TConstraints> Function; + TMaybe<THintName::TConstraints> Hint; + TMaybe<TObjectNameConstraints> Object; + TMaybe<TClusterName::TConstraints> Cluster; + TMaybe<TColumnName::TConstraints> Column; + + bool IsEmpty() const { + return !Pragma && + !Type && + !Function && + !Hint && + !Object && + !Cluster && + !Column; + } + + TGenericName Qualified(TGenericName unqualified) const; + TGenericName Unqualified(TGenericName qualified) const; + TVector<TGenericName> Qualified(TVector<TGenericName> unqualified) const; + TVector<TGenericName> Unqualified(TVector<TGenericName> qualified) const; +}; + +struct TNameRequest { + TVector<TString> Keywords; + TNameConstraints Constraints; + TString Prefix = ""; + size_t Limit = 128; + + bool IsEmpty() const { + return Keywords.empty() && Constraints.IsEmpty(); + } +}; + +struct TNameResponse { + TVector<TGenericName> RankedNames; + TMaybe<size_t> NameHintLength = Nothing(); + + bool IsEmpty() const { + return RankedNames.empty(); + } +}; + +class INameService: public TThrRefBase { +public: + using TPtr = TIntrusivePtr<INameService>; + + virtual NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const = 0; +}; } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/ranking/dummy.cpp b/yql/essentials/sql/v1/complete/name/service/ranking/dummy.cpp index c8dc320cc73..89258599aa7 100644 --- a/yql/essentials/sql/v1/complete/name/service/ranking/dummy.cpp +++ b/yql/essentials/sql/v1/complete/name/service/ranking/dummy.cpp @@ -2,22 +2,22 @@ namespace NSQLComplete { - namespace { +namespace { - class TRanking: public IRanking { - public: - void CropToSortedPrefix( - TVector<TGenericName>& names, - const TNameConstraints& /* constraints */, - size_t limit) const override { - names.crop(limit); - } - }; +class TRanking: public IRanking { +public: + void CropToSortedPrefix( + TVector<TGenericName>& names, + const TNameConstraints& /* constraints */, + size_t limit) const override { + names.crop(limit); + } +}; - } // namespace +} // namespace - IRanking::TPtr MakeDummyRanking() { - return new TRanking(); - } +IRanking::TPtr MakeDummyRanking() { + return new TRanking(); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/ranking/dummy.h b/yql/essentials/sql/v1/complete/name/service/ranking/dummy.h index f9f024fe7ab..9fa441946fb 100644 --- a/yql/essentials/sql/v1/complete/name/service/ranking/dummy.h +++ b/yql/essentials/sql/v1/complete/name/service/ranking/dummy.h @@ -4,6 +4,6 @@ namespace NSQLComplete { - IRanking::TPtr MakeDummyRanking(); +IRanking::TPtr MakeDummyRanking(); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/ranking/frequency.cpp b/yql/essentials/sql/v1/complete/name/service/ranking/frequency.cpp index 9c5f0cadefe..5ae3bc8231e 100644 --- a/yql/essentials/sql/v1/complete/name/service/ranking/frequency.cpp +++ b/yql/essentials/sql/v1/complete/name/service/ranking/frequency.cpp @@ -9,109 +9,109 @@ namespace NSQLComplete { - constexpr struct { - struct { - const char* Parent = "parent"; - const char* Rule = "rule"; - const char* Sum = "sum"; - } Key; - struct { - const char* Pragma = "PRAGMA"; - const char* Type = "TYPE"; - const char* Func = "FUNC"; - const char* Keyword = "KEYWORD"; - const char* Module = "MODULE"; - const char* ModuleFunc = "MODULE_FUNC"; - const char* ReadHint = "READ_HINT"; - const char* InsertHint = "INSERT_HINT"; - } Parent; - } Json; - - struct TFrequencyItem { - TString Parent; - TString Rule; - size_t Sum; - - static TFrequencyItem ParseJsonMap(NJson::TJsonValue::TMapType&& json) { - return { - .Parent = json.at(Json.Key.Parent).GetStringSafe(), - .Rule = json.at(Json.Key.Rule).GetStringSafe(), - .Sum = json.at(Json.Key.Sum).GetUIntegerSafe(), - }; - } - - static TVector<TFrequencyItem> ParseListFromJsonArray(NJson::TJsonValue::TArray& json) { - TVector<TFrequencyItem> items; - items.reserve(json.size()); - for (auto& element : json) { - auto item = TFrequencyItem::ParseJsonMap(std::move(element.GetMapSafe())); - items.emplace_back(std::move(item)); - } - return items; - } - - static TVector<TFrequencyItem> ParseListFromJsonText(TStringBuf text) { - NJson::TJsonValue json = NJson::ReadJsonFastTree(text); - return ParseListFromJsonArray(json.GetArraySafe()); - } - }; - - TFrequencyData Collect(const TVector<TFrequencyItem>& items) { - TFrequencyData data; - for (auto& item : items) { - if (item.Parent == Json.Parent.Pragma) { - data.Pragmas[item.Rule] += item.Sum; - } else if (item.Parent == Json.Parent.Type) { - data.Types[item.Rule] += item.Sum; - } else if (item.Parent == Json.Parent.Keyword) { - data.Keywords[item.Rule] += item.Sum; - } else if (item.Parent == Json.Parent.Module) { - // Ignore, unsupported: Modules - } else if (item.Parent == Json.Parent.Func || - item.Parent == Json.Parent.ModuleFunc) { - data.Functions[item.Rule] += item.Sum; - } else if (item.Parent == Json.Parent.ReadHint || - item.Parent == Json.Parent.InsertHint) { - data.Hints[item.Rule] += item.Sum; - } else { - // Ignore, unsupported: Parser Call Stacks - } - } - return data; - } - - THashMap<TString, size_t> PrunedBy(const THashMap<TString, size_t>& data, auto normalize) { - THashMap<TString, size_t> pruned; - for (const auto& [name, count] : data) { - pruned[normalize(name)] += count; - } - return pruned; - } - - TFrequencyData PrunedBy(const TFrequencyData& data, auto normalize) { +constexpr struct { + struct { + const char* Parent = "parent"; + const char* Rule = "rule"; + const char* Sum = "sum"; + } Key; + struct { + const char* Pragma = "PRAGMA"; + const char* Type = "TYPE"; + const char* Func = "FUNC"; + const char* Keyword = "KEYWORD"; + const char* Module = "MODULE"; + const char* ModuleFunc = "MODULE_FUNC"; + const char* ReadHint = "READ_HINT"; + const char* InsertHint = "INSERT_HINT"; + } Parent; +} Json; + +struct TFrequencyItem { + TString Parent; + TString Rule; + size_t Sum; + + static TFrequencyItem ParseJsonMap(NJson::TJsonValue::TMapType&& json) { return { - .Keywords = PrunedBy(data.Keywords, normalize), - .Pragmas = PrunedBy(data.Pragmas, normalize), - .Types = PrunedBy(data.Types, normalize), - .Functions = PrunedBy(data.Functions, normalize), - .Hints = PrunedBy(data.Hints, normalize), + .Parent = json.at(Json.Key.Parent).GetStringSafe(), + .Rule = json.at(Json.Key.Rule).GetStringSafe(), + .Sum = json.at(Json.Key.Sum).GetUIntegerSafe(), }; } - TFrequencyData Pruned(const TFrequencyData& data) { - return PrunedBy(data, [](TStringBuf s) { - return NormalizeName(s); - }); + static TVector<TFrequencyItem> ParseListFromJsonArray(NJson::TJsonValue::TArray& json) { + TVector<TFrequencyItem> items; + items.reserve(json.size()); + for (auto& element : json) { + auto item = TFrequencyItem::ParseJsonMap(std::move(element.GetMapSafe())); + items.emplace_back(std::move(item)); + } + return items; } - TFrequencyData ParseJsonFrequencyData(TStringBuf text) { - return Collect(TFrequencyItem::ParseListFromJsonText(text)); + static TVector<TFrequencyItem> ParseListFromJsonText(TStringBuf text) { + NJson::TJsonValue json = NJson::ReadJsonFastTree(text); + return ParseListFromJsonArray(json.GetArraySafe()); + } +}; + +TFrequencyData Collect(const TVector<TFrequencyItem>& items) { + TFrequencyData data; + for (auto& item : items) { + if (item.Parent == Json.Parent.Pragma) { + data.Pragmas[item.Rule] += item.Sum; + } else if (item.Parent == Json.Parent.Type) { + data.Types[item.Rule] += item.Sum; + } else if (item.Parent == Json.Parent.Keyword) { + data.Keywords[item.Rule] += item.Sum; + } else if (item.Parent == Json.Parent.Module) { + // Ignore, unsupported: Modules + } else if (item.Parent == Json.Parent.Func || + item.Parent == Json.Parent.ModuleFunc) { + data.Functions[item.Rule] += item.Sum; + } else if (item.Parent == Json.Parent.ReadHint || + item.Parent == Json.Parent.InsertHint) { + data.Hints[item.Rule] += item.Sum; + } else { + // Ignore, unsupported: Parser Call Stacks + } } + return data; +} - TFrequencyData LoadFrequencyData() { - TString text; - Y_ENSURE(NResource::FindExact("rules_corr_basic.json", &text)); - return ParseJsonFrequencyData(text); +THashMap<TString, size_t> PrunedBy(const THashMap<TString, size_t>& data, auto normalize) { + THashMap<TString, size_t> pruned; + for (const auto& [name, count] : data) { + pruned[normalize(name)] += count; } + return pruned; +} + +TFrequencyData PrunedBy(const TFrequencyData& data, auto normalize) { + return { + .Keywords = PrunedBy(data.Keywords, normalize), + .Pragmas = PrunedBy(data.Pragmas, normalize), + .Types = PrunedBy(data.Types, normalize), + .Functions = PrunedBy(data.Functions, normalize), + .Hints = PrunedBy(data.Hints, normalize), + }; +} + +TFrequencyData Pruned(const TFrequencyData& data) { + return PrunedBy(data, [](TStringBuf s) { + return NormalizeName(s); + }); +} + +TFrequencyData ParseJsonFrequencyData(TStringBuf text) { + return Collect(TFrequencyItem::ParseListFromJsonText(text)); +} + +TFrequencyData LoadFrequencyData() { + TString text; + Y_ENSURE(NResource::FindExact("rules_corr_basic.json", &text)); + return ParseJsonFrequencyData(text); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/ranking/frequency.h b/yql/essentials/sql/v1/complete/name/service/ranking/frequency.h index 92a5ca6b810..566cd2ed54c 100644 --- a/yql/essentials/sql/v1/complete/name/service/ranking/frequency.h +++ b/yql/essentials/sql/v1/complete/name/service/ranking/frequency.h @@ -5,18 +5,18 @@ namespace NSQLComplete { - struct TFrequencyData { - THashMap<TString, size_t> Keywords; - THashMap<TString, size_t> Pragmas; - THashMap<TString, size_t> Types; - THashMap<TString, size_t> Functions; - THashMap<TString, size_t> Hints; - }; +struct TFrequencyData { + THashMap<TString, size_t> Keywords; + THashMap<TString, size_t> Pragmas; + THashMap<TString, size_t> Types; + THashMap<TString, size_t> Functions; + THashMap<TString, size_t> Hints; +}; - TFrequencyData Pruned(const TFrequencyData& data); +TFrequencyData Pruned(const TFrequencyData& data); - TFrequencyData ParseJsonFrequencyData(TStringBuf text); +TFrequencyData ParseJsonFrequencyData(TStringBuf text); - TFrequencyData LoadFrequencyData(); +TFrequencyData LoadFrequencyData(); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/ranking/frequency_ut.cpp b/yql/essentials/sql/v1/complete/name/service/ranking/frequency_ut.cpp index 725abfc562d..b865e0799cc 100644 --- a/yql/essentials/sql/v1/complete/name/service/ranking/frequency_ut.cpp +++ b/yql/essentials/sql/v1/complete/name/service/ranking/frequency_ut.cpp @@ -6,8 +6,8 @@ using namespace NSQLComplete; Y_UNIT_TEST_SUITE(FrequencyTests) { - Y_UNIT_TEST(FrequencyDataJson) { - TFrequencyData actual = Pruned(ParseJsonFrequencyData(R"([ +Y_UNIT_TEST(FrequencyDataJson) { + TFrequencyData actual = Pruned(ParseJsonFrequencyData(R"([ {"parent":"FUNC","rule":"ABC","sum":1}, {"parent":"TYPE","rule":"BIGINT","sum":7101}, {"parent":"KEYWORD","rule":"UNION","sum":65064443}, @@ -18,32 +18,32 @@ Y_UNIT_TEST_SUITE(FrequencyTests) { {"parent":"TRule_action_or_subquery_args","rule":"TRule_action_or_subquery_args.Block2","sum":4874480} ])")); - TFrequencyData expected = { - .Keywords = { - {"union", 65064443}, - }, - .Types = { - {"bigint", 7101}, - }, - .Functions = { - {"abc", 1}, - {"compress::bzip2", 2}, - }, - .Hints = { - {"columns", 826110}, - {"columngroups", 225}, - }, - }; - - UNIT_ASSERT_VALUES_EQUAL(actual.Keywords, expected.Keywords); - UNIT_ASSERT_VALUES_EQUAL(actual.Types, expected.Types); - UNIT_ASSERT_VALUES_EQUAL(actual.Functions, expected.Functions); - UNIT_ASSERT_VALUES_EQUAL(actual.Hints, expected.Hints); - } - - Y_UNIT_TEST(FrequencyDataResouce) { - TFrequencyData data = LoadFrequencyData(); - Y_UNUSED(data); - } + TFrequencyData expected = { + .Keywords = { + {"union", 65064443}, + }, + .Types = { + {"bigint", 7101}, + }, + .Functions = { + {"abc", 1}, + {"compress::bzip2", 2}, + }, + .Hints = { + {"columns", 826110}, + {"columngroups", 225}, + }, + }; + + UNIT_ASSERT_VALUES_EQUAL(actual.Keywords, expected.Keywords); + UNIT_ASSERT_VALUES_EQUAL(actual.Types, expected.Types); + UNIT_ASSERT_VALUES_EQUAL(actual.Functions, expected.Functions); + UNIT_ASSERT_VALUES_EQUAL(actual.Hints, expected.Hints); +} + +Y_UNIT_TEST(FrequencyDataResouce) { + TFrequencyData data = LoadFrequencyData(); + Y_UNUSED(data); +} } // Y_UNIT_TEST_SUITE(FrequencyTests) diff --git a/yql/essentials/sql/v1/complete/name/service/ranking/ranking.cpp b/yql/essentials/sql/v1/complete/name/service/ranking/ranking.cpp index 2e00224f768..ea7c0504a6a 100644 --- a/yql/essentials/sql/v1/complete/name/service/ranking/ranking.cpp +++ b/yql/essentials/sql/v1/complete/name/service/ranking/ranking.cpp @@ -6,140 +6,140 @@ namespace NSQLComplete { - class TRanking: public IRanking { - private: - struct TRow { - TGenericName Name; - size_t Weight; - }; - - public: - explicit TRanking(TFrequencyData frequency) - : Frequency_(std::move(frequency)) - { - } +class TRanking: public IRanking { +private: + struct TRow { + TGenericName Name; + size_t Weight; + }; - void CropToSortedPrefix( - TVector<TGenericName>& names, - const TNameConstraints& constraints, - size_t limit) const override { - limit = Min(limit, names.size()); - - TVector<TRow> rows; - rows.reserve(names.size()); - for (TGenericName& name : names) { - name = constraints.Qualified(std::move(name)); - size_t weight = Weight(name); - rows.emplace_back(std::move(name), weight); - } +public: + explicit TRanking(TFrequencyData frequency) + : Frequency_(std::move(frequency)) + { + } - ::PartialSort( - std::begin(rows), std::begin(rows) + limit, std::end(rows), - [this](const TRow& lhs, const TRow& rhs) { - const size_t lhs_weight = ReversedWeight(lhs.Weight); - const auto lhs_content = ContentView(lhs.Name); + void CropToSortedPrefix( + TVector<TGenericName>& names, + const TNameConstraints& constraints, + size_t limit) const override { + limit = Min(limit, names.size()); + + TVector<TRow> rows; + rows.reserve(names.size()); + for (TGenericName& name : names) { + name = constraints.Qualified(std::move(name)); + size_t weight = Weight(name); + rows.emplace_back(std::move(name), weight); + } - const size_t rhs_weight = ReversedWeight(rhs.Weight); - const auto rhs_content = ContentView(rhs.Name); + ::PartialSort( + std::begin(rows), std::begin(rows) + limit, std::end(rows), + [this](const TRow& lhs, const TRow& rhs) { + const size_t lhs_weight = ReversedWeight(lhs.Weight); + const auto lhs_content = ContentView(lhs.Name); - return std::tie(lhs_weight, lhs_content) < - std::tie(rhs_weight, rhs_content); - }); + const size_t rhs_weight = ReversedWeight(rhs.Weight); + const auto rhs_content = ContentView(rhs.Name); - names.crop(limit); - rows.crop(limit); + return std::tie(lhs_weight, lhs_content) < + std::tie(rhs_weight, rhs_content); + }); - for (size_t i = 0; i < limit; ++i) { - names[i] = constraints.Unqualified(std::move(rows[i].Name)); - } + names.crop(limit); + rows.crop(limit); + + for (size_t i = 0; i < limit; ++i) { + names[i] = constraints.Unqualified(std::move(rows[i].Name)); } + } - private: - size_t Weight(const TGenericName& name) const { - return std::visit([this](const auto& name) -> size_t { - using T = std::decay_t<decltype(name)>; +private: + size_t Weight(const TGenericName& name) const { + return std::visit([this](const auto& name) -> size_t { + using T = std::decay_t<decltype(name)>; - TString content = NormalizeName(ContentView(name).first); + TString content = NormalizeName(ContentView(name).first); - if constexpr (std::is_same_v<T, TKeyword>) { - if (auto weight = Frequency_.Keywords.FindPtr(content)) { - return *weight; - } + if constexpr (std::is_same_v<T, TKeyword>) { + if (auto weight = Frequency_.Keywords.FindPtr(content)) { + return *weight; } + } - if constexpr (std::is_same_v<T, TPragmaName>) { - if (auto weight = Frequency_.Pragmas.FindPtr(content)) { - return *weight; - } + if constexpr (std::is_same_v<T, TPragmaName>) { + if (auto weight = Frequency_.Pragmas.FindPtr(content)) { + return *weight; } + } - if constexpr (std::is_same_v<T, TFunctionName>) { - if (auto weight = Frequency_.Functions.FindPtr(content)) { - return *weight; - } + if constexpr (std::is_same_v<T, TFunctionName>) { + if (auto weight = Frequency_.Functions.FindPtr(content)) { + return *weight; } + } - if constexpr (std::is_same_v<T, TTypeName>) { - if (auto weight = Frequency_.Types.FindPtr(content)) { - return *weight; - } + if constexpr (std::is_same_v<T, TTypeName>) { + if (auto weight = Frequency_.Types.FindPtr(content)) { + return *weight; } + } - if constexpr (std::is_same_v<T, THintName>) { - if (auto weight = Frequency_.Hints.FindPtr(content)) { - return *weight; - } + if constexpr (std::is_same_v<T, THintName>) { + if (auto weight = Frequency_.Hints.FindPtr(content)) { + return *weight; } + } - if constexpr (std::is_same_v<T, TFolderName> || - std::is_same_v<T, TTableName> || - std::is_same_v<T, TColumnName>) { - return std::numeric_limits<size_t>::max(); - } + if constexpr (std::is_same_v<T, TFolderName> || + std::is_same_v<T, TTableName> || + std::is_same_v<T, TColumnName>) { + return std::numeric_limits<size_t>::max(); + } - if constexpr (std::is_same_v<T, TBindingName>) { - return std::numeric_limits<size_t>::max() - 4; - } + if constexpr (std::is_same_v<T, TBindingName>) { + return std::numeric_limits<size_t>::max() - 4; + } - if constexpr (std::is_same_v<T, TClusterName>) { - return std::numeric_limits<size_t>::max() - 8; - } + if constexpr (std::is_same_v<T, TClusterName>) { + return std::numeric_limits<size_t>::max() - 8; + } - return 0; - }, name); - } + return 0; + }, name); + } - static size_t ReversedWeight(size_t weight) { - return std::numeric_limits<size_t>::max() - weight; - } + static size_t ReversedWeight(size_t weight) { + return std::numeric_limits<size_t>::max() - weight; + } - std::pair<TStringBuf, TStringBuf> ContentView(const TGenericName& name Y_LIFETIME_BOUND) const { - return std::visit([](const auto& name) -> std::pair<TStringBuf, TStringBuf> { - using T = std::decay_t<decltype(name)>; - if constexpr (std::is_base_of_v<TKeyword, T>) { - return {name.Content, ""}; - } - if constexpr (std::is_base_of_v<TColumnName, T>) { - return {name.TableAlias, name.Identifier}; - } - if constexpr (std::is_base_of_v<TIdentifier, T>) { - return {name.Identifier, ""}; - } - if constexpr (std::is_base_of_v<TUnknownName, T>) { - return {name.Content, ""}; - } - }, name); - } + std::pair<TStringBuf, TStringBuf> ContentView(const TGenericName& name Y_LIFETIME_BOUND) const { + return std::visit([](const auto& name) -> std::pair<TStringBuf, TStringBuf> { + using T = std::decay_t<decltype(name)>; + if constexpr (std::is_base_of_v<TKeyword, T>) { + return {name.Content, ""}; + } + if constexpr (std::is_base_of_v<TColumnName, T>) { + return {name.TableAlias, name.Identifier}; + } + if constexpr (std::is_base_of_v<TIdentifier, T>) { + return {name.Identifier, ""}; + } + if constexpr (std::is_base_of_v<TUnknownName, T>) { + return {name.Content, ""}; + } + }, name); + } - TFrequencyData Frequency_; - }; + TFrequencyData Frequency_; +}; - IRanking::TPtr MakeDefaultRanking() { - return MakeDefaultRanking(LoadFrequencyData()); - } +IRanking::TPtr MakeDefaultRanking() { + return MakeDefaultRanking(LoadFrequencyData()); +} - IRanking::TPtr MakeDefaultRanking(const TFrequencyData& frequency) { - return MakeIntrusive<TRanking>(Pruned(frequency)); - } +IRanking::TPtr MakeDefaultRanking(const TFrequencyData& frequency) { + return MakeIntrusive<TRanking>(Pruned(frequency)); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/ranking/ranking.h b/yql/essentials/sql/v1/complete/name/service/ranking/ranking.h index 5fadad65f8b..3c6c5cdb350 100644 --- a/yql/essentials/sql/v1/complete/name/service/ranking/ranking.h +++ b/yql/essentials/sql/v1/complete/name/service/ranking/ranking.h @@ -7,20 +7,20 @@ namespace NSQLComplete { - class IRanking: public TThrRefBase { - public: - using TPtr = TIntrusivePtr<IRanking>; +class IRanking: public TThrRefBase { +public: + using TPtr = TIntrusivePtr<IRanking>; - ~IRanking() override = default; - virtual void CropToSortedPrefix( - TVector<TGenericName>& names, - const TNameConstraints& constraints, - size_t limit) const = 0; - }; + ~IRanking() override = default; + virtual void CropToSortedPrefix( + TVector<TGenericName>& names, + const TNameConstraints& constraints, + size_t limit) const = 0; +}; - // TODO(YQL-19747): Migrate YDB CLI to MakeDefaultRanking(...) - IRanking::TPtr MakeDefaultRanking(); +// TODO(YQL-19747): Migrate YDB CLI to MakeDefaultRanking(...) +IRanking::TPtr MakeDefaultRanking(); - IRanking::TPtr MakeDefaultRanking(const TFrequencyData& frequency); +IRanking::TPtr MakeDefaultRanking(const TFrequencyData& frequency); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/ranking/ranking_ut.cpp b/yql/essentials/sql/v1/complete/name/service/ranking/ranking_ut.cpp index af89d666f77..ea968d7df86 100644 --- a/yql/essentials/sql/v1/complete/name/service/ranking/ranking_ut.cpp +++ b/yql/essentials/sql/v1/complete/name/service/ranking/ranking_ut.cpp @@ -6,9 +6,9 @@ using namespace NSQLComplete; Y_UNIT_TEST_SUITE(RankingTests) { - Y_UNIT_TEST(RankingIsBuilt) { - auto ranking = MakeDefaultRanking(LoadFrequencyData()); - Y_DO_NOT_OPTIMIZE_AWAY(ranking); - } +Y_UNIT_TEST(RankingIsBuilt) { + auto ranking = MakeDefaultRanking(LoadFrequencyData()); + Y_DO_NOT_OPTIMIZE_AWAY(ranking); +} } // Y_UNIT_TEST_SUITE(RankingTests) diff --git a/yql/essentials/sql/v1/complete/name/service/schema/name_service.cpp b/yql/essentials/sql/v1/complete/name/service/schema/name_service.cpp index dafc1e4113a..a31660e613e 100644 --- a/yql/essentials/sql/v1/complete/name/service/schema/name_service.cpp +++ b/yql/essentials/sql/v1/complete/name/service/schema/name_service.cpp @@ -5,176 +5,176 @@ namespace NSQLComplete { - namespace { +namespace { - class TNameService: public INameService { - public: - explicit TNameService(ISchema::TPtr schema) - : Schema_(std::move(schema)) - { - } +class TNameService: public INameService { +public: + explicit TNameService(ISchema::TPtr schema) + : Schema_(std::move(schema)) + { + } - NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { - if (request.Constraints.Object) { - return Schema_ - ->List(ToListRequest(std::move(request))) - .Apply(ToListNameResponse); - } + NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { + if (request.Constraints.Object) { + return Schema_ + ->List(ToListRequest(std::move(request))) + .Apply(ToListNameResponse); + } + + if (request.Constraints.Column && !request.Constraints.Column->Tables.empty()) { + return BatchDescribe( + std::move(request.Constraints.Column->Tables), + std::move(request.Constraints.Column->WithoutByTableAlias), + request.Prefix, + request.Limit); + } + + return NThreading::MakeFuture<TNameResponse>({}); + } - if (request.Constraints.Column && !request.Constraints.Column->Tables.empty()) { - return BatchDescribe( - std::move(request.Constraints.Column->Tables), - std::move(request.Constraints.Column->WithoutByTableAlias), - request.Prefix, - request.Limit); +private: + NThreading::TFuture<TNameResponse> BatchDescribe( + TVector<TAliased<TTableId>> tables, + THashMap<TString, THashSet<TString>> withoutByTableAlias, + TString prefix, + ui64 limit) const { + THashMap<TTableId, TVector<TString>> aliasesByTable; + for (TAliased<TTableId> table : std::move(tables)) { + aliasesByTable[std::move(static_cast<TTableId&>(table))] + .emplace_back(std::move(table.Alias)); + } + + THashMap<TTableId, NThreading::TFuture<TDescribeTableResponse>> futuresByTable; + for (const auto& [table, aliases] : aliasesByTable) { + TString columnPrefix = prefix; + for (const auto& alias : aliases) { + if (alias.StartsWith(prefix)) { + columnPrefix = ""; + break; } - - return NThreading::MakeFuture<TNameResponse>({}); } - private: - NThreading::TFuture<TNameResponse> BatchDescribe( - TVector<TAliased<TTableId>> tables, - THashMap<TString, THashSet<TString>> withoutByTableAlias, - TString prefix, - ui64 limit) const { - THashMap<TTableId, TVector<TString>> aliasesByTable; - for (TAliased<TTableId> table : std::move(tables)) { - aliasesByTable[std::move(static_cast<TTableId&>(table))] - .emplace_back(std::move(table.Alias)); - } + TDescribeTableRequest request = { + .TableCluster = table.Cluster, + .TablePath = table.Path, + .ColumnPrefix = columnPrefix, + .ColumnsLimit = limit, + }; - THashMap<TTableId, NThreading::TFuture<TDescribeTableResponse>> futuresByTable; - for (const auto& [table, aliases] : aliasesByTable) { - TString columnPrefix = prefix; - for (const auto& alias : aliases) { - if (alias.StartsWith(prefix)) { - columnPrefix = ""; - break; - } - } + futuresByTable.emplace(table, Schema_->Describe(request)); + } - TDescribeTableRequest request = { - .TableCluster = table.Cluster, - .TablePath = table.Path, - .ColumnPrefix = columnPrefix, - .ColumnsLimit = limit, - }; + auto futuresIt = IterateValues(futuresByTable); + TVector<NThreading::TFuture<TDescribeTableResponse>> futures(begin(futuresIt), end(futuresIt)); - futuresByTable.emplace(table, Schema_->Describe(request)); - } + return NThreading::WaitAll(std::move(futures)) + .Apply([aliasesByTable = std::move(aliasesByTable), + futuresByTable = std::move(futuresByTable), + withoutByTableAlias = std::move(withoutByTableAlias)](auto) mutable { + TNameResponse response; - auto futuresIt = IterateValues(futuresByTable); - TVector<NThreading::TFuture<TDescribeTableResponse>> futures(begin(futuresIt), end(futuresIt)); - - return NThreading::WaitAll(std::move(futures)) - .Apply([aliasesByTable = std::move(aliasesByTable), - futuresByTable = std::move(futuresByTable), - withoutByTableAlias = std::move(withoutByTableAlias)](auto) mutable { - TNameResponse response; - - for (auto [table, f] : futuresByTable) { - TDescribeTableResponse description = f.ExtractValue(); - for (const TString& column : description.Columns) { - const auto& aliases = aliasesByTable[table]; - for (const TString& alias : aliases) { - if ((withoutByTableAlias[alias].contains(column)) || - (alias.empty() && 1 < aliases.size())) { - continue; - } - - TColumnName name; - name.Identifier = column; - name.TableAlias = alias; - - response.RankedNames.emplace_back(std::move(name)); - } + for (auto [table, f] : futuresByTable) { + TDescribeTableResponse description = f.ExtractValue(); + for (const TString& column : description.Columns) { + const auto& aliases = aliasesByTable[table]; + for (const TString& alias : aliases) { + if ((withoutByTableAlias[alias].contains(column)) || + (alias.empty() && 1 < aliases.size())) { + continue; } - } - return response; - }); - } + TColumnName name; + name.Identifier = column; + name.TableAlias = alias; - static TListRequest ToListRequest(const TNameRequest& request) { - return { - .Cluster = ClusterName(*request.Constraints.Object), - .Path = request.Prefix, - .Filter = ToListFilter(request.Constraints), - .Limit = request.Limit, - }; - } + response.RankedNames.emplace_back(std::move(name)); + } + } + } - static TString ClusterName(const TObjectNameConstraints& constraints) { - return constraints.Cluster; - } + return response; + }); + } + + static TListRequest ToListRequest(const TNameRequest& request) { + return { + .Cluster = ClusterName(*request.Constraints.Object), + .Path = request.Prefix, + .Filter = ToListFilter(request.Constraints), + .Limit = request.Limit, + }; + } - static TListFilter ToListFilter(const TNameConstraints& constraints) { - const auto& kinds = constraints.Object->Kinds; + static TString ClusterName(const TObjectNameConstraints& constraints) { + return constraints.Cluster; + } - TListFilter filter; - filter.Types = THashSet<TString>(); - filter.IsUnknownAllowed = kinds.contains(EObjectKind::Unknown); - for (EObjectKind kind : kinds) { - if (kind == EObjectKind::Unknown) { - continue; - } + static TListFilter ToListFilter(const TNameConstraints& constraints) { + const auto& kinds = constraints.Object->Kinds; - filter.Types->emplace(ToFolderEntry(kind)); - } - return filter; + TListFilter filter; + filter.Types = THashSet<TString>(); + filter.IsUnknownAllowed = kinds.contains(EObjectKind::Unknown); + for (EObjectKind kind : kinds) { + if (kind == EObjectKind::Unknown) { + continue; } - static TString ToFolderEntry(EObjectKind kind) { - switch (kind) { - case EObjectKind::Folder: - return TFolderEntry::Folder; - case EObjectKind::Table: - return TFolderEntry::Table; - case EObjectKind::Unknown: - ythrow yexception() - << "Unknown is a type class and " - << "can not be a folder entry"; - } - } + filter.Types->emplace(ToFolderEntry(kind)); + } + return filter; + } - static TNameResponse ToListNameResponse(NThreading::TFuture<TListResponse> f) { - TListResponse list = f.ExtractValue(); + static TString ToFolderEntry(EObjectKind kind) { + switch (kind) { + case EObjectKind::Folder: + return TFolderEntry::Folder; + case EObjectKind::Table: + return TFolderEntry::Table; + case EObjectKind::Unknown: + ythrow yexception() + << "Unknown is a type class and " + << "can not be a folder entry"; + } + } - TNameResponse response; - for (auto& entry : list.Entries) { - response.RankedNames.emplace_back(ToGenericName(std::move(entry))); - } - response.NameHintLength = list.NameHintLength; - return response; - } + static TNameResponse ToListNameResponse(NThreading::TFuture<TListResponse> f) { + TListResponse list = f.ExtractValue(); - static TGenericName ToGenericName(TFolderEntry entry) { - TGenericName name; - if (entry.Type == TFolderEntry::Folder) { - TFolderName local; - local.Identifier = std::move(entry.Name); - name = std::move(local); - } else if (entry.Type == TFolderEntry::Table) { - TTableName local; - local.Identifier = std::move(entry.Name); - name = std::move(local); - } else { - TUnknownName local; - local.Content = std::move(entry.Name); - local.Type = std::move(entry.Type); - name = std::move(local); - } - return name; - } + TNameResponse response; + for (auto& entry : list.Entries) { + response.RankedNames.emplace_back(ToGenericName(std::move(entry))); + } + response.NameHintLength = list.NameHintLength; + return response; + } - ISchema::TPtr Schema_; - }; + static TGenericName ToGenericName(TFolderEntry entry) { + TGenericName name; + if (entry.Type == TFolderEntry::Folder) { + TFolderName local; + local.Identifier = std::move(entry.Name); + name = std::move(local); + } else if (entry.Type == TFolderEntry::Table) { + TTableName local; + local.Identifier = std::move(entry.Name); + name = std::move(local); + } else { + TUnknownName local; + local.Content = std::move(entry.Name); + local.Type = std::move(entry.Type); + name = std::move(local); + } + return name; + } - } // namespace + ISchema::TPtr Schema_; +}; - INameService::TPtr MakeSchemaNameService(ISchema::TPtr schema) { - return new TNameService(std::move(schema)); - } +} // namespace + +INameService::TPtr MakeSchemaNameService(ISchema::TPtr schema) { + return new TNameService(std::move(schema)); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/schema/name_service.h b/yql/essentials/sql/v1/complete/name/service/schema/name_service.h index aa2d7eb7f31..a468c08f8c5 100644 --- a/yql/essentials/sql/v1/complete/name/service/schema/name_service.h +++ b/yql/essentials/sql/v1/complete/name/service/schema/name_service.h @@ -5,6 +5,6 @@ namespace NSQLComplete { - INameService::TPtr MakeSchemaNameService(ISchema::TPtr schema); +INameService::TPtr MakeSchemaNameService(ISchema::TPtr schema); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/static/name_index.h b/yql/essentials/sql/v1/complete/name/service/static/name_index.h index 271d7beca48..853303ff341 100644 --- a/yql/essentials/sql/v1/complete/name/service/static/name_index.h +++ b/yql/essentials/sql/v1/complete/name/service/static/name_index.h @@ -8,55 +8,55 @@ namespace NSQLComplete { - struct TNameIndexEntry { - TString Normalized; - TString Original; - }; +struct TNameIndexEntry { + TString Normalized; + TString Original; +}; - using TNameIndex = TVector<TNameIndexEntry>; +using TNameIndex = TVector<TNameIndexEntry>; - inline bool NameIndexCompare(const TNameIndexEntry& lhs, const TNameIndexEntry& rhs) { - return NoCaseCompare(lhs.Normalized, rhs.Normalized); - } +inline bool NameIndexCompare(const TNameIndexEntry& lhs, const TNameIndexEntry& rhs) { + return NoCaseCompare(lhs.Normalized, rhs.Normalized); +} - inline auto NameIndexCompareLimit(size_t limit) { - return [cmp = NoCaseCompareLimit(limit)](const TNameIndexEntry& lhs, const TNameIndexEntry& rhs) { - return cmp(lhs.Normalized, rhs.Normalized); +inline auto NameIndexCompareLimit(size_t limit) { + return [cmp = NoCaseCompareLimit(limit)](const TNameIndexEntry& lhs, const TNameIndexEntry& rhs) { + return cmp(lhs.Normalized, rhs.Normalized); + }; +} + +TNameIndex BuildNameIndex(TVector<TString> originals, auto normalize) { + TNameIndex index; + for (auto& original : originals) { + TNameIndexEntry entry = { + .Normalized = normalize(original), + .Original = std::move(original), }; + index.emplace_back(std::move(entry)); } - TNameIndex BuildNameIndex(TVector<TString> originals, auto normalize) { - TNameIndex index; - for (auto& original : originals) { - TNameIndexEntry entry = { - .Normalized = normalize(original), - .Original = std::move(original), - }; - index.emplace_back(std::move(entry)); - } - - Sort(index, NameIndexCompare); - return index; - } - - const TVector<TStringBuf> FilteredByPrefix( - const TString& prefix, - const TNameIndex& index Y_LIFETIME_BOUND, - auto normalize) { - TNameIndexEntry normalized = { - .Normalized = normalize(prefix), - .Original = "", - }; + Sort(index, NameIndexCompare); + return index; +} + +const TVector<TStringBuf> FilteredByPrefix( + const TString& prefix, + const TNameIndex& index Y_LIFETIME_BOUND, + auto normalize) { + TNameIndexEntry normalized = { + .Normalized = normalize(prefix), + .Original = "", + }; - auto range = std::ranges::equal_range( - std::begin(index), std::end(index), - normalized, NameIndexCompareLimit(normalized.Normalized.size())); + auto range = std::ranges::equal_range( + std::begin(index), std::end(index), + normalized, NameIndexCompareLimit(normalized.Normalized.size())); - TVector<TStringBuf> filtered; - for (const TNameIndexEntry& entry : range) { - filtered.emplace_back(TStringBuf(entry.Original)); - } - return filtered; + TVector<TStringBuf> filtered; + for (const TNameIndexEntry& entry : range) { + filtered.emplace_back(TStringBuf(entry.Original)); } + return filtered; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/static/name_service.cpp b/yql/essentials/sql/v1/complete/name/service/static/name_service.cpp index e2f5f4edfc5..8ef8169e5a0 100644 --- a/yql/essentials/sql/v1/complete/name/service/static/name_service.cpp +++ b/yql/essentials/sql/v1/complete/name/service/static/name_service.cpp @@ -8,268 +8,268 @@ namespace NSQLComplete { - const TVector<TStringBuf> FilteredByPrefix( - const TString& prefix, - const TVector<TString>& sorted Y_LIFETIME_BOUND) { - auto [first, last] = EqualRange( - std::begin(sorted), std::end(sorted), - prefix, NoCaseCompareLimit(prefix.size())); - return TVector<TStringBuf>(first, last); - } - - template <class T, class S = TStringBuf> - void AppendAs(TVector<TGenericName>& target, const TVector<S>& source) { - for (const auto& element : source) { - T name; +const TVector<TStringBuf> FilteredByPrefix( + const TString& prefix, + const TVector<TString>& sorted Y_LIFETIME_BOUND) { + auto [first, last] = EqualRange( + std::begin(sorted), std::end(sorted), + prefix, NoCaseCompareLimit(prefix.size())); + return TVector<TStringBuf>(first, last); +} + +template <class T, class S = TStringBuf> +void AppendAs(TVector<TGenericName>& target, const TVector<S>& source) { + for (const auto& element : source) { + T name; - TString* content = nullptr; - if constexpr (std::is_same_v<TKeyword, T>) { - content = &name.Content; - } else { - content = &name.Identifier; - } + TString* content = nullptr; + if constexpr (std::is_same_v<TKeyword, T>) { + content = &name.Content; + } else { + content = &name.Identifier; + } - *content = element; + *content = element; - target.emplace_back(std::move(name)); - } + target.emplace_back(std::move(name)); + } +} + +template <class T> +void NameIndexScan( + const TNameIndex& index, + const TString& prefix, + const TNameConstraints& constraints, + TVector<TGenericName>& out) { + T name; + name.Identifier = prefix; + name = std::get<T>(constraints.Qualified(std::move(name))); + + AppendAs<T>(out, FilteredByPrefix(name.Identifier, index, NormalizeName)); + out = constraints.Unqualified(std::move(out)); +} + +class IRankingNameService: public INameService { +private: + auto Ranking(const TNameRequest& request) const { + return [request, this](auto f) { + TNameResponse response = f.ExtractValue(); + Ranking_->CropToSortedPrefix( + response.RankedNames, + request.Constraints, + request.Limit); + return response; + }; } - template <class T> - void NameIndexScan( - const TNameIndex& index, - const TString& prefix, - const TNameConstraints& constraints, - TVector<TGenericName>& out) { - T name; - name.Identifier = prefix; - name = std::get<T>(constraints.Qualified(std::move(name))); +public: + explicit IRankingNameService(IRanking::TPtr ranking) + : Ranking_(std::move(ranking)) + { + } - AppendAs<T>(out, FilteredByPrefix(name.Identifier, index, NormalizeName)); - out = constraints.Unqualified(std::move(out)); + NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { + return LookupAllUnranked(request).Apply(Ranking(request)); } - class IRankingNameService: public INameService { - private: - auto Ranking(const TNameRequest& request) const { - return [request, this](auto f) { - TNameResponse response = f.ExtractValue(); - Ranking_->CropToSortedPrefix( - response.RankedNames, - request.Constraints, - request.Limit); - return response; - }; - } + virtual NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const = 0; - public: - explicit IRankingNameService(IRanking::TPtr ranking) - : Ranking_(std::move(ranking)) - { - } +private: + IRanking::TPtr Ranking_; +}; - NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { - return LookupAllUnranked(request).Apply(Ranking(request)); - } +class TKeywordNameService: public IRankingNameService { +public: + explicit TKeywordNameService(IRanking::TPtr ranking) + : IRankingNameService(std::move(ranking)) + { + } - virtual NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const = 0; + NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const override { + TVector<TString> keywords = request.Keywords; - private: - IRanking::TPtr Ranking_; - }; + TNameResponse response; + Sort(keywords, NoCaseCompare); + AppendAs<TKeyword>(response.RankedNames, FilteredByPrefix(request.Prefix, keywords)); + return NThreading::MakeFuture<TNameResponse>(std::move(response)); + } +}; + +class TPragmaNameService: public IRankingNameService { +public: + TPragmaNameService(IRanking::TPtr ranking, TVector<TString> pragmas) + : IRankingNameService(std::move(ranking)) + , Pragmas_(BuildNameIndex(std::move(pragmas), NormalizeName)) + { + } - class TKeywordNameService: public IRankingNameService { - public: - explicit TKeywordNameService(IRanking::TPtr ranking) - : IRankingNameService(std::move(ranking)) - { + NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const override { + TNameResponse response; + if (request.Constraints.Pragma) { + NameIndexScan<TPragmaName>( + Pragmas_, + request.Prefix, + request.Constraints, + response.RankedNames); } + return NThreading::MakeFuture<TNameResponse>(std::move(response)); + } - NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const override { - TVector<TString> keywords = request.Keywords; +private: + TNameIndex Pragmas_; +}; + +class TTypeNameService: public IRankingNameService { +public: + TTypeNameService(IRanking::TPtr ranking, TVector<TString> types) + : IRankingNameService(std::move(ranking)) + , SimpleTypes_(BuildNameIndex(std::move(types), NormalizeName)) + , ContainerTypes_(BuildNameIndex( + { + "Optional", + "Tuple", + "Struct", + "Variant", + "List", + "Stream", + "Flow", + "Dict", + "Set", + "Enum", + "Resource", + "Tagged", + "Callable", + }, NormalizeName)) + , ParameterizedTypes_(BuildNameIndex( + { + "Decimal", + }, NormalizeName)) + { + } - TNameResponse response; - Sort(keywords, NoCaseCompare); - AppendAs<TKeyword>(response.RankedNames, FilteredByPrefix(request.Prefix, keywords)); - return NThreading::MakeFuture<TNameResponse>(std::move(response)); - } - }; + NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const override { + TNameResponse response; + if (request.Constraints.Type) { + NameIndexScan<TTypeName>(SimpleTypes_, request.Prefix, request.Constraints, response.RankedNames); - class TPragmaNameService: public IRankingNameService { - public: - TPragmaNameService(IRanking::TPtr ranking, TVector<TString> pragmas) - : IRankingNameService(std::move(ranking)) - , Pragmas_(BuildNameIndex(std::move(pragmas), NormalizeName)) - { - } + size_t previousSize = response.RankedNames.size(); + NameIndexScan<TTypeName>(ContainerTypes_, request.Prefix, request.Constraints, response.RankedNames); + for (size_t i = previousSize; i < response.RankedNames.size(); ++i) { + std::get<TTypeName>(response.RankedNames[i]).Kind = TTypeName::EKind::Container; + } - NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const override { - TNameResponse response; - if (request.Constraints.Pragma) { - NameIndexScan<TPragmaName>( - Pragmas_, - request.Prefix, - request.Constraints, - response.RankedNames); + previousSize = response.RankedNames.size(); + NameIndexScan<TTypeName>(ParameterizedTypes_, request.Prefix, request.Constraints, response.RankedNames); + for (size_t i = previousSize; i < response.RankedNames.size(); ++i) { + std::get<TTypeName>(response.RankedNames[i]).Kind = TTypeName::EKind::Parameterized; } - return NThreading::MakeFuture<TNameResponse>(std::move(response)); } + return NThreading::MakeFuture<TNameResponse>(std::move(response)); + } - private: - TNameIndex Pragmas_; - }; - - class TTypeNameService: public IRankingNameService { - public: - TTypeNameService(IRanking::TPtr ranking, TVector<TString> types) - : IRankingNameService(std::move(ranking)) - , SimpleTypes_(BuildNameIndex(std::move(types), NormalizeName)) - , ContainerTypes_(BuildNameIndex( - { - "Optional", - "Tuple", - "Struct", - "Variant", - "List", - "Stream", - "Flow", - "Dict", - "Set", - "Enum", - "Resource", - "Tagged", - "Callable", - }, NormalizeName)) - , ParameterizedTypes_(BuildNameIndex( - { - "Decimal", - }, NormalizeName)) - { - } +private: + TNameIndex SimpleTypes_; + TNameIndex ContainerTypes_; + TNameIndex ParameterizedTypes_; +}; + +class TFunctionNameService: public IRankingNameService { +public: + TFunctionNameService(IRanking::TPtr ranking, TVector<TString> functions) + : IRankingNameService(std::move(ranking)) + , Functions_(BuildNameIndex(std::move(functions), NormalizeName)) + , TableFunctions_(BuildNameIndex( + { + "CONCAT", + "RANGE", + "LIKE", + "REGEXP", + "FILTER", + "FOLDER", + "WalkFolders", + "EACH", + "PARTITION_LIST", + }, NormalizeName)) + { + } - NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const override { - TNameResponse response; - if (request.Constraints.Type) { - NameIndexScan<TTypeName>(SimpleTypes_, request.Prefix, request.Constraints, response.RankedNames); - - size_t previousSize = response.RankedNames.size(); - NameIndexScan<TTypeName>(ContainerTypes_, request.Prefix, request.Constraints, response.RankedNames); - for (size_t i = previousSize; i < response.RankedNames.size(); ++i) { - std::get<TTypeName>(response.RankedNames[i]).Kind = TTypeName::EKind::Container; - } - - previousSize = response.RankedNames.size(); - NameIndexScan<TTypeName>(ParameterizedTypes_, request.Prefix, request.Constraints, response.RankedNames); - for (size_t i = previousSize; i < response.RankedNames.size(); ++i) { - std::get<TTypeName>(response.RankedNames[i]).Kind = TTypeName::EKind::Parameterized; - } + NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const override { + TNameResponse response; + if (auto function = request.Constraints.Function) { + const TNameIndex* index = nullptr; + switch (function->ReturnType) { + case ENodeKind::Any: { + index = &Functions_; + } break; + case ENodeKind::Table: { + index = &TableFunctions_; + } break; } - return NThreading::MakeFuture<TNameResponse>(std::move(response)); - } - private: - TNameIndex SimpleTypes_; - TNameIndex ContainerTypes_; - TNameIndex ParameterizedTypes_; - }; - - class TFunctionNameService: public IRankingNameService { - public: - TFunctionNameService(IRanking::TPtr ranking, TVector<TString> functions) - : IRankingNameService(std::move(ranking)) - , Functions_(BuildNameIndex(std::move(functions), NormalizeName)) - , TableFunctions_(BuildNameIndex( - { - "CONCAT", - "RANGE", - "LIKE", - "REGEXP", - "FILTER", - "FOLDER", - "WalkFolders", - "EACH", - "PARTITION_LIST", - }, NormalizeName)) - { + NameIndexScan<TFunctionName>( + *index, + request.Prefix, + request.Constraints, + response.RankedNames); } + return NThreading::MakeFuture<TNameResponse>(std::move(response)); + } + +private: + TNameIndex Functions_; + TNameIndex TableFunctions_; +}; + +class THintNameService: public IRankingNameService { +public: + THintNameService( + IRanking::TPtr ranking, + THashMap<EStatementKind, TVector<TString>> hints) + : IRankingNameService(std::move(ranking)) + , Hints_([hints = std::move(hints)] { + THashMap<EStatementKind, TNameIndex> index; + for (auto& [k, hints] : hints) { + index.emplace(k, BuildNameIndex(std::move(hints), NormalizeName)); + } + return index; + }()) + { + } - NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const override { - TNameResponse response; - if (auto function = request.Constraints.Function) { - const TNameIndex* index = nullptr; - switch (function->ReturnType) { - case ENodeKind::Any: { - index = &Functions_; - } break; - case ENodeKind::Table: { - index = &TableFunctions_; - } break; - } - - NameIndexScan<TFunctionName>( - *index, + NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const override { + TNameResponse response; + if (request.Constraints.Hint) { + const auto stmt = request.Constraints.Hint->Statement; + if (const auto* hints = Hints_.FindPtr(stmt)) { + NameIndexScan<THintName>( + *hints, request.Prefix, request.Constraints, response.RankedNames); } - return NThreading::MakeFuture<TNameResponse>(std::move(response)); } - - private: - TNameIndex Functions_; - TNameIndex TableFunctions_; - }; - - class THintNameService: public IRankingNameService { - public: - THintNameService( - IRanking::TPtr ranking, - THashMap<EStatementKind, TVector<TString>> hints) - : IRankingNameService(std::move(ranking)) - , Hints_([hints = std::move(hints)] { - THashMap<EStatementKind, TNameIndex> index; - for (auto& [k, hints] : hints) { - index.emplace(k, BuildNameIndex(std::move(hints), NormalizeName)); - } - return index; - }()) - { - } - - NThreading::TFuture<TNameResponse> LookupAllUnranked(const TNameRequest& request) const override { - TNameResponse response; - if (request.Constraints.Hint) { - const auto stmt = request.Constraints.Hint->Statement; - if (const auto* hints = Hints_.FindPtr(stmt)) { - NameIndexScan<THintName>( - *hints, - request.Prefix, - request.Constraints, - response.RankedNames); - } - } - return NThreading::MakeFuture<TNameResponse>(std::move(response)); - } - - private: - THashMap<EStatementKind, TNameIndex> Hints_; - }; - - INameService::TPtr MakeStaticNameService(TNameSet names, TFrequencyData frequency) { - return MakeStaticNameService( - Pruned(std::move(names), frequency), - MakeDefaultRanking(std::move(frequency))); + return NThreading::MakeFuture<TNameResponse>(std::move(response)); } - INameService::TPtr MakeStaticNameService(TNameSet names, IRanking::TPtr ranking) { - TVector<INameService::TPtr> children = { - new TKeywordNameService(ranking), - new TPragmaNameService(ranking, std::move(names.Pragmas)), - new TTypeNameService(ranking, std::move(names.Types)), - new TFunctionNameService(ranking, std::move(names.Functions)), - new THintNameService(ranking, std::move(names.Hints)), - }; - return MakeUnionNameService(std::move(children), ranking); - } +private: + THashMap<EStatementKind, TNameIndex> Hints_; +}; + +INameService::TPtr MakeStaticNameService(TNameSet names, TFrequencyData frequency) { + return MakeStaticNameService( + Pruned(std::move(names), frequency), + MakeDefaultRanking(std::move(frequency))); +} + +INameService::TPtr MakeStaticNameService(TNameSet names, IRanking::TPtr ranking) { + TVector<INameService::TPtr> children = { + new TKeywordNameService(ranking), + new TPragmaNameService(ranking, std::move(names.Pragmas)), + new TTypeNameService(ranking, std::move(names.Types)), + new TFunctionNameService(ranking, std::move(names.Functions)), + new THintNameService(ranking, std::move(names.Hints)), + }; + return MakeUnionNameService(std::move(children), ranking); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/static/name_service.h b/yql/essentials/sql/v1/complete/name/service/static/name_service.h index b009ec5b27e..14eb6c7e61e 100644 --- a/yql/essentials/sql/v1/complete/name/service/static/name_service.h +++ b/yql/essentials/sql/v1/complete/name/service/static/name_service.h @@ -8,8 +8,8 @@ namespace NSQLComplete { - INameService::TPtr MakeStaticNameService(TNameSet names, TFrequencyData frequency); +INameService::TPtr MakeStaticNameService(TNameSet names, TFrequencyData frequency); - INameService::TPtr MakeStaticNameService(TNameSet names, IRanking::TPtr ranking); +INameService::TPtr MakeStaticNameService(TNameSet names, IRanking::TPtr ranking); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/static/name_set.cpp b/yql/essentials/sql/v1/complete/name/service/static/name_set.cpp index 41b2feef7e8..22e36becbf3 100644 --- a/yql/essentials/sql/v1/complete/name/service/static/name_set.cpp +++ b/yql/essentials/sql/v1/complete/name/service/static/name_set.cpp @@ -6,40 +6,40 @@ namespace NSQLComplete { - TVector<TString> Pruned(TVector<TString> names, const THashMap<TString, size_t>& frequency) { - THashMap<TString, TVector<std::tuple<TString, size_t>>> groups; - - for (auto& [normalized, original] : BuildNameIndex(std::move(names), NormalizeName)) { - size_t freq = 0; - if (const size_t* it = frequency.FindPtr(original)) { - freq = *it; - } - groups[normalized].emplace_back(std::move(original), freq); - } +TVector<TString> Pruned(TVector<TString> names, const THashMap<TString, size_t>& frequency) { + THashMap<TString, TVector<std::tuple<TString, size_t>>> groups; - for (auto& [_, group] : groups) { - Sort(group, [](const auto& lhs, const auto& rhs) { - return std::get<1>(lhs) < std::get<1>(rhs); - }); + for (auto& [normalized, original] : BuildNameIndex(std::move(names), NormalizeName)) { + size_t freq = 0; + if (const size_t* it = frequency.FindPtr(original)) { + freq = *it; } + groups[normalized].emplace_back(std::move(original), freq); + } - names = TVector<TString>(); - names.reserve(groups.size()); - for (auto& [_, group] : groups) { - Y_ASSERT(!group.empty()); - names.emplace_back(std::move(std::get<0>(group.back()))); - } - return names; + for (auto& [_, group] : groups) { + Sort(group, [](const auto& lhs, const auto& rhs) { + return std::get<1>(lhs) < std::get<1>(rhs); + }); } - TNameSet Pruned(TNameSet names, const TFrequencyData& frequency) { - names.Pragmas = Pruned(std::move(names.Pragmas), frequency.Pragmas); - names.Types = Pruned(std::move(names.Types), frequency.Types); - names.Functions = Pruned(std::move(names.Functions), frequency.Functions); - for (auto& [k, h] : names.Hints) { - h = Pruned(h, frequency.Hints); - } - return names; + names = TVector<TString>(); + names.reserve(groups.size()); + for (auto& [_, group] : groups) { + Y_ASSERT(!group.empty()); + names.emplace_back(std::move(std::get<0>(group.back()))); + } + return names; +} + +TNameSet Pruned(TNameSet names, const TFrequencyData& frequency) { + names.Pragmas = Pruned(std::move(names.Pragmas), frequency.Pragmas); + names.Types = Pruned(std::move(names.Types), frequency.Types); + names.Functions = Pruned(std::move(names.Functions), frequency.Functions); + for (auto& [k, h] : names.Hints) { + h = Pruned(h, frequency.Hints); } + return names; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/static/name_set.h b/yql/essentials/sql/v1/complete/name/service/static/name_set.h index d3b6e72fc2c..2b1ef58b3f2 100644 --- a/yql/essentials/sql/v1/complete/name/service/static/name_set.h +++ b/yql/essentials/sql/v1/complete/name/service/static/name_set.h @@ -9,18 +9,18 @@ namespace NSQLComplete { - struct TNameSet { - TVector<TString> Pragmas; - TVector<TString> Types; - TVector<TString> Functions; - THashMap<EStatementKind, TVector<TString>> Hints; - }; +struct TNameSet { + TVector<TString> Pragmas; + TVector<TString> Types; + TVector<TString> Functions; + THashMap<EStatementKind, TVector<TString>> Hints; +}; - TNameSet Pruned(TNameSet names, const TFrequencyData& frequency); +TNameSet Pruned(TNameSet names, const TFrequencyData& frequency); - TNameSet LoadDefaultNameSet(); +TNameSet LoadDefaultNameSet(); - // TODO(YQL-19747): Mirate YDB CLI to LoadDefaultNameSet - TNameSet MakeDefaultNameSet(); +// TODO(YQL-19747): Mirate YDB CLI to LoadDefaultNameSet +TNameSet MakeDefaultNameSet(); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/static/name_set_json.cpp b/yql/essentials/sql/v1/complete/name/service/static/name_set_json.cpp index b1ed855d599..4426f89c401 100644 --- a/yql/essentials/sql/v1/complete/name/service/static/name_set_json.cpp +++ b/yql/essentials/sql/v1/complete/name/service/static/name_set_json.cpp @@ -10,84 +10,84 @@ namespace NSQLComplete { - NJson::TJsonValue LoadJsonResource(TStringBuf filename) { - TString text; - Y_ENSURE(NResource::FindExact(filename, &text), filename); - return NJson::ReadJsonFastTree(text); +NJson::TJsonValue LoadJsonResource(TStringBuf filename) { + TString text; + Y_ENSURE(NResource::FindExact(filename, &text), filename); + return NJson::ReadJsonFastTree(text); +} + +TVector<TString> ParseNames(NJson::TJsonValue::TArray& json) { + TVector<TString> keys; + keys.reserve(json.size()); + for (auto& item : json) { + keys.emplace_back(item.GetMapSafe().at("name").GetStringSafe()); } - - TVector<TString> ParseNames(NJson::TJsonValue::TArray& json) { - TVector<TString> keys; - keys.reserve(json.size()); - for (auto& item : json) { - keys.emplace_back(item.GetMapSafe().at("name").GetStringSafe()); + return keys; +} + +TVector<TString> ParsePragmas(NJson::TJsonValue json) { + return ParseNames(json.GetArraySafe()); +} + +TVector<TString> ParseTypes(NJson::TJsonValue json) { + return ParseNames(json.GetArraySafe()); +} + +TVector<TString> ParseFunctions(NJson::TJsonValue json) { + return ParseNames(json.GetArraySafe()); +} + +TVector<TString> ParseUdfs(NJson::TJsonValue json) { + TVector<TString> names; + for (auto& [module, v] : json.GetMapSafe()) { + auto functions = ParseNames(v.GetArraySafe()); + for (auto& function : functions) { + function.prepend("::").prepend(module); } - return keys; - } - - TVector<TString> ParsePragmas(NJson::TJsonValue json) { - return ParseNames(json.GetArraySafe()); - } - - TVector<TString> ParseTypes(NJson::TJsonValue json) { - return ParseNames(json.GetArraySafe()); + std::copy(std::begin(functions), std::end(functions), std::back_inserter(names)); } - - TVector<TString> ParseFunctions(NJson::TJsonValue json) { - return ParseNames(json.GetArraySafe()); - } - - TVector<TString> ParseUdfs(NJson::TJsonValue json) { - TVector<TString> names; - for (auto& [module, v] : json.GetMapSafe()) { - auto functions = ParseNames(v.GetArraySafe()); - for (auto& function : functions) { - function.prepend("::").prepend(module); + return names; +} + +// TODO(YQL-19747): support multiple systems, name service/set hierarchy - common & special +THashMap<EStatementKind, TVector<TString>> ParseHints(NJson::TJsonValue json) { + THashMap<EStatementKind, TVector<TString>> hints; + + THashMap<EStatementKind, TString> StatementNames = { + {EStatementKind::Select, "read"}, + {EStatementKind::Insert, "insert"}, + }; + + for (const auto& [k, kname] : StatementNames) { + for (auto& [_, values] : json.GetMapSafe().at(kname).GetMapSafe()) { + for (auto& name : ParseNames(values.GetMapSafe().at("hints").GetArraySafe())) { + hints[k].emplace_back(std::move(name)); } - std::copy(std::begin(functions), std::end(functions), std::back_inserter(names)); } - return names; } - // TODO(YQL-19747): support multiple systems, name service/set hierarchy - common & special - THashMap<EStatementKind, TVector<TString>> ParseHints(NJson::TJsonValue json) { - THashMap<EStatementKind, TVector<TString>> hints; - - THashMap<EStatementKind, TString> StatementNames = { - {EStatementKind::Select, "read"}, - {EStatementKind::Insert, "insert"}, - }; - - for (const auto& [k, kname] : StatementNames) { - for (auto& [_, values] : json.GetMapSafe().at(kname).GetMapSafe()) { - for (auto& name : ParseNames(values.GetMapSafe().at("hints").GetArraySafe())) { - hints[k].emplace_back(std::move(name)); - } - } - } - - for (auto& [_, hints] : hints) { - for (auto& hint : hints) { - hint = ToUpperUTF8(hint); - } + for (auto& [_, hints] : hints) { + for (auto& hint : hints) { + hint = ToUpperUTF8(hint); } - - return hints; - } - - TNameSet LoadDefaultNameSet() { - return { - .Pragmas = ParsePragmas(LoadJsonResource("pragmas_opensource.json")), - .Types = ParseTypes(LoadJsonResource("types.json")), - .Functions = Merge( - ParseFunctions(LoadJsonResource("sql_functions.json")), - ParseUdfs(LoadJsonResource("udfs_basic.json"))), - .Hints = ParseHints(LoadJsonResource("statements_opensource.json")), - }; } - TNameSet MakeDefaultNameSet() { - return Pruned(LoadDefaultNameSet(), LoadFrequencyData()); - } + return hints; +} + +TNameSet LoadDefaultNameSet() { + return { + .Pragmas = ParsePragmas(LoadJsonResource("pragmas_opensource.json")), + .Types = ParseTypes(LoadJsonResource("types.json")), + .Functions = Merge( + ParseFunctions(LoadJsonResource("sql_functions.json")), + ParseUdfs(LoadJsonResource("udfs_basic.json"))), + .Hints = ParseHints(LoadJsonResource("statements_opensource.json")), + }; +} + +TNameSet MakeDefaultNameSet() { + return Pruned(LoadDefaultNameSet(), LoadFrequencyData()); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/static/name_set_json.h b/yql/essentials/sql/v1/complete/name/service/static/name_set_json.h index 06180b1167f..82435a73628 100644 --- a/yql/essentials/sql/v1/complete/name/service/static/name_set_json.h +++ b/yql/essentials/sql/v1/complete/name/service/static/name_set_json.h @@ -10,22 +10,22 @@ namespace NSQLComplete { - NJson::TJsonValue LoadJsonResource(TStringBuf filename); +NJson::TJsonValue LoadJsonResource(TStringBuf filename); - template <class T, class U> - T Merge(T lhs, U rhs) { - std::copy(std::begin(rhs), std::end(rhs), std::back_inserter(lhs)); - return lhs; - } +template <class T, class U> +T Merge(T lhs, U rhs) { + std::copy(std::begin(rhs), std::end(rhs), std::back_inserter(lhs)); + return lhs; +} - TVector<TString> ParsePragmas(NJson::TJsonValue json); +TVector<TString> ParsePragmas(NJson::TJsonValue json); - TVector<TString> ParseTypes(NJson::TJsonValue json); +TVector<TString> ParseTypes(NJson::TJsonValue json); - TVector<TString> ParseFunctions(NJson::TJsonValue json); +TVector<TString> ParseFunctions(NJson::TJsonValue json); - TVector<TString> ParseUdfs(NJson::TJsonValue json); +TVector<TString> ParseUdfs(NJson::TJsonValue json); - THashMap<EStatementKind, TVector<TString>> ParseHints(NJson::TJsonValue json); +THashMap<EStatementKind, TVector<TString>> ParseHints(NJson::TJsonValue json); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/union/name_service.cpp b/yql/essentials/sql/v1/complete/name/service/union/name_service.cpp index f96f5856a6a..1b241c64be6 100644 --- a/yql/essentials/sql/v1/complete/name/service/union/name_service.cpp +++ b/yql/essentials/sql/v1/complete/name/service/union/name_service.cpp @@ -4,67 +4,67 @@ namespace NSQLComplete { - namespace { +namespace { - class TNameService: public INameService { - public: - TNameService( - TVector<INameService::TPtr> children, - IRanking::TPtr ranking) - : Children_(std::move(children)) - , Ranking_(std::move(ranking)) - { - } +class TNameService: public INameService { +public: + TNameService( + TVector<INameService::TPtr> children, + IRanking::TPtr ranking) + : Children_(std::move(children)) + , Ranking_(std::move(ranking)) + { + } - NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { - TVector<NThreading::TFuture<TNameResponse>> fs; - for (const auto& c : Children_) { - fs.emplace_back(c->Lookup(request)); - } + NThreading::TFuture<TNameResponse> Lookup(const TNameRequest& request) const override { + TVector<NThreading::TFuture<TNameResponse>> fs; + for (const auto& c : Children_) { + fs.emplace_back(c->Lookup(request)); + } - return NThreading::WaitAll(fs) - .Apply([fs, ranking = Ranking_, request](auto) { - return Union(fs, ranking, request.Constraints, request.Limit); - }); - } + return NThreading::WaitAll(fs) + .Apply([fs, ranking = Ranking_, request](auto) { + return Union(fs, ranking, request.Constraints, request.Limit); + }); + } - private: - static TNameResponse Union( - TVector<NThreading::TFuture<TNameResponse>> fs, - IRanking::TPtr ranking, - const TNameConstraints& constraints, - size_t limit) { - TNameResponse united; - for (auto f : fs) { - TNameResponse response = f.ExtractValue(); +private: + static TNameResponse Union( + TVector<NThreading::TFuture<TNameResponse>> fs, + IRanking::TPtr ranking, + const TNameConstraints& constraints, + size_t limit) { + TNameResponse united; + for (auto f : fs) { + TNameResponse response = f.ExtractValue(); - std::ranges::move( - response.RankedNames, - std::back_inserter(united.RankedNames)); + std::ranges::move( + response.RankedNames, + std::back_inserter(united.RankedNames)); - if (!response.IsEmpty() && response.NameHintLength) { - Y_ENSURE( - united.NameHintLength.Empty() || - united.NameHintLength == response.NameHintLength); - united.NameHintLength = response.NameHintLength; - } - } - ranking->CropToSortedPrefix(united.RankedNames, constraints, limit); - return united; + if (!response.IsEmpty() && response.NameHintLength) { + Y_ENSURE( + united.NameHintLength.Empty() || + united.NameHintLength == response.NameHintLength); + united.NameHintLength = response.NameHintLength; } + } + ranking->CropToSortedPrefix(united.RankedNames, constraints, limit); + return united; + } - TVector<INameService::TPtr> Children_; - IRanking::TPtr Ranking_; - }; + TVector<INameService::TPtr> Children_; + IRanking::TPtr Ranking_; +}; - } // namespace +} // namespace - INameService::TPtr MakeUnionNameService( - TVector<INameService::TPtr> children, - IRanking::TPtr ranking) { - return INameService::TPtr(new TNameService( - std::move(children), - std::move(ranking))); - } +INameService::TPtr MakeUnionNameService( + TVector<INameService::TPtr> children, + IRanking::TPtr ranking) { + return INameService::TPtr(new TNameService( + std::move(children), + std::move(ranking))); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/union/name_service.h b/yql/essentials/sql/v1/complete/name/service/union/name_service.h index a9cd292b39b..6539902caf9 100644 --- a/yql/essentials/sql/v1/complete/name/service/union/name_service.h +++ b/yql/essentials/sql/v1/complete/name/service/union/name_service.h @@ -5,8 +5,8 @@ namespace NSQLComplete { - INameService::TPtr MakeUnionNameService( - TVector<INameService::TPtr> children, - IRanking::TPtr ranking); +INameService::TPtr MakeUnionNameService( + TVector<INameService::TPtr> children, + IRanking::TPtr ranking); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name_mapping.cpp b/yql/essentials/sql/v1/complete/name_mapping.cpp index a4707942fa3..50105119686 100644 --- a/yql/essentials/sql/v1/complete/name_mapping.cpp +++ b/yql/essentials/sql/v1/complete/name_mapping.cpp @@ -4,179 +4,179 @@ namespace NSQLComplete { - namespace { - - TString ToIdentifier(TString content, const TLocalSyntaxContext& local) { - if (IsPlain(content) && !local.IsQuoted.AtLhs && !local.IsQuoted.AtRhs) { - return content; - } - - SubstGlobal(content, "`", "``"); - if (!local.IsQuoted.AtLhs) { - content.prepend('`'); - } - if (!local.IsQuoted.AtRhs) { - content.append('`'); - } - return content; - } +namespace { - } // namespace +TString ToIdentifier(TString content, const TLocalSyntaxContext& local) { + if (IsPlain(content) && !local.IsQuoted.AtLhs && !local.IsQuoted.AtRhs) { + return content; + } - TCandidate ToCandidate(TKeyword name, TLocalSyntaxContext& local) { - TVector<TString>& seq = local.Keywords[name.Content]; - seq.insert(std::begin(seq), name.Content); + SubstGlobal(content, "`", "``"); + if (!local.IsQuoted.AtLhs) { + content.prepend('`'); + } + if (!local.IsQuoted.AtRhs) { + content.append('`'); + } + return content; +} - TCandidate candidate = { - .Kind = ECandidateKind::Keyword, - .Content = FormatKeywords(seq), - }; +} // namespace - if (candidate.Content.EndsWith('(')) { - candidate.Content += ')'; - candidate.CursorShift = 1; - } +TCandidate ToCandidate(TKeyword name, TLocalSyntaxContext& local) { + TVector<TString>& seq = local.Keywords[name.Content]; + seq.insert(std::begin(seq), name.Content); - return candidate; - } + TCandidate candidate = { + .Kind = ECandidateKind::Keyword, + .Content = FormatKeywords(seq), + }; - TCandidate ToCandidate(TPragmaName name) { - return {ECandidateKind::PragmaName, std::move(name.Identifier)}; + if (candidate.Content.EndsWith('(')) { + candidate.Content += ')'; + candidate.CursorShift = 1; } - TCandidate ToCandidate(TTypeName name) { - TCandidate candidate = { - .Kind = ECandidateKind::TypeName, - .Content = std::move(name.Identifier), - }; - - switch (name.Kind) { - case TTypeName::EKind::Simple: { - } break; - case TTypeName::EKind::Container: { - candidate.Content += "<>"; - candidate.CursorShift = 1; - } break; - case TTypeName::EKind::Parameterized: { - candidate.Content += "()"; - candidate.CursorShift = 1; - } break; - } + return candidate; +} - return candidate; - } +TCandidate ToCandidate(TPragmaName name) { + return {ECandidateKind::PragmaName, std::move(name.Identifier)}; +} - TCandidate ToCandidate(TFunctionName name) { - TCandidate candidate = { - .Kind = ECandidateKind::FunctionName, - .Content = std::move(name.Identifier), - }; +TCandidate ToCandidate(TTypeName name) { + TCandidate candidate = { + .Kind = ECandidateKind::TypeName, + .Content = std::move(name.Identifier), + }; - candidate.Content += "()"; - candidate.CursorShift = 1; - - return candidate; + switch (name.Kind) { + case TTypeName::EKind::Simple: { + } break; + case TTypeName::EKind::Container: { + candidate.Content += "<>"; + candidate.CursorShift = 1; + } break; + case TTypeName::EKind::Parameterized: { + candidate.Content += "()"; + candidate.CursorShift = 1; + } break; } - TCandidate ToCandidate(THintName name) { - return {ECandidateKind::HintName, std::move(name.Identifier)}; - } + return candidate; +} - TCandidate ToCandidate(TFolderName name, TLocalSyntaxContext& local) { - TCandidate candidate = { - .Kind = ECandidateKind::FolderName, - .Content = std::move(name.Identifier), - }; +TCandidate ToCandidate(TFunctionName name) { + TCandidate candidate = { + .Kind = ECandidateKind::FunctionName, + .Content = std::move(name.Identifier), + }; - if (!local.IsQuoted.AtLhs) { - candidate.Content.prepend('`'); - } + candidate.Content += "()"; + candidate.CursorShift = 1; - candidate.Content.append('/'); + return candidate; +} - if (!local.IsQuoted.AtRhs) { - candidate.Content.append('`'); - candidate.CursorShift = 1; - } +TCandidate ToCandidate(THintName name) { + return {ECandidateKind::HintName, std::move(name.Identifier)}; +} - return candidate; - } +TCandidate ToCandidate(TFolderName name, TLocalSyntaxContext& local) { + TCandidate candidate = { + .Kind = ECandidateKind::FolderName, + .Content = std::move(name.Identifier), + }; - TCandidate ToCandidate(TTableName name, TLocalSyntaxContext& local) { - if (!local.IsQuoted.AtLhs) { - name.Identifier.prepend('`'); - } - if (!local.IsQuoted.AtRhs) { - name.Identifier.append('`'); - } - return {ECandidateKind::TableName, std::move(name.Identifier)}; + if (!local.IsQuoted.AtLhs) { + candidate.Content.prepend('`'); } - TCandidate ToCandidate(TClusterName name) { - return {ECandidateKind::ClusterName, std::move(name.Identifier)}; - } + candidate.Content.append('/'); - TCandidate ToCandidate(TColumnName name, TLocalSyntaxContext& local) { - name.Identifier = ToIdentifier(std::move(name.Identifier), local); + if (!local.IsQuoted.AtRhs) { + candidate.Content.append('`'); + candidate.CursorShift = 1; + } - if (local.Column->Table.empty() && !name.TableAlias.empty()) { - name.Identifier.prepend('.'); - name.Identifier.prepend(ToIdentifier(std::move(name.TableAlias), local)); - } + return candidate; +} - return {ECandidateKind::ColumnName, std::move(name.Identifier)}; +TCandidate ToCandidate(TTableName name, TLocalSyntaxContext& local) { + if (!local.IsQuoted.AtLhs) { + name.Identifier.prepend('`'); } - - TCandidate ToCandidate(TBindingName name) { - name.Identifier.prepend('$'); - return {ECandidateKind::BindingName, std::move(name.Identifier)}; + if (!local.IsQuoted.AtRhs) { + name.Identifier.append('`'); } + return {ECandidateKind::TableName, std::move(name.Identifier)}; +} + +TCandidate ToCandidate(TClusterName name) { + return {ECandidateKind::ClusterName, std::move(name.Identifier)}; +} - TCandidate ToCandidate(TUnknownName name, TLocalSyntaxContext& local) { - name.Content = ToIdentifier(std::move(name.Content), local); +TCandidate ToCandidate(TColumnName name, TLocalSyntaxContext& local) { + name.Identifier = ToIdentifier(std::move(name.Identifier), local); - return {ECandidateKind::UnknownName, std::move(name.Content)}; + if (local.Column->Table.empty() && !name.TableAlias.empty()) { + name.Identifier.prepend('.'); + name.Identifier.prepend(ToIdentifier(std::move(name.TableAlias), local)); } - TCandidate ToCandidate(TGenericName generic, TLocalSyntaxContext& local) { - return std::visit([&](auto&& name) -> TCandidate { - using T = std::decay_t<decltype(name)>; + return {ECandidateKind::ColumnName, std::move(name.Identifier)}; +} - constexpr bool IsContextSensitive = - std::is_same_v<T, TKeyword> || - std::is_same_v<T, TFolderName> || - std::is_same_v<T, TTableName> || - std::is_same_v<T, TColumnName> || - std::is_same_v<T, TUnknownName>; +TCandidate ToCandidate(TBindingName name) { + name.Identifier.prepend('$'); + return {ECandidateKind::BindingName, std::move(name.Identifier)}; +} - constexpr bool IsDocumented = - std::is_base_of_v<TDescribed, T>; +TCandidate ToCandidate(TUnknownName name, TLocalSyntaxContext& local) { + name.Content = ToIdentifier(std::move(name.Content), local); - TMaybe<TString> documentation; - if constexpr (IsDocumented) { - documentation = std::move(name.Description); - } + return {ECandidateKind::UnknownName, std::move(name.Content)}; +} - TCandidate candidate; - if constexpr (IsContextSensitive) { - candidate = ToCandidate(std::move(name), local); - } else { - candidate = ToCandidate(std::move(name)); - } +TCandidate ToCandidate(TGenericName generic, TLocalSyntaxContext& local) { + return std::visit([&](auto&& name) -> TCandidate { + using T = std::decay_t<decltype(name)>; - candidate.Documentation = std::move(documentation); + constexpr bool IsContextSensitive = + std::is_same_v<T, TKeyword> || + std::is_same_v<T, TFolderName> || + std::is_same_v<T, TTableName> || + std::is_same_v<T, TColumnName> || + std::is_same_v<T, TUnknownName>; - return candidate; - }, std::move(generic)); - } + constexpr bool IsDocumented = + std::is_base_of_v<TDescribed, T>; - TVector<TCandidate> ToCandidate(TVector<TGenericName> names, TLocalSyntaxContext local) { - TVector<TCandidate> candidates; - candidates.reserve(names.size()); - for (auto& name : names) { - candidates.emplace_back(ToCandidate(std::move(name), local)); + TMaybe<TString> documentation; + if constexpr (IsDocumented) { + documentation = std::move(name.Description); } - return candidates; + + TCandidate candidate; + if constexpr (IsContextSensitive) { + candidate = ToCandidate(std::move(name), local); + } else { + candidate = ToCandidate(std::move(name)); + } + + candidate.Documentation = std::move(documentation); + + return candidate; + }, std::move(generic)); +} + +TVector<TCandidate> ToCandidate(TVector<TGenericName> names, TLocalSyntaxContext local) { + TVector<TCandidate> candidates; + candidates.reserve(names.size()); + for (auto& name : names) { + candidates.emplace_back(ToCandidate(std::move(name), local)); } + return candidates; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name_mapping.h b/yql/essentials/sql/v1/complete/name_mapping.h index 2afa509de01..274f769127b 100644 --- a/yql/essentials/sql/v1/complete/name_mapping.h +++ b/yql/essentials/sql/v1/complete/name_mapping.h @@ -7,8 +7,8 @@ namespace NSQLComplete { - TCandidate ToCandidate(TGenericName name, TLocalSyntaxContext& local); +TCandidate ToCandidate(TGenericName name, TLocalSyntaxContext& local); - TVector<TCandidate> ToCandidate(TVector<TGenericName> names, TLocalSyntaxContext local); +TVector<TCandidate> ToCandidate(TVector<TGenericName> names, TLocalSyntaxContext local); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/sql_complete.cpp b/yql/essentials/sql/v1/complete/sql_complete.cpp index fc8db52af13..401588dc594 100644 --- a/yql/essentials/sql/v1/complete/sql_complete.cpp +++ b/yql/essentials/sql/v1/complete/sql_complete.cpp @@ -21,238 +21,238 @@ namespace NSQLComplete { - TString TCandidate::FilterText() const { - TStringBuf text = Content; - if (IsQuoted(text)) { - text = Unquoted(text); - } - return ToLowerUTF8(text); +TString TCandidate::FilterText() const { + TStringBuf text = Content; + if (IsQuoted(text)) { + text = Unquoted(text); } + return ToLowerUTF8(text); +} - class TSqlCompletionEngine: public ISqlCompletionEngine { - public: - TSqlCompletionEngine( - TLexerSupplier lexer, - INameService::TPtr names, - IRanking::TPtr ranking, - TConfiguration configuration) - : Configuration_(std::move(configuration)) - , SyntaxAnalysis_(MakeLocalSyntaxAnalysis( - lexer, - Configuration_.IgnoredRules_, - Configuration_.DisabledPreviousByToken_, - Configuration_.ForcedPreviousByToken_)) - , GlobalAnalysis_(MakeGlobalAnalysis()) - , Names_(std::move(names)) - , Ranking_(std::move(ranking)) - { - Ranking_ = Ranking_ ? Ranking_ : MakeDummyRanking(); - } - - NThreading::TFuture<TCompletion> - Complete(TCompletionInput input, TEnvironment env = {}) override { - return CompleteAsync(input, env); - } - - NThreading::TFuture<TCompletion> CompleteAsync(TCompletionInput input, TEnvironment env) override { - if ((input.CursorPosition < input.Text.length() && - IsUTF8ContinuationByte(input.Text.at(input.CursorPosition))) || - (input.Text.length() < input.CursorPosition)) { - ythrow yexception() - << "invalid cursor position " << input.CursorPosition - << " for input size " << input.Text.size(); - } - - TLocalSyntaxContext local = SyntaxAnalysis_->Analyze(input); +class TSqlCompletionEngine: public ISqlCompletionEngine { +public: + TSqlCompletionEngine( + TLexerSupplier lexer, + INameService::TPtr names, + IRanking::TPtr ranking, + TConfiguration configuration) + : Configuration_(std::move(configuration)) + , SyntaxAnalysis_(MakeLocalSyntaxAnalysis( + lexer, + Configuration_.IgnoredRules_, + Configuration_.DisabledPreviousByToken_, + Configuration_.ForcedPreviousByToken_)) + , GlobalAnalysis_(MakeGlobalAnalysis()) + , Names_(std::move(names)) + , Ranking_(std::move(ranking)) + { + Ranking_ = Ranking_ ? Ranking_ : MakeDummyRanking(); + } - TGlobalContext global = GlobalAnalysis_->Analyze(input, std::move(env)); + NThreading::TFuture<TCompletion> + Complete(TCompletionInput input, TEnvironment env = {}) override { + return CompleteAsync(input, env); + } - local = Enriched(std::move(local), global); + NThreading::TFuture<TCompletion> CompleteAsync(TCompletionInput input, TEnvironment env) override { + if ((input.CursorPosition < input.Text.length() && + IsUTF8ContinuationByte(input.Text.at(input.CursorPosition))) || + (input.Text.length() < input.CursorPosition)) { + ythrow yexception() + << "invalid cursor position " << input.CursorPosition + << " for input size " << input.Text.size(); + } - TNameRequest request = NameRequestFrom(input, local, global); - if (request.IsEmpty()) { - return NThreading::MakeFuture<TCompletion>({ - .CompletedToken = GetCompletedToken(input, local.ReplaceRange), - .Candidates = {}, - }); - } + TLocalSyntaxContext local = SyntaxAnalysis_->Analyze(input); - TVector<INameService::TPtr> children; + TGlobalContext global = GlobalAnalysis_->Analyze(input, std::move(env)); - if (!local.IsQuoted) { - children.emplace_back(MakeBindingNameService(std::move(global.Names))); - } + local = Enriched(std::move(local), global); - if (!local.Binding && global.Column) { - children.emplace_back(MakeColumnNameService(std::move(global.Column->Columns))); - } + TNameRequest request = NameRequestFrom(input, local, global); + if (request.IsEmpty()) { + return NThreading::MakeFuture<TCompletion>({ + .CompletedToken = GetCompletedToken(input, local.ReplaceRange), + .Candidates = {}, + }); + } - if (!local.Binding) { - children.emplace_back(Names_); - } + TVector<INameService::TPtr> children; - INameService::TPtr service = - MakeColumnReplicatingService( - MakeUnionNameService(std::move(children), Ranking_), - Ranking_); + if (!local.IsQuoted) { + children.emplace_back(MakeBindingNameService(std::move(global.Names))); + } - return service - ->Lookup(std::move(request)) - .Apply([this, input, local = std::move(local)](auto f) { - return ToCompletion(input, std::move(local), f.ExtractValue()); - }); + if (!local.Binding && global.Column) { + children.emplace_back(MakeColumnNameService(std::move(global.Column->Columns))); } - private: - TCompletedToken GetCompletedToken(TCompletionInput input, TEditRange editRange) const { - return { - .Content = input.Text.SubStr(editRange.Begin, editRange.Length), - .SourcePosition = editRange.Begin, - }; + if (!local.Binding) { + children.emplace_back(Names_); } - TNameRequest NameRequestFrom( - TCompletionInput input, - const TLocalSyntaxContext& local, - const TGlobalContext& global) const { - TNameRequest request = { - .Prefix = TString(GetCompletedToken(input, local.FilterRange).Content), - .Limit = Configuration_.Limit, - }; + INameService::TPtr service = + MakeColumnReplicatingService( + MakeUnionNameService(std::move(children), Ranking_), + Ranking_); - for (const auto& [first, _] : local.Keywords) { - request.Keywords.emplace_back(first); - } + return service + ->Lookup(std::move(request)) + .Apply([this, input, local = std::move(local)](auto f) { + return ToCompletion(input, std::move(local), f.ExtractValue()); + }); + } - if (local.Pragma) { - TPragmaName::TConstraints constraints; - constraints.Namespace = local.Pragma->Namespace; - request.Constraints.Pragma = std::move(constraints); - } +private: + TCompletedToken GetCompletedToken(TCompletionInput input, TEditRange editRange) const { + return { + .Content = input.Text.SubStr(editRange.Begin, editRange.Length), + .SourcePosition = editRange.Begin, + }; + } - if (local.Type) { - request.Constraints.Type = TTypeName::TConstraints(); - } + TNameRequest NameRequestFrom( + TCompletionInput input, + const TLocalSyntaxContext& local, + const TGlobalContext& global) const { + TNameRequest request = { + .Prefix = TString(GetCompletedToken(input, local.FilterRange).Content), + .Limit = Configuration_.Limit, + }; + + for (const auto& [first, _] : local.Keywords) { + request.Keywords.emplace_back(first); + } - if (local.Function) { - TFunctionName::TConstraints constraints; - constraints.Namespace = local.Function->Namespace; - constraints.ReturnType = local.Function->ReturnType; - request.Constraints.Function = std::move(constraints); - } + if (local.Pragma) { + TPragmaName::TConstraints constraints; + constraints.Namespace = local.Pragma->Namespace; + request.Constraints.Pragma = std::move(constraints); + } - if (local.Hint) { - THintName::TConstraints constraints; - constraints.Statement = local.Hint->StatementKind; - request.Constraints.Hint = std::move(constraints); - } + if (local.Type) { + request.Constraints.Type = TTypeName::TConstraints(); + } - if (local.Object) { - request.Constraints.Object = TObjectNameConstraints(); - request.Constraints.Object->Kinds = local.Object->Kinds; - request.Prefix = local.Object->Path; - } + if (local.Function) { + TFunctionName::TConstraints constraints; + constraints.Namespace = local.Function->Namespace; + constraints.ReturnType = local.Function->ReturnType; + request.Constraints.Function = std::move(constraints); + } - if (local.Object && global.Use) { - request.Constraints.Object->Provider = global.Use->Provider; - request.Constraints.Object->Cluster = global.Use->Name; - } + if (local.Hint) { + THintName::TConstraints constraints; + constraints.Statement = local.Hint->StatementKind; + request.Constraints.Hint = std::move(constraints); + } - if (local.Object && local.Object->HasCluster()) { - request.Constraints.Object->Provider = local.Object->Provider; - request.Constraints.Object->Cluster = local.Object->Cluster; - } + if (local.Object) { + request.Constraints.Object = TObjectNameConstraints(); + request.Constraints.Object->Kinds = local.Object->Kinds; + request.Prefix = local.Object->Path; + } - if (local.Cluster) { - TClusterName::TConstraints constraints; - constraints.Namespace = ""; // TODO(YQL-19747): filter by provider - request.Constraints.Cluster = std::move(constraints); - } + if (local.Object && global.Use) { + request.Constraints.Object->Provider = global.Use->Provider; + request.Constraints.Object->Cluster = global.Use->Name; + } - if (local.Column && global.Column) { - TMaybe<TStringBuf> table = local.Column->Table; - table = !table->empty() ? table : Nothing(); + if (local.Object && local.Object->HasCluster()) { + request.Constraints.Object->Provider = local.Object->Provider; + request.Constraints.Object->Cluster = local.Object->Cluster; + } - request.Constraints.Column = TColumnName::TConstraints(); - request.Constraints.Column->TableAlias = local.Column->Table; - request.Constraints.Column->Tables = - TColumnContext(*global.Column).ExtractAliased(table).Tables; - request.Constraints.Column->WithoutByTableAlias = global.Column->WithoutByTableAlias; - } + if (local.Cluster) { + TClusterName::TConstraints constraints; + constraints.Namespace = ""; // TODO(YQL-19747): filter by provider + request.Constraints.Cluster = std::move(constraints); + } - return request; + if (local.Column && global.Column) { + TMaybe<TStringBuf> table = local.Column->Table; + table = !table->empty() ? table : Nothing(); + + request.Constraints.Column = TColumnName::TConstraints(); + request.Constraints.Column->TableAlias = local.Column->Table; + request.Constraints.Column->Tables = + TColumnContext(*global.Column).ExtractAliased(table).Tables; + request.Constraints.Column->WithoutByTableAlias = global.Column->WithoutByTableAlias; } - TCompletion ToCompletion(TCompletionInput input, TLocalSyntaxContext local, TNameResponse response) const { - TCompletion completion = { - .CompletedToken = GetCompletedToken(input, local.ReplaceRange), - .Candidates = ToCandidate(std::move(response.RankedNames), std::move(local)), + return request; + } + + TCompletion ToCompletion(TCompletionInput input, TLocalSyntaxContext local, TNameResponse response) const { + TCompletion completion = { + .CompletedToken = GetCompletedToken(input, local.ReplaceRange), + .Candidates = ToCandidate(std::move(response.RankedNames), std::move(local)), + }; + + if (response.NameHintLength) { + const auto length = *response.NameHintLength; + TEditRange editRange = { + .Begin = input.CursorPosition - length, + .Length = length, }; + completion.CompletedToken = GetCompletedToken(input, editRange); + } - if (response.NameHintLength) { - const auto length = *response.NameHintLength; - TEditRange editRange = { - .Begin = input.CursorPosition - length, - .Length = length, - }; - completion.CompletedToken = GetCompletedToken(input, editRange); - } + return completion; + } - return completion; + static TLocalSyntaxContext Enriched(TLocalSyntaxContext local, const TGlobalContext& global) { + TMaybe<TFunctionContext> function = global.EnclosingFunction; + TMaybe<TLocalSyntaxContext::TObject>& object = local.Object; + if (!function || !object) { + return local; } - static TLocalSyntaxContext Enriched(TLocalSyntaxContext local, const TGlobalContext& global) { - TMaybe<TFunctionContext> function = global.EnclosingFunction; - TMaybe<TLocalSyntaxContext::TObject>& object = local.Object; - if (!function || !object) { - return local; - } - - if (TMaybe<TClusterContext> cluster = function->Cluster) { - object->Provider = cluster->Provider; - object->Cluster = cluster->Name; - } + if (TMaybe<TClusterContext> cluster = function->Cluster) { + object->Provider = cluster->Provider; + object->Cluster = cluster->Name; + } - auto& name = function->Name; - size_t number = function->ArgumentNumber; - - name = NormalizeName(name); - - if (name == "concat") { - object->Kinds = {EObjectKind::Folder, EObjectKind::Table}; - } else if ((number == 0) && - (name == "range" || name == "like" || - name == "regexp" || name == "filter" || - name == "folder" || name == "walkfolders")) { - object->Kinds = {EObjectKind::Folder}; - } else if ((number == 1 || number == 2) && (name == "range")) { - if (TMaybe<TString> path = function->Arg0) { - object->Path = *path; - object->Path.append("/"); - } - - object->Kinds = {EObjectKind::Folder, EObjectKind::Table}; + auto& name = function->Name; + size_t number = function->ArgumentNumber; + + name = NormalizeName(name); + + if (name == "concat") { + object->Kinds = {EObjectKind::Folder, EObjectKind::Table}; + } else if ((number == 0) && + (name == "range" || name == "like" || + name == "regexp" || name == "filter" || + name == "folder" || name == "walkfolders")) { + object->Kinds = {EObjectKind::Folder}; + } else if ((number == 1 || number == 2) && (name == "range")) { + if (TMaybe<TString> path = function->Arg0) { + object->Path = *path; + object->Path.append("/"); } - return local; + object->Kinds = {EObjectKind::Folder, EObjectKind::Table}; } - TConfiguration Configuration_; - ILocalSyntaxAnalysis::TPtr SyntaxAnalysis_; - IGlobalAnalysis::TPtr GlobalAnalysis_; - INameService::TPtr Names_; - IRanking::TPtr Ranking_; - }; - - ISqlCompletionEngine::TPtr MakeSqlCompletionEngine( - TLexerSupplier lexer, - INameService::TPtr names, - TConfiguration configuration, - IRanking::TPtr ranking) { - return MakeHolder<TSqlCompletionEngine>( - lexer, std::move(names), std::move(ranking), std::move(configuration)); + return local; } + TConfiguration Configuration_; + ILocalSyntaxAnalysis::TPtr SyntaxAnalysis_; + IGlobalAnalysis::TPtr GlobalAnalysis_; + INameService::TPtr Names_; + IRanking::TPtr Ranking_; +}; + +ISqlCompletionEngine::TPtr MakeSqlCompletionEngine( + TLexerSupplier lexer, + INameService::TPtr names, + TConfiguration configuration, + IRanking::TPtr ranking) { + return MakeHolder<TSqlCompletionEngine>( + lexer, std::move(names), std::move(ranking), std::move(configuration)); +} + } // namespace NSQLComplete template <> diff --git a/yql/essentials/sql/v1/complete/sql_complete.h b/yql/essentials/sql/v1/complete/sql_complete.h index 8fb02c37b06..0f6edfde7ba 100644 --- a/yql/essentials/sql/v1/complete/sql_complete.h +++ b/yql/essentials/sql/v1/complete/sql_complete.h @@ -17,61 +17,61 @@ namespace NSQLComplete { - struct TCompletedToken { - TStringBuf Content; - size_t SourcePosition = 0; - }; - - enum class ECandidateKind { - Keyword, - PragmaName, - TypeName, - FunctionName, - HintName, - FolderName, - TableName, - ClusterName, - ColumnName, - BindingName, - UnknownName, - }; - - struct TCandidate { - ECandidateKind Kind; - TString Content; - size_t CursorShift = 0; - TMaybe<TString> Documentation = Nothing(); - - friend bool operator==(const TCandidate& lhs, const TCandidate& rhs) = default; - - TString FilterText() const; - }; - - struct TCompletion { - TCompletedToken CompletedToken; - TVector<TCandidate> Candidates; - }; - - // TODO(YQL-19747): Make it thread-safe. - class ISqlCompletionEngine { - public: - using TPtr = THolder<ISqlCompletionEngine>; - - virtual ~ISqlCompletionEngine() = default; - - virtual NThreading::TFuture<TCompletion> - Complete(TCompletionInput input, TEnvironment env = {}) = 0; - - virtual NThreading::TFuture<TCompletion> // TODO(YQL-19747): Migrate YDB CLI to `Complete` method - CompleteAsync(TCompletionInput input, TEnvironment env = {}) = 0; - }; - - using TLexerSupplier = std::function<NSQLTranslation::ILexer::TPtr(bool ansi)>; - - ISqlCompletionEngine::TPtr MakeSqlCompletionEngine( - TLexerSupplier lexer, - INameService::TPtr names, - TConfiguration configuration = {}, - IRanking::TPtr ranking = nullptr); +struct TCompletedToken { + TStringBuf Content; + size_t SourcePosition = 0; +}; + +enum class ECandidateKind { + Keyword, + PragmaName, + TypeName, + FunctionName, + HintName, + FolderName, + TableName, + ClusterName, + ColumnName, + BindingName, + UnknownName, +}; + +struct TCandidate { + ECandidateKind Kind; + TString Content; + size_t CursorShift = 0; + TMaybe<TString> Documentation = Nothing(); + + friend bool operator==(const TCandidate& lhs, const TCandidate& rhs) = default; + + TString FilterText() const; +}; + +struct TCompletion { + TCompletedToken CompletedToken; + TVector<TCandidate> Candidates; +}; + +// TODO(YQL-19747): Make it thread-safe. +class ISqlCompletionEngine { +public: + using TPtr = THolder<ISqlCompletionEngine>; + + virtual ~ISqlCompletionEngine() = default; + + virtual NThreading::TFuture<TCompletion> + Complete(TCompletionInput input, TEnvironment env = {}) = 0; + + virtual NThreading::TFuture<TCompletion> // TODO(YQL-19747): Migrate YDB CLI to `Complete` method + CompleteAsync(TCompletionInput input, TEnvironment env = {}) = 0; +}; + +using TLexerSupplier = std::function<NSQLTranslation::ILexer::TPtr(bool ansi)>; + +ISqlCompletionEngine::TPtr MakeSqlCompletionEngine( + TLexerSupplier lexer, + INameService::TPtr names, + TConfiguration configuration = {}, + IRanking::TPtr ranking = nullptr); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp index 679230c7a24..cb14f0e2a7e 100644 --- a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp +++ b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp @@ -45,51 +45,51 @@ public: }; Y_UNIT_TEST_SUITE(SqlCompleteTests) { - using ECandidateKind::BindingName; - using ECandidateKind::ClusterName; - using ECandidateKind::ColumnName; - using ECandidateKind::FolderName; - using ECandidateKind::FunctionName; - using ECandidateKind::HintName; - using ECandidateKind::Keyword; - using ECandidateKind::PragmaName; - using ECandidateKind::TableName; - using ECandidateKind::TypeName; - using ECandidateKind::UnknownName; - - TLexerSupplier MakePureLexerSupplier() { - NSQLTranslationV1::TLexers lexers; - lexers.Antlr4Pure = NSQLTranslationV1::MakeAntlr4PureLexerFactory(); - lexers.Antlr4PureAnsi = NSQLTranslationV1::MakeAntlr4PureAnsiLexerFactory(); - return [lexers = std::move(lexers)](bool ansi) { - return NSQLTranslationV1::MakeLexer( - lexers, ansi, /* antlr4 = */ true, - NSQLTranslationV1::ELexerFlavor::Pure); - }; - } - - ISqlCompletionEngine::TPtr MakeSqlCompletionEngineUT() { - TLexerSupplier lexer = MakePureLexerSupplier(); - - TNameSet names = { - .Pragmas = { - "yson.CastToString", - "yt.RuntimeCluster", - "yt.RuntimeClusterSelection", - }, - .Types = {"Uint64"}, - .Functions = { - "StartsWith", - "DateTime::Split", - "Python::__private", - }, - .Hints = { - {EStatementKind::Select, {"XLOCK"}}, - {EStatementKind::Insert, {"EXPIRATION"}}, - }, - }; - - TString clustersText = R"({ +using ECandidateKind::BindingName; +using ECandidateKind::ClusterName; +using ECandidateKind::ColumnName; +using ECandidateKind::FolderName; +using ECandidateKind::FunctionName; +using ECandidateKind::HintName; +using ECandidateKind::Keyword; +using ECandidateKind::PragmaName; +using ECandidateKind::TableName; +using ECandidateKind::TypeName; +using ECandidateKind::UnknownName; + +TLexerSupplier MakePureLexerSupplier() { + NSQLTranslationV1::TLexers lexers; + lexers.Antlr4Pure = NSQLTranslationV1::MakeAntlr4PureLexerFactory(); + lexers.Antlr4PureAnsi = NSQLTranslationV1::MakeAntlr4PureAnsiLexerFactory(); + return [lexers = std::move(lexers)](bool ansi) { + return NSQLTranslationV1::MakeLexer( + lexers, ansi, /* antlr4 = */ true, + NSQLTranslationV1::ELexerFlavor::Pure); + }; +} + +ISqlCompletionEngine::TPtr MakeSqlCompletionEngineUT() { + TLexerSupplier lexer = MakePureLexerSupplier(); + + TNameSet names = { + .Pragmas = { + "yson.CastToString", + "yt.RuntimeCluster", + "yt.RuntimeClusterSelection", + }, + .Types = {"Uint64"}, + .Functions = { + "StartsWith", + "DateTime::Split", + "Python::__private", + }, + .Hints = { + {EStatementKind::Select, {"XLOCK"}}, + {EStatementKind::Insert, {"EXPIRATION"}}, + }, + }; + + TString clustersText = R"({ "": { "type": "Folder", "entries": { "local": { "type": "Folder", "entries": { "example": { "type": "Table", "columns": {} }, @@ -147,654 +147,654 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { }} })"; - NJson::TJsonMap clustersJson; - Y_ENSURE(NJson::ReadJsonTree(clustersText, &clustersJson)); - - auto clustersIt = NFuncTools::Filter( - [](const auto& x) { return !x.empty(); }, IterateKeys(clustersJson.GetMapSafe())); - TVector<TString> clusters(begin(clustersIt), end(clustersIt)); + NJson::TJsonMap clustersJson; + Y_ENSURE(NJson::ReadJsonTree(clustersText, &clustersJson)); + + auto clustersIt = NFuncTools::Filter( + [](const auto& x) { return !x.empty(); }, IterateKeys(clustersJson.GetMapSafe())); + TVector<TString> clusters(begin(clustersIt), end(clustersIt)); + + TFrequencyData frequency; + IRanking::TPtr ranking = MakeDefaultRanking(frequency); + + TVector<INameService::TPtr> children = { + MakeStaticNameService(std::move(names), frequency), + MakeImpatientNameService( + MakeSchemaNameService( + MakeSimpleSchema( + MakeStaticSimpleSchema(clustersJson)))), + MakeImpatientNameService( + MakeClusterNameService( + MakeStaticClusterDiscovery(std::move(clusters)))), + }; + INameService::TPtr service = MakeUnionNameService(std::move(children), ranking); + + TConfiguration config; + return MakeSqlCompletionEngine(std::move(lexer), std::move(service), config, ranking); +} + +TVector<TCandidate> Complete(ISqlCompletionEngine::TPtr& engine, TString sharped, TEnvironment env = {}) { + return engine->Complete(SharpedInput(sharped), std::move(env)).GetValueSync().Candidates; +} + +TVector<TCandidate> CompleteTop(size_t limit, ISqlCompletionEngine::TPtr& engine, TString sharped, TEnvironment env = {}) { + auto candidates = Complete(engine, std::move(sharped), std::move(env)); + candidates.crop(limit); + return candidates; +} + +Y_UNIT_TEST(Beginning) { + TVector<TCandidate> expected = { + {Keyword, "ALTER"}, + {Keyword, "ANALYZE"}, + {Keyword, "BACKUP"}, + {Keyword, "BATCH"}, + {Keyword, "COMMIT"}, + {Keyword, "CREATE"}, + {Keyword, "DECLARE"}, + {Keyword, "DEFINE"}, + {Keyword, "DELETE FROM"}, + {Keyword, "DISCARD"}, + {Keyword, "DO"}, + {Keyword, "DROP"}, + {Keyword, "EVALUATE"}, + {Keyword, "EXPLAIN"}, + {Keyword, "EXPORT"}, + {Keyword, "FOR"}, + {Keyword, "FROM"}, + {Keyword, "GRANT"}, + {Keyword, "IF"}, + {Keyword, "IMPORT"}, + {Keyword, "INSERT"}, + {Keyword, "PARALLEL"}, + {Keyword, "PRAGMA"}, + {Keyword, "PROCESS"}, + {Keyword, "REDUCE"}, + {Keyword, "REPLACE"}, + {Keyword, "RESTORE"}, + {Keyword, "REVOKE"}, + {Keyword, "ROLLBACK"}, + {Keyword, "SELECT"}, + {Keyword, "SHOW CREATE"}, + {Keyword, "UPDATE"}, + {Keyword, "UPSERT"}, + {Keyword, "USE"}, + {Keyword, "VALUES"}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, ""), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, " "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, " "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, ";"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "; "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, " ; "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "#SELECT"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "#SELECT * FROM"), expected); +} + +Y_UNIT_TEST(Use) { + TVector<TCandidate> expected = { + {ClusterName, "example"}, + {ClusterName, "loggy"}, + {ClusterName, "saurus"}, + }; + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "USE "), expected); +} + +Y_UNIT_TEST(UseClusterResultion) { + auto engine = MakeSqlCompletionEngineUT(); + { + TString query = R"sql( + DECLARE $cluster_name AS String; + USE yt:$cluster_name; + SELECT * FROM # + )sql"; - TFrequencyData frequency; - IRanking::TPtr ranking = MakeDefaultRanking(frequency); + TEnvironment env = { + .Parameters = {{"$cluster_name", "saurus"}}, + }; - TVector<INameService::TPtr> children = { - MakeStaticNameService(std::move(names), frequency), - MakeImpatientNameService( - MakeSchemaNameService( - MakeSimpleSchema( - MakeStaticSimpleSchema(clustersJson)))), - MakeImpatientNameService( - MakeClusterNameService( - MakeStaticClusterDiscovery(std::move(clusters)))), + TVector<TCandidate> expected = { + {TableName, "`maxim`"}, + {BindingName, "$cluster_name"}, + {ClusterName, "example"}, + {ClusterName, "loggy"}, + {ClusterName, "saurus"}, }; - INameService::TPtr service = MakeUnionNameService(std::move(children), ranking); - TConfiguration config; - return MakeSqlCompletionEngine(std::move(lexer), std::move(service), config, ranking); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(5, engine, query, env), expected); } - - TVector<TCandidate> Complete(ISqlCompletionEngine::TPtr& engine, TString sharped, TEnvironment env = {}) { - return engine->Complete(SharpedInput(sharped), std::move(env)).GetValueSync().Candidates; + { + TVector<TCandidate> expected = { + {FolderName, "`.sys/`", 1}, + {FolderName, "`local/`", 1}, + {FolderName, "`prod/`", 1}, + {FolderName, "`test/`", 1}, + {ClusterName, "example"}, + {ClusterName, "loggy"}, + {ClusterName, "saurus"}, + {Keyword, "ANY"}, + }; + UNIT_ASSERT_VALUES_EQUAL( + CompleteTop( + 8, + engine, + "USE yt:$cluster_name; SELECT * FROM ", + {.Parameters = {}}), + expected); + } +} + +Y_UNIT_TEST(Alter) { + TVector<TCandidate> expected = { + {Keyword, "ASYNC REPLICATION"}, + {Keyword, "BACKUP COLLECTION"}, + {Keyword, "DATABASE"}, + {Keyword, "EXTERNAL"}, + {Keyword, "GROUP"}, + {Keyword, "OBJECT"}, + {Keyword, "RESOURCE POOL"}, + {Keyword, "SECRET"}, + {Keyword, "SEQUENCE"}, + {Keyword, "STREAMING QUERY"}, + {Keyword, "TABLE"}, + {Keyword, "TABLESTORE"}, + {Keyword, "TOPIC"}, + {Keyword, "TRANSFER"}, + {Keyword, "USER"}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "ALTER "), expected); +} + +Y_UNIT_TEST(Create) { + TVector<TCandidate> expected = { + {Keyword, "ASYNC REPLICATION"}, + {Keyword, "BACKUP COLLECTION"}, + {Keyword, "EXTERNAL"}, + {Keyword, "GROUP"}, + {Keyword, "OBJECT"}, + {Keyword, "OR REPLACE"}, + {Keyword, "RESOURCE POOL"}, + {Keyword, "SECRET"}, + {Keyword, "STREAMING QUERY"}, + {Keyword, "TABLE"}, + {Keyword, "TABLESTORE"}, + {Keyword, "TEMP TABLE"}, + {Keyword, "TEMPORARY TABLE"}, + {Keyword, "TOPIC"}, + {Keyword, "TRANSFER"}, + {Keyword, "USER"}, + {Keyword, "VIEW"}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "CREATE "), expected); +} + +Y_UNIT_TEST(CreateTable) { + auto engine = MakeSqlCompletionEngineUT(); + { + TVector<TCandidate> expected = { + {FolderName, "`.sys/`", 1}, + {FolderName, "`local/`", 1}, + {FolderName, "`prod/`", 1}, + {FolderName, "`test/`", 1}, + {ClusterName, "example"}, + {ClusterName, "loggy"}, + {ClusterName, "saurus"}, + {Keyword, "IF NOT EXISTS"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "CREATE TABLE #"), expected); } - - TVector<TCandidate> CompleteTop(size_t limit, ISqlCompletionEngine::TPtr& engine, TString sharped, TEnvironment env = {}) { - auto candidates = Complete(engine, std::move(sharped), std::move(env)); - candidates.crop(limit); - return candidates; + { + TVector<TCandidate> expected = { + {FolderName, "service/"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "CREATE TABLE `test/#`"), expected); + } +} + +Y_UNIT_TEST(Delete) { + TVector<TCandidate> expected = { + {Keyword, "FROM"}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "DELETE "), expected); +} + +Y_UNIT_TEST(Drop) { + TVector<TCandidate> expected = { + {Keyword, "ASYNC REPLICATION"}, + {Keyword, "BACKUP COLLECTION"}, + {Keyword, "EXTERNAL"}, + {Keyword, "GROUP"}, + {Keyword, "OBJECT"}, + {Keyword, "RESOURCE POOL"}, + {Keyword, "SECRET"}, + {Keyword, "STREAMING QUERY"}, + {Keyword, "TABLE"}, + {Keyword, "TABLESTORE"}, + {Keyword, "TOPIC"}, + {Keyword, "TRANSFER"}, + {Keyword, "USER"}, + {Keyword, "VIEW"}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "DROP "), expected); +} + +Y_UNIT_TEST(DropObject) { + TVector<TCandidate> expected = { + {FolderName, "`.sys/`", 1}, + {FolderName, "`local/`", 1}, + {FolderName, "`prod/`", 1}, + {FolderName, "`test/`", 1}, + {ClusterName, "example"}, + {ClusterName, "loggy"}, + {ClusterName, "saurus"}, + {Keyword, "IF EXISTS"}, + }; + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "DROP TABLE "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "DROP VIEW "), expected); +} + +Y_UNIT_TEST(Explain) { + TVector<TCandidate> expected = { + {Keyword, "ALTER"}, + {Keyword, "ANALYZE"}, + {Keyword, "BACKUP"}, + {Keyword, "BATCH"}, + {Keyword, "COMMIT"}, + {Keyword, "CREATE"}, + {Keyword, "DECLARE"}, + {Keyword, "DEFINE"}, + {Keyword, "DELETE FROM"}, + {Keyword, "DISCARD"}, + {Keyword, "DO"}, + {Keyword, "DROP"}, + {Keyword, "EVALUATE"}, + {Keyword, "EXPORT"}, + {Keyword, "FOR"}, + {Keyword, "FROM"}, + {Keyword, "GRANT"}, + {Keyword, "IF"}, + {Keyword, "IMPORT"}, + {Keyword, "INSERT"}, + {Keyword, "PARALLEL"}, + {Keyword, "PRAGMA"}, + {Keyword, "PROCESS"}, + {Keyword, "QUERY PLAN"}, + {Keyword, "REDUCE"}, + {Keyword, "REPLACE"}, + {Keyword, "RESTORE"}, + {Keyword, "REVOKE"}, + {Keyword, "ROLLBACK"}, + {Keyword, "SELECT"}, + {Keyword, "SHOW CREATE"}, + {Keyword, "UPDATE"}, + {Keyword, "UPSERT"}, + {Keyword, "USE"}, + {Keyword, "VALUES"}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "EXPLAIN "), expected); +} + +Y_UNIT_TEST(Grant) { + TVector<TCandidate> expected = { + {Keyword, "ALL"}, + {Keyword, "ALTER SCHEMA"}, + {Keyword, "CONNECT"}, + {Keyword, "CREATE"}, + {Keyword, "DESCRIBE SCHEMA"}, + {Keyword, "DROP"}, + {Keyword, "ERASE ROW"}, + {Keyword, "FULL"}, + {Keyword, "GRANT"}, + {Keyword, "INSERT"}, + {Keyword, "LIST"}, + {Keyword, "MANAGE"}, + {Keyword, "MODIFY"}, + {Keyword, "REMOVE SCHEMA"}, + {Keyword, "SELECT"}, + {Keyword, "UPDATE ROW"}, + {Keyword, "USE"}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "GRANT "), expected); +} + +Y_UNIT_TEST(Insert) { + TVector<TCandidate> expected = { + {Keyword, "INTO"}, + {Keyword, "OR"}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "INSERT "), expected); +} + +Y_UNIT_TEST(Pragma) { + auto engine = MakeSqlCompletionEngineUT(); + { + TVector<TCandidate> expected = { + {Keyword, "ANSI"}, + {PragmaName, "yson.CastToString"}, + {PragmaName, "yt.RuntimeCluster"}, + {PragmaName, "yt.RuntimeClusterSelection"}}; + auto completion = engine->Complete({"PRAGMA "}).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, ""); + } + { + TVector<TCandidate> expected = { + {PragmaName, "yson.CastToString"}}; + auto completion = engine->Complete({"PRAGMA ys"}).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, "ys"); } - - Y_UNIT_TEST(Beginning) { + { TVector<TCandidate> expected = { - {Keyword, "ALTER"}, - {Keyword, "ANALYZE"}, - {Keyword, "BACKUP"}, - {Keyword, "BATCH"}, - {Keyword, "COMMIT"}, - {Keyword, "CREATE"}, - {Keyword, "DECLARE"}, - {Keyword, "DEFINE"}, - {Keyword, "DELETE FROM"}, - {Keyword, "DISCARD"}, - {Keyword, "DO"}, - {Keyword, "DROP"}, - {Keyword, "EVALUATE"}, - {Keyword, "EXPLAIN"}, - {Keyword, "EXPORT"}, - {Keyword, "FOR"}, - {Keyword, "FROM"}, - {Keyword, "GRANT"}, - {Keyword, "IF"}, - {Keyword, "IMPORT"}, - {Keyword, "INSERT"}, - {Keyword, "PARALLEL"}, - {Keyword, "PRAGMA"}, - {Keyword, "PROCESS"}, - {Keyword, "REDUCE"}, - {Keyword, "REPLACE"}, - {Keyword, "RESTORE"}, - {Keyword, "REVOKE"}, - {Keyword, "ROLLBACK"}, - {Keyword, "SELECT"}, - {Keyword, "SHOW CREATE"}, - {Keyword, "UPDATE"}, - {Keyword, "UPSERT"}, - {Keyword, "USE"}, - {Keyword, "VALUES"}, + {PragmaName, "yson.CastToString"}}; + auto completion = engine->Complete({"PRAGMA yson"}).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, "yson"); + } + { + TVector<TCandidate> expected = { + {PragmaName, "CastToString"}}; + auto completion = engine->Complete({"PRAGMA yson."}).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, ""); + } + { + TVector<TCandidate> expected = { + {PragmaName, "CastToString"}}; + auto completion = engine->Complete({"PRAGMA yson.cast"}).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, "cast"); + } + { + TVector<TCandidate> expected = { + {PragmaName, "RuntimeCluster"}, + {PragmaName, "RuntimeClusterSelection"}}; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "pragma yt."), expected); + UNIT_ASSERT_VALUES_EQUAL( + Complete(engine, "pragma yt.RuntimeClusterSelection='force';\npragma yt.Ru"), + expected); + } + { + TVector<TCandidate> expected = { + {PragmaName, "RuntimeCluster"}, + {PragmaName, "RuntimeClusterSelection"}}; + UNIT_ASSERT_VALUES_EQUAL( + Complete(engine, "pragma yt.Ru#\n"), + expected); + } +} + +Y_UNIT_TEST(Select) { + TVector<TCandidate> expected = { + {Keyword, "ALL"}, + {Keyword, "BITCAST()", 1}, + {Keyword, "CASE"}, + {Keyword, "CAST()", 1}, + {Keyword, "CURRENT_DATE"}, + {Keyword, "CURRENT_TIME"}, + {Keyword, "CURRENT_TIMESTAMP"}, + {TypeName, "Callable<>", 1}, + {Keyword, "DISTINCT"}, + {FunctionName, "DateTime::Split()", 1}, + {TypeName, "Decimal()", 1}, + {TypeName, "Dict<>", 1}, + {Keyword, "EMPTY_ACTION"}, + {Keyword, "EXISTS()", 1}, + {TypeName, "Enum<>", 1}, + {Keyword, "FALSE"}, + {TypeName, "Flow<>", 1}, + {Keyword, "JSON_EXISTS()", 1}, + {Keyword, "JSON_QUERY()", 1}, + {Keyword, "JSON_VALUE()", 1}, + {TypeName, "List<>", 1}, + {Keyword, "NOT"}, + {Keyword, "NULL"}, + {TypeName, "Optional<>", 1}, + {FunctionName, "Python::__private()", 1}, + {TypeName, "Resource<>", 1}, + {Keyword, "STREAM"}, + {TypeName, "Set<>", 1}, + {FunctionName, "StartsWith()", 1}, + {TypeName, "Stream<>", 1}, + {TypeName, "Struct<>", 1}, + {Keyword, "TRUE"}, + {TypeName, "Tagged<>", 1}, + {TypeName, "Tuple<>", 1}, + {TypeName, "Uint64"}, + {TypeName, "Variant<>", 1}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT # FROM"), expected); +} + +Y_UNIT_TEST(SelectFrom) { + auto engine = MakeSqlCompletionEngineUT(); + { + TVector<TCandidate> expected = { + {FolderName, "`.sys/`", 1}, + {FolderName, "`local/`", 1}, + {FolderName, "`prod/`", 1}, + {FolderName, "`test/`", 1}, + {ClusterName, "example"}, + {ClusterName, "loggy"}, + {ClusterName, "saurus"}, + {Keyword, "ANY"}, + {FunctionName, "CONCAT()", 1}, + {FunctionName, "EACH()", 1}, + {FunctionName, "FILTER()", 1}, + {FunctionName, "FOLDER()", 1}, + {FunctionName, "LIKE()", 1}, + {FunctionName, "PARTITION_LIST()", 1}, + {FunctionName, "RANGE()", 1}, + {FunctionName, "REGEXP()", 1}, + {FunctionName, "WalkFolders()", 1}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM "), expected); + } + { + TString input = "SELECT * FROM pr"; + TVector<TCandidate> expected = { + {FolderName, "`prod/`", 1}, + }; + TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, "pr"); + } + { + TVector<TCandidate> expected = { + {FolderName, ".sys/`", 1}, + {FolderName, "local/`", 1}, + {FolderName, "prod/`", 1}, + {FolderName, "test/`", 1}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM `#"), expected); + } + { + TString input = "SELECT * FROM `#`"; + TVector<TCandidate> expected = { + {FolderName, ".sys/"}, + {FolderName, "local/"}, + {FolderName, "prod/"}, + {FolderName, "test/"}, + }; + TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, ""); + } + { + TString input = "SELECT * FROM `local/#`"; + TVector<TCandidate> expected = { + {TableName, "abacaba"}, + {TableName, "account"}, + {TableName, "example"}, + }; + TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, ""); + } + { + TString input = "SELECT * FROM `local/a#`"; + TVector<TCandidate> expected = { + {TableName, "abacaba"}, + {TableName, "account"}, }; + TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, "a"); + } + { + TString input = "SELECT * FROM `.sy#`"; + TVector<TCandidate> expected = { + {FolderName, ".sys/"}, + }; + TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, ".sy"); + } + { + TString input = "SELECT * FROM `/test/ser#vice/`"; + TVector<TCandidate> expected = { + {FolderName, "service/"}, + }; + TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, "ser"); + } +} - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, ""), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, " "), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, " "), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, ";"), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "; "), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, " ; "), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "#SELECT"), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "#SELECT * FROM"), expected); +Y_UNIT_TEST(SelectFromUnclosedIdQuoted) { + auto engine = MakeSqlCompletionEngineUT(); + { + TVector<TCandidate> expected = { + {FolderName, ".sys/`", 1}, + {FolderName, "local/`", 1}, + {FolderName, "prod/`", 1}, + {FolderName, "test/`", 1}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(4, engine, "SELECT * FROM `#"), expected); + } + { + TVector<TCandidate> expected = { + {TableName, "meta`"}, + {FolderName, "service/`", 1}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM `test/"), expected); } +} - Y_UNIT_TEST(Use) { +Y_UNIT_TEST(SelectFromCluster) { + auto engine = MakeSqlCompletionEngineUT(); + { TVector<TCandidate> expected = { {ClusterName, "example"}, {ClusterName, "loggy"}, {ClusterName, "saurus"}, }; - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "USE "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM yt:"), expected); } - - Y_UNIT_TEST(UseClusterResultion) { - auto engine = MakeSqlCompletionEngineUT(); - { - TString query = R"sql( - DECLARE $cluster_name AS String; - USE yt:$cluster_name; - SELECT * FROM # - )sql"; - - TEnvironment env = { - .Parameters = {{"$cluster_name", "saurus"}}, - }; - - TVector<TCandidate> expected = { - {TableName, "`maxim`"}, - {BindingName, "$cluster_name"}, - {ClusterName, "example"}, - {ClusterName, "loggy"}, - {ClusterName, "saurus"}, - }; - - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(5, engine, query, env), expected); - } - { - TVector<TCandidate> expected = { - {FolderName, "`.sys/`", 1}, - {FolderName, "`local/`", 1}, - {FolderName, "`prod/`", 1}, - {FolderName, "`test/`", 1}, - {ClusterName, "example"}, - {ClusterName, "loggy"}, - {ClusterName, "saurus"}, - {Keyword, "ANY"}, - }; - UNIT_ASSERT_VALUES_EQUAL( - CompleteTop( - 8, - engine, - "USE yt:$cluster_name; SELECT * FROM ", - {.Parameters = {}}), - expected); - } - } - - Y_UNIT_TEST(Alter) { - TVector<TCandidate> expected = { - {Keyword, "ASYNC REPLICATION"}, - {Keyword, "BACKUP COLLECTION"}, - {Keyword, "DATABASE"}, - {Keyword, "EXTERNAL"}, - {Keyword, "GROUP"}, - {Keyword, "OBJECT"}, - {Keyword, "RESOURCE POOL"}, - {Keyword, "SECRET"}, - {Keyword, "SEQUENCE"}, - {Keyword, "STREAMING QUERY"}, - {Keyword, "TABLE"}, - {Keyword, "TABLESTORE"}, - {Keyword, "TOPIC"}, - {Keyword, "TRANSFER"}, - {Keyword, "USER"}, + { + TVector<TCandidate> expected = { + {ClusterName, "saurus"}, }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "ALTER "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM yt:saurus#"), expected); } - - Y_UNIT_TEST(Create) { + { TVector<TCandidate> expected = { - {Keyword, "ASYNC REPLICATION"}, - {Keyword, "BACKUP COLLECTION"}, - {Keyword, "EXTERNAL"}, - {Keyword, "GROUP"}, - {Keyword, "OBJECT"}, - {Keyword, "OR REPLACE"}, - {Keyword, "RESOURCE POOL"}, - {Keyword, "SECRET"}, - {Keyword, "STREAMING QUERY"}, - {Keyword, "TABLE"}, - {Keyword, "TABLESTORE"}, - {Keyword, "TEMP TABLE"}, - {Keyword, "TEMPORARY TABLE"}, - {Keyword, "TOPIC"}, - {Keyword, "TRANSFER"}, - {Keyword, "USER"}, - {Keyword, "VIEW"}, - }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "CREATE "), expected); - } - - Y_UNIT_TEST(CreateTable) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {FolderName, "`.sys/`", 1}, - {FolderName, "`local/`", 1}, - {FolderName, "`prod/`", 1}, - {FolderName, "`test/`", 1}, - {ClusterName, "example"}, - {ClusterName, "loggy"}, - {ClusterName, "saurus"}, - {Keyword, "IF NOT EXISTS"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "CREATE TABLE #"), expected); - } - { - TVector<TCandidate> expected = { - {FolderName, "service/"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "CREATE TABLE `test/#`"), expected); - } - } - - Y_UNIT_TEST(Delete) { + {TableName, "`maxim`"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT * FROM yt:saurus."), expected); + } + { TVector<TCandidate> expected = { - {Keyword, "FROM"}, + {TableName, "`people`"}, }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "DELETE "), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT * FROM example."), expected); } - - Y_UNIT_TEST(Drop) { + { TVector<TCandidate> expected = { - {Keyword, "ASYNC REPLICATION"}, - {Keyword, "BACKUP COLLECTION"}, - {Keyword, "EXTERNAL"}, - {Keyword, "GROUP"}, - {Keyword, "OBJECT"}, - {Keyword, "RESOURCE POOL"}, - {Keyword, "SECRET"}, - {Keyword, "STREAMING QUERY"}, - {Keyword, "TABLE"}, - {Keyword, "TABLESTORE"}, - {Keyword, "TOPIC"}, - {Keyword, "TRANSFER"}, - {Keyword, "USER"}, - {Keyword, "VIEW"}, + {TableName, "tutorial"}, }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "DROP "), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT * FROM example.`/yql/t#`"), expected); } +} - Y_UNIT_TEST(DropObject) { +Y_UNIT_TEST(SelectFromWithUse) { + auto engine = MakeSqlCompletionEngineUT(); + { TVector<TCandidate> expected = { - {FolderName, "`.sys/`", 1}, - {FolderName, "`local/`", 1}, - {FolderName, "`prod/`", 1}, - {FolderName, "`test/`", 1}, + {TableName, "`maxim`"}, {ClusterName, "example"}, {ClusterName, "loggy"}, {ClusterName, "saurus"}, - {Keyword, "IF EXISTS"}, - }; - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "DROP TABLE "), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "DROP VIEW "), expected); - } - - Y_UNIT_TEST(Explain) { - TVector<TCandidate> expected = { - {Keyword, "ALTER"}, - {Keyword, "ANALYZE"}, - {Keyword, "BACKUP"}, - {Keyword, "BATCH"}, - {Keyword, "COMMIT"}, - {Keyword, "CREATE"}, - {Keyword, "DECLARE"}, - {Keyword, "DEFINE"}, - {Keyword, "DELETE FROM"}, - {Keyword, "DISCARD"}, - {Keyword, "DO"}, - {Keyword, "DROP"}, - {Keyword, "EVALUATE"}, - {Keyword, "EXPORT"}, - {Keyword, "FOR"}, - {Keyword, "FROM"}, - {Keyword, "GRANT"}, - {Keyword, "IF"}, - {Keyword, "IMPORT"}, - {Keyword, "INSERT"}, - {Keyword, "PARALLEL"}, - {Keyword, "PRAGMA"}, - {Keyword, "PROCESS"}, - {Keyword, "QUERY PLAN"}, - {Keyword, "REDUCE"}, - {Keyword, "REPLACE"}, - {Keyword, "RESTORE"}, - {Keyword, "REVOKE"}, - {Keyword, "ROLLBACK"}, - {Keyword, "SELECT"}, - {Keyword, "SHOW CREATE"}, - {Keyword, "UPDATE"}, - {Keyword, "UPSERT"}, - {Keyword, "USE"}, - {Keyword, "VALUES"}, + {Keyword, "ANY"}, }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "EXPLAIN "), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(5, engine, "USE yt:saurus; SELECT * FROM "), expected); } - - Y_UNIT_TEST(Grant) { + { TVector<TCandidate> expected = { - {Keyword, "ALL"}, - {Keyword, "ALTER SCHEMA"}, - {Keyword, "CONNECT"}, - {Keyword, "CREATE"}, - {Keyword, "DESCRIBE SCHEMA"}, - {Keyword, "DROP"}, - {Keyword, "ERASE ROW"}, - {Keyword, "FULL"}, - {Keyword, "GRANT"}, - {Keyword, "INSERT"}, - {Keyword, "LIST"}, - {Keyword, "MANAGE"}, - {Keyword, "MODIFY"}, - {Keyword, "REMOVE SCHEMA"}, - {Keyword, "SELECT"}, - {Keyword, "UPDATE ROW"}, - {Keyword, "USE"}, + {TableName, "`people`"}, + {FolderName, "`yql/`", 1}, }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "GRANT "), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "USE yt:saurus; SELECT * FROM example."), expected); } - - Y_UNIT_TEST(Insert) { + { TVector<TCandidate> expected = { - {Keyword, "INTO"}, - {Keyword, "OR"}, + {TableName, "`maxim`"}, + {ClusterName, "example"}, + {ClusterName, "loggy"}, + {ClusterName, "saurus"}, + {Keyword, "ANY"}, }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "INSERT "), expected); - } - - Y_UNIT_TEST(Pragma) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {Keyword, "ANSI"}, - {PragmaName, "yson.CastToString"}, - {PragmaName, "yt.RuntimeCluster"}, - {PragmaName, "yt.RuntimeClusterSelection"}}; - auto completion = engine->Complete({"PRAGMA "}).GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, ""); - } - { - TVector<TCandidate> expected = { - {PragmaName, "yson.CastToString"}}; - auto completion = engine->Complete({"PRAGMA ys"}).GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, "ys"); - } - { - TVector<TCandidate> expected = { - {PragmaName, "yson.CastToString"}}; - auto completion = engine->Complete({"PRAGMA yson"}).GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, "yson"); - } - { - TVector<TCandidate> expected = { - {PragmaName, "CastToString"}}; - auto completion = engine->Complete({"PRAGMA yson."}).GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, ""); - } - { - TVector<TCandidate> expected = { - {PragmaName, "CastToString"}}; - auto completion = engine->Complete({"PRAGMA yson.cast"}).GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, "cast"); - } - { - TVector<TCandidate> expected = { - {PragmaName, "RuntimeCluster"}, - {PragmaName, "RuntimeClusterSelection"}}; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "pragma yt."), expected); - UNIT_ASSERT_VALUES_EQUAL( - Complete(engine, "pragma yt.RuntimeClusterSelection='force';\npragma yt.Ru"), - expected); - } - { - TVector<TCandidate> expected = { - {PragmaName, "RuntimeCluster"}, - {PragmaName, "RuntimeClusterSelection"}}; - UNIT_ASSERT_VALUES_EQUAL( - Complete(engine, "pragma yt.Ru#\n"), - expected); - } - } - - Y_UNIT_TEST(Select) { + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(5, engine, "USE example; USE yt:saurus; SELECT * FROM "), expected); + } + { TVector<TCandidate> expected = { - {Keyword, "ALL"}, - {Keyword, "BITCAST()", 1}, - {Keyword, "CASE"}, - {Keyword, "CAST()", 1}, - {Keyword, "CURRENT_DATE"}, - {Keyword, "CURRENT_TIME"}, - {Keyword, "CURRENT_TIMESTAMP"}, - {TypeName, "Callable<>", 1}, - {Keyword, "DISTINCT"}, - {FunctionName, "DateTime::Split()", 1}, - {TypeName, "Decimal()", 1}, - {TypeName, "Dict<>", 1}, - {Keyword, "EMPTY_ACTION"}, - {Keyword, "EXISTS()", 1}, - {TypeName, "Enum<>", 1}, - {Keyword, "FALSE"}, - {TypeName, "Flow<>", 1}, - {Keyword, "JSON_EXISTS()", 1}, - {Keyword, "JSON_QUERY()", 1}, - {Keyword, "JSON_VALUE()", 1}, - {TypeName, "List<>", 1}, - {Keyword, "NOT"}, - {Keyword, "NULL"}, - {TypeName, "Optional<>", 1}, - {FunctionName, "Python::__private()", 1}, - {TypeName, "Resource<>", 1}, - {Keyword, "STREAM"}, - {TypeName, "Set<>", 1}, - {FunctionName, "StartsWith()", 1}, - {TypeName, "Stream<>", 1}, - {TypeName, "Struct<>", 1}, - {Keyword, "TRUE"}, - {TypeName, "Tagged<>", 1}, - {TypeName, "Tuple<>", 1}, - {TypeName, "Uint64"}, - {TypeName, "Variant<>", 1}, - }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT "), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT # FROM"), expected); - } - - Y_UNIT_TEST(SelectFrom) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {FolderName, "`.sys/`", 1}, - {FolderName, "`local/`", 1}, - {FolderName, "`prod/`", 1}, - {FolderName, "`test/`", 1}, - {ClusterName, "example"}, - {ClusterName, "loggy"}, - {ClusterName, "saurus"}, - {Keyword, "ANY"}, - {FunctionName, "CONCAT()", 1}, - {FunctionName, "EACH()", 1}, - {FunctionName, "FILTER()", 1}, - {FunctionName, "FOLDER()", 1}, - {FunctionName, "LIKE()", 1}, - {FunctionName, "PARTITION_LIST()", 1}, - {FunctionName, "RANGE()", 1}, - {FunctionName, "REGEXP()", 1}, - {FunctionName, "WalkFolders()", 1}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM "), expected); - } - { - TString input = "SELECT * FROM pr"; - TVector<TCandidate> expected = { - {FolderName, "`prod/`", 1}, - }; - TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, "pr"); - } - { - TVector<TCandidate> expected = { - {FolderName, ".sys/`", 1}, - {FolderName, "local/`", 1}, - {FolderName, "prod/`", 1}, - {FolderName, "test/`", 1}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM `#"), expected); - } - { - TString input = "SELECT * FROM `#`"; - TVector<TCandidate> expected = { - {FolderName, ".sys/"}, - {FolderName, "local/"}, - {FolderName, "prod/"}, - {FolderName, "test/"}, - }; - TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, ""); - } - { - TString input = "SELECT * FROM `local/#`"; - TVector<TCandidate> expected = { - {TableName, "abacaba"}, - {TableName, "account"}, - {TableName, "example"}, - }; - TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, ""); - } - { - TString input = "SELECT * FROM `local/a#`"; - TVector<TCandidate> expected = { - {TableName, "abacaba"}, - {TableName, "account"}, - }; - TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, "a"); - } - { - TString input = "SELECT * FROM `.sy#`"; - TVector<TCandidate> expected = { - {FolderName, ".sys/"}, - }; - TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, ".sy"); - } - { - TString input = "SELECT * FROM `/test/ser#vice/`"; - TVector<TCandidate> expected = { - {FolderName, "service/"}, - }; - TCompletion actual = engine->Complete(SharpedInput(input)).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(actual.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(actual.CompletedToken.Content, "ser"); - } - } - - Y_UNIT_TEST(SelectFromUnclosedIdQuoted) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {FolderName, ".sys/`", 1}, - {FolderName, "local/`", 1}, - {FolderName, "prod/`", 1}, - {FolderName, "test/`", 1}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(4, engine, "SELECT * FROM `#"), expected); - } - { - TVector<TCandidate> expected = { - {TableName, "meta`"}, - {FolderName, "service/`", 1}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM `test/"), expected); - } - } - - Y_UNIT_TEST(SelectFromCluster) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {ClusterName, "example"}, - {ClusterName, "loggy"}, - {ClusterName, "saurus"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM yt:"), expected); - } - { - TVector<TCandidate> expected = { - {ClusterName, "saurus"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM yt:saurus#"), expected); - } - { - TVector<TCandidate> expected = { - {TableName, "`maxim`"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT * FROM yt:saurus."), expected); - } - { - TVector<TCandidate> expected = { - {TableName, "`people`"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT * FROM example."), expected); - } - { - TVector<TCandidate> expected = { - {TableName, "tutorial"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT * FROM example.`/yql/t#`"), expected); - } - } - - Y_UNIT_TEST(SelectFromWithUse) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {TableName, "`maxim`"}, - {ClusterName, "example"}, - {ClusterName, "loggy"}, - {ClusterName, "saurus"}, - {Keyword, "ANY"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(5, engine, "USE yt:saurus; SELECT * FROM "), expected); - } - { - TVector<TCandidate> expected = { - {TableName, "`people`"}, - {FolderName, "`yql/`", 1}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "USE yt:saurus; SELECT * FROM example."), expected); - } - { - TVector<TCandidate> expected = { - {TableName, "`maxim`"}, - {ClusterName, "example"}, - {ClusterName, "loggy"}, - {ClusterName, "saurus"}, - {Keyword, "ANY"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(5, engine, "USE example; USE yt:saurus; SELECT * FROM "), expected); - } - { - TVector<TCandidate> expected = { - {TableName, "`maxim`"}, - {BindingName, "$hello"}, - {ClusterName, "example"}, - {ClusterName, "loggy"}, - {ClusterName, "saurus"}, - {Keyword, "ANY"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(6, engine, R"( + {TableName, "`maxim`"}, + {BindingName, "$hello"}, + {ClusterName, "example"}, + {ClusterName, "loggy"}, + {ClusterName, "saurus"}, + {Keyword, "ANY"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(6, engine, R"( USE example; DEFINE ACTION $hello() AS USE yt:saurus; SELECT * FROM #; END DEFINE; )"), expected); - } - { - TVector<TCandidate> expected = { - {TableName, "`people`"}, - {FolderName, "`yql/`", 1}, - {BindingName, "$action"}, - {ClusterName, "example"}, - {ClusterName, "loggy"}, - {ClusterName, "saurus"}, - {Keyword, "ANY"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(7, engine, R"( + } + { + TVector<TCandidate> expected = { + {TableName, "`people`"}, + {FolderName, "`yql/`", 1}, + {BindingName, "$action"}, + {ClusterName, "example"}, + {ClusterName, "loggy"}, + {ClusterName, "saurus"}, + {Keyword, "ANY"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(7, engine, R"( USE example; DEFINE ACTION $action() AS @@ -804,572 +804,572 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { SELECT * FROM # )"), expected); - } } - - Y_UNIT_TEST(SelectWhere) { +} + +Y_UNIT_TEST(SelectWhere) { + TVector<TCandidate> expected = { + {Keyword, "BITCAST()", 1}, + {Keyword, "CASE"}, + {Keyword, "CAST()", 1}, + {Keyword, "CURRENT_DATE"}, + {Keyword, "CURRENT_TIME"}, + {Keyword, "CURRENT_TIMESTAMP"}, + {TypeName, "Callable<>", 1}, + {FunctionName, "DateTime::Split()", 1}, + {TypeName, "Decimal()", 1}, + {TypeName, "Dict<>", 1}, + {Keyword, "EMPTY_ACTION"}, + {Keyword, "EXISTS()", 1}, + {TypeName, "Enum<>", 1}, + {Keyword, "FALSE"}, + {TypeName, "Flow<>", 1}, + {Keyword, "JSON_EXISTS()", 1}, + {Keyword, "JSON_QUERY()", 1}, + {Keyword, "JSON_VALUE()", 1}, + {TypeName, "List<>", 1}, + {Keyword, "NOT"}, + {Keyword, "NULL"}, + {TypeName, "Optional<>", 1}, + {FunctionName, "Python::__private()", 1}, + {TypeName, "Resource<>", 1}, + {TypeName, "Set<>", 1}, + {FunctionName, "StartsWith()", 1}, + {TypeName, "Stream<>", 1}, + {TypeName, "Struct<>", 1}, + {Keyword, "TRUE"}, + {TypeName, "Tagged<>", 1}, + {TypeName, "Tuple<>", 1}, + {TypeName, "Uint64"}, + {TypeName, "Variant<>", 1}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM a WHERE "), expected); +} + +Y_UNIT_TEST(SelectSubquery) { + auto engine = MakeSqlCompletionEngineUT(); + + TVector<TCandidate> expected = { + {Keyword, "SELECT"}, + }; + + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "$x = sel#"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "$x = (sel#)"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT (sel#)"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM t WHERE (sel#)"), expected); +} + +Y_UNIT_TEST(Upsert) { + TVector<TCandidate> expected = { + {Keyword, "INTO"}, + {Keyword, "OBJECT"}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "UPSERT "), expected); +} + +Y_UNIT_TEST(UpsertInto) { + auto engine = MakeSqlCompletionEngineUT(); + { TVector<TCandidate> expected = { - {Keyword, "BITCAST()", 1}, - {Keyword, "CASE"}, - {Keyword, "CAST()", 1}, - {Keyword, "CURRENT_DATE"}, - {Keyword, "CURRENT_TIME"}, - {Keyword, "CURRENT_TIMESTAMP"}, - {TypeName, "Callable<>", 1}, - {FunctionName, "DateTime::Split()", 1}, - {TypeName, "Decimal()", 1}, - {TypeName, "Dict<>", 1}, - {Keyword, "EMPTY_ACTION"}, - {Keyword, "EXISTS()", 1}, - {TypeName, "Enum<>", 1}, - {Keyword, "FALSE"}, - {TypeName, "Flow<>", 1}, - {Keyword, "JSON_EXISTS()", 1}, - {Keyword, "JSON_QUERY()", 1}, - {Keyword, "JSON_VALUE()", 1}, - {TypeName, "List<>", 1}, - {Keyword, "NOT"}, - {Keyword, "NULL"}, - {TypeName, "Optional<>", 1}, - {FunctionName, "Python::__private()", 1}, - {TypeName, "Resource<>", 1}, - {TypeName, "Set<>", 1}, - {FunctionName, "StartsWith()", 1}, - {TypeName, "Stream<>", 1}, - {TypeName, "Struct<>", 1}, - {Keyword, "TRUE"}, - {TypeName, "Tagged<>", 1}, - {TypeName, "Tuple<>", 1}, - {TypeName, "Uint64"}, - {TypeName, "Variant<>", 1}, + {FolderName, "`.sys/`", 1}, + {FolderName, "`local/`", 1}, + {FolderName, "`prod/`", 1}, + {FolderName, "`test/`", 1}, + {ClusterName, "example"}, + {ClusterName, "loggy"}, + {ClusterName, "saurus"}, }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM a WHERE "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "UPSERT INTO "), expected); } + { + TVector<TCandidate> expected = { + {TableName, "meta"}, + {FolderName, "service/"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "UPSERT INTO `test/#`"), expected); + } +} - Y_UNIT_TEST(SelectSubquery) { - auto engine = MakeSqlCompletionEngineUT(); +Y_UNIT_TEST(AlterObject) { + auto engine = MakeSqlCompletionEngineUT(); + TString query = R"sql( + ALTER OBJECT example.`#` + )sql"; + + TVector<TCandidate> expected = { + {FolderName, "yql/"}, + {UnknownName, "link"}, + {UnknownName, "topic"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, query), expected); +} + +Y_UNIT_TEST(TypeName) { + TVector<TCandidate> expected = { + {TypeName, "Callable<>", 1}, + {TypeName, "Decimal()", 1}, + {TypeName, "Dict<>", 1}, + {TypeName, "Enum<>", 1}, + {TypeName, "Flow<>", 1}, + {TypeName, "List<>", 1}, + {TypeName, "Optional<>", 1}, + {TypeName, "Resource<>", 1}, + {TypeName, "Set<>", 1}, + {TypeName, "Stream<>", 1}, + {TypeName, "Struct<>", 1}, + {TypeName, "Tagged<>", 1}, + {TypeName, "Tuple<>", 1}, + {TypeName, "Uint64"}, + {TypeName, "Variant<>", 1}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "CREATE TABLE table (id "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT CAST (1 AS "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Optional<"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Optional<#>"), expected); +} + +Y_UNIT_TEST(TypeNameAsArgument) { + auto engine = MakeSqlCompletionEngineUT(); + { TVector<TCandidate> expected = { - {Keyword, "SELECT"}, + {TypeName, "Uint64"}, }; - - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "$x = sel#"), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "$x = (sel#)"), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT (sel#)"), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM t WHERE (sel#)"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Nothing(Uint"), expected); } - - Y_UNIT_TEST(Upsert) { + { TVector<TCandidate> expected = { - {Keyword, "INTO"}, - {Keyword, "OBJECT"}, + {TypeName, "Optional<>", 1}, }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "UPSERT "), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Nothing(Option"), expected); } +} - Y_UNIT_TEST(UpsertInto) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {FolderName, "`.sys/`", 1}, - {FolderName, "`local/`", 1}, - {FolderName, "`prod/`", 1}, - {FolderName, "`test/`", 1}, - {ClusterName, "example"}, - {ClusterName, "loggy"}, - {ClusterName, "saurus"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "UPSERT INTO "), expected); - } - { - TVector<TCandidate> expected = { - {TableName, "meta"}, - {FolderName, "service/"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "UPSERT INTO `test/#`"), expected); - } +Y_UNIT_TEST(FunctionName) { + auto engine = MakeSqlCompletionEngineUT(); + { + TVector<TCandidate> expected = { + {FunctionName, "DateTime::Split()", 1}, + }; + auto completion = engine->Complete({"SELECT Date"}).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, "Date"); } - - Y_UNIT_TEST(AlterObject) { - auto engine = MakeSqlCompletionEngineUT(); - - TString query = R"sql( - ALTER OBJECT example.`#` - )sql"; - + { + TVector<TCandidate> expected = { + {FunctionName, "Split()", 1}, + }; + auto completion = engine->Complete({"SELECT DateTime:"}).GetValueSync(); + UNIT_ASSERT(completion.Candidates.empty()); + } + { TVector<TCandidate> expected = { - {FolderName, "yql/"}, - {UnknownName, "link"}, - {UnknownName, "topic"}, + {FunctionName, "Split()", 1}, }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, query), expected); + auto completion = engine->Complete({"SELECT DateTime::"}).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, ""); } + { + TVector<TCandidate> expected = { + {FunctionName, "Split()", 1}, + }; + auto completion = engine->Complete({"SELECT DateTime::s"}).GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); + UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, "s"); + } +} - Y_UNIT_TEST(TypeName) { +Y_UNIT_TEST(SelectTableHintName) { + auto engine = MakeSqlCompletionEngineUT(); + { TVector<TCandidate> expected = { - {TypeName, "Callable<>", 1}, - {TypeName, "Decimal()", 1}, - {TypeName, "Dict<>", 1}, - {TypeName, "Enum<>", 1}, - {TypeName, "Flow<>", 1}, - {TypeName, "List<>", 1}, - {TypeName, "Optional<>", 1}, - {TypeName, "Resource<>", 1}, - {TypeName, "Set<>", 1}, - {TypeName, "Stream<>", 1}, - {TypeName, "Struct<>", 1}, - {TypeName, "Tagged<>", 1}, - {TypeName, "Tuple<>", 1}, - {TypeName, "Uint64"}, - {TypeName, "Variant<>", 1}, - }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "CREATE TABLE table (id "), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT CAST (1 AS "), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Optional<"), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Optional<#>"), expected); - } - - Y_UNIT_TEST(TypeNameAsArgument) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {TypeName, "Uint64"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Nothing(Uint"), expected); - } - { - TVector<TCandidate> expected = { - {TypeName, "Optional<>", 1}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Nothing(Option"), expected); - } - } - - Y_UNIT_TEST(FunctionName) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {FunctionName, "DateTime::Split()", 1}, - }; - auto completion = engine->Complete({"SELECT Date"}).GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, "Date"); - } - { - TVector<TCandidate> expected = { - {FunctionName, "Split()", 1}, - }; - auto completion = engine->Complete({"SELECT DateTime:"}).GetValueSync(); - UNIT_ASSERT(completion.Candidates.empty()); - } - { - TVector<TCandidate> expected = { - {FunctionName, "Split()", 1}, - }; - auto completion = engine->Complete({"SELECT DateTime::"}).GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, ""); - } - { - TVector<TCandidate> expected = { - {FunctionName, "Split()", 1}, - }; - auto completion = engine->Complete({"SELECT DateTime::s"}).GetValueSync(); - UNIT_ASSERT_VALUES_EQUAL(completion.Candidates, expected); - UNIT_ASSERT_VALUES_EQUAL(completion.CompletedToken.Content, "s"); - } - } - - Y_UNIT_TEST(SelectTableHintName) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {HintName, "XLOCK"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "PROCESS my_table USING $udf(TableRows()) WITH "), expected); - } - { - TVector<TCandidate> expected = { - {Keyword, "COLUMNS"}, - {Keyword, "SCHEMA"}, - {Keyword, "WATERMARK AS()", 1}, - {HintName, "XLOCK"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "REDUCE my_table WITH "), expected); - } - { - TVector<TCandidate> expected = { - {Keyword, "COLUMNS"}, - {Keyword, "SCHEMA"}, - {Keyword, "WATERMARK AS()", 1}, - {HintName, "XLOCK"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT key FROM my_table WITH "), expected); - } - } - - Y_UNIT_TEST(InsertTableHintName) { + {HintName, "XLOCK"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "PROCESS my_table USING $udf(TableRows()) WITH "), expected); + } + { TVector<TCandidate> expected = { {Keyword, "COLUMNS"}, - {HintName, "EXPIRATION"}, {Keyword, "SCHEMA"}, {Keyword, "WATERMARK AS()", 1}, + {HintName, "XLOCK"}, }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "REDUCE my_table WITH "), expected); + } + { + TVector<TCandidate> expected = { + {Keyword, "COLUMNS"}, + {Keyword, "SCHEMA"}, + {Keyword, "WATERMARK AS()", 1}, + {HintName, "XLOCK"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT key FROM my_table WITH "), expected); + } +} - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "INSERT INTO my_table WITH "), expected); - } - - Y_UNIT_TEST(CursorPosition) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {Keyword, "AND"}, - {Keyword, "AS"}, - {Keyword, "ASSUME"}, - {Keyword, "BETWEEN"}, - {Keyword, "COLLATE"}, - {Keyword, "EXCEPT"}, - {Keyword, "FROM"}, - {Keyword, "GLOB"}, - {Keyword, "GROUP"}, - {Keyword, "HAVING"}, - {Keyword, "ILIKE"}, - {Keyword, "IN"}, - {Keyword, "INTERSECT"}, - {Keyword, "INTO RESULT"}, - {Keyword, "IS"}, - {Keyword, "ISNULL"}, - {Keyword, "LIKE"}, - {Keyword, "LIMIT"}, - {Keyword, "MATCH"}, - {Keyword, "NOT"}, - {Keyword, "NOTNULL"}, - {Keyword, "OR"}, - {Keyword, "ORDER BY"}, - {Keyword, "REGEXP"}, - {Keyword, "RLIKE"}, - {Keyword, "UNION"}, - {Keyword, "WHERE"}, - {Keyword, "WINDOW"}, - {Keyword, "WITHOUT"}, - {Keyword, "XOR"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `a`"), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `a`#FROM"), expected); - } - { - TVector<TCandidate> expected = { - {Keyword, "FROM"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM# "), expected); - } - } - - Y_UNIT_TEST(Enclosed) { - TVector<TCandidate> empty = {}; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT \"#\""), empty); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `#`"), empty); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT 21#21"), empty); - - UNIT_ASSERT(FindPtr(Complete(engine, "SELECT `name`#"), TCandidate{Keyword, "FROM"}) != nullptr); - UNIT_ASSERT(FindPtr(Complete(engine, "SELECT #`name`"), TCandidate{FunctionName, "StartsWith()", 1}) != nullptr); - - UNIT_ASSERT_GT_C(Complete(engine, "SELECT \"a\"#\"b\"").size(), 0, "Between tokens"); - UNIT_ASSERT_VALUES_EQUAL_C(Complete(engine, "SELECT `a`#`b`"), empty, "Solid ID_QUOTED"); - UNIT_ASSERT_VALUES_EQUAL_C(Complete(engine, "SELECT `a#\\`b`"), empty, "Solid ID_QUOTED"); - UNIT_ASSERT_VALUES_EQUAL_C(Complete(engine, "SELECT `a\\#`b`"), empty, "Solid ID_QUOTED"); - UNIT_ASSERT_VALUES_EQUAL_C(Complete(engine, "SELECT `a\\`#b`"), empty, "Solid ID_QUOTED"); - } - - Y_UNIT_TEST(SemiEnclosed) { - TVector<TCandidate> expected = {}; +Y_UNIT_TEST(InsertTableHintName) { + TVector<TCandidate> expected = { + {Keyword, "COLUMNS"}, + {HintName, "EXPIRATION"}, + {Keyword, "SCHEMA"}, + {Keyword, "WATERMARK AS()", 1}, + }; - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT \""), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `"), expected); - } + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "INSERT INTO my_table WITH "), expected); +} - Y_UNIT_TEST(UTF8Wide) { - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "\xF0\x9F\x98\x8A").size(), 0); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "编码").size(), 0); +Y_UNIT_TEST(CursorPosition) { + auto engine = MakeSqlCompletionEngineUT(); + { + TVector<TCandidate> expected = { + {Keyword, "AND"}, + {Keyword, "AS"}, + {Keyword, "ASSUME"}, + {Keyword, "BETWEEN"}, + {Keyword, "COLLATE"}, + {Keyword, "EXCEPT"}, + {Keyword, "FROM"}, + {Keyword, "GLOB"}, + {Keyword, "GROUP"}, + {Keyword, "HAVING"}, + {Keyword, "ILIKE"}, + {Keyword, "IN"}, + {Keyword, "INTERSECT"}, + {Keyword, "INTO RESULT"}, + {Keyword, "IS"}, + {Keyword, "ISNULL"}, + {Keyword, "LIKE"}, + {Keyword, "LIMIT"}, + {Keyword, "MATCH"}, + {Keyword, "NOT"}, + {Keyword, "NOTNULL"}, + {Keyword, "OR"}, + {Keyword, "ORDER BY"}, + {Keyword, "REGEXP"}, + {Keyword, "RLIKE"}, + {Keyword, "UNION"}, + {Keyword, "WHERE"}, + {Keyword, "WINDOW"}, + {Keyword, "WITHOUT"}, + {Keyword, "XOR"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `a`"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `a`#FROM"), expected); } - - Y_UNIT_TEST(WordBreak) { - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_GE(Complete(engine, "SELECT (").size(), 29); - UNIT_ASSERT_GE(Complete(engine, "SELECT (1)").size(), 30); - UNIT_ASSERT_GE(Complete(engine, "SELECT 1;").size(), 35); + { + TVector<TCandidate> expected = { + {Keyword, "FROM"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM# "), expected); } +} - Y_UNIT_TEST(Bindings) { - auto engine = MakeSqlCompletionEngineUT(); +Y_UNIT_TEST(Enclosed) { + TVector<TCandidate> empty = {}; - TString query = R"( + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT \"#\""), empty); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `#`"), empty); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT 21#21"), empty); + + UNIT_ASSERT(FindPtr(Complete(engine, "SELECT `name`#"), TCandidate{Keyword, "FROM"}) != nullptr); + UNIT_ASSERT(FindPtr(Complete(engine, "SELECT #`name`"), TCandidate{FunctionName, "StartsWith()", 1}) != nullptr); + + UNIT_ASSERT_GT_C(Complete(engine, "SELECT \"a\"#\"b\"").size(), 0, "Between tokens"); + UNIT_ASSERT_VALUES_EQUAL_C(Complete(engine, "SELECT `a`#`b`"), empty, "Solid ID_QUOTED"); + UNIT_ASSERT_VALUES_EQUAL_C(Complete(engine, "SELECT `a#\\`b`"), empty, "Solid ID_QUOTED"); + UNIT_ASSERT_VALUES_EQUAL_C(Complete(engine, "SELECT `a\\#`b`"), empty, "Solid ID_QUOTED"); + UNIT_ASSERT_VALUES_EQUAL_C(Complete(engine, "SELECT `a\\`#b`"), empty, "Solid ID_QUOTED"); +} + +Y_UNIT_TEST(SemiEnclosed) { + TVector<TCandidate> expected = {}; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT \""), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `"), expected); +} + +Y_UNIT_TEST(UTF8Wide) { + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "\xF0\x9F\x98\x8A").size(), 0); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "编码").size(), 0); +} + +Y_UNIT_TEST(WordBreak) { + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_GE(Complete(engine, "SELECT (").size(), 29); + UNIT_ASSERT_GE(Complete(engine, "SELECT (1)").size(), 30); + UNIT_ASSERT_GE(Complete(engine, "SELECT 1;").size(), 35); +} + +Y_UNIT_TEST(Bindings) { + auto engine = MakeSqlCompletionEngineUT(); + + TString query = R"( $=0; $a=0; $abac=0; SELECT )"; - { - TVector<TCandidate> expected = { - {BindingName, "$a"}, - {BindingName, "$abac"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } - { - TVector<TCandidate> expected = { - {BindingName, "$abac"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query + "ab"), expected); - } - { - TVector<TCandidate> expected = { - {BindingName, "$a"}, - {BindingName, "$abac"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, query + "$"), expected); - } - { - TVector<TCandidate> expected = { - {BindingName, "$abac"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, query + "$ab"), expected); - } - } - - Y_UNIT_TEST(BindingEditRange) { - auto engine = MakeSqlCompletionEngineUT(); - { - TString query = R"sql( + { + TVector<TCandidate> expected = { + {BindingName, "$a"}, + {BindingName, "$abac"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); + } + { + TVector<TCandidate> expected = { + {BindingName, "$abac"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query + "ab"), expected); + } + { + TVector<TCandidate> expected = { + {BindingName, "$a"}, + {BindingName, "$abac"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, query + "$"), expected); + } + { + TVector<TCandidate> expected = { + {BindingName, "$abac"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, query + "$ab"), expected); + } +} + +Y_UNIT_TEST(BindingEditRange) { + auto engine = MakeSqlCompletionEngineUT(); + { + TString query = R"sql( $abacaba=0; SELECT # )sql"; - TCompletion c = engine->Complete(SharpedInput(query)).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(c.CompletedToken.Content, ""); - } - { - TString query = R"sql( + TCompletion c = engine->Complete(SharpedInput(query)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(c.CompletedToken.Content, ""); + } + { + TString query = R"sql( $abacaba=0; SELECT $# )sql"; - TCompletion c = engine->Complete(SharpedInput(query)).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(c.CompletedToken.Content, "$"); - } - { - TString query = R"sql( + TCompletion c = engine->Complete(SharpedInput(query)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(c.CompletedToken.Content, "$"); + } + { + TString query = R"sql( $abacaba=0; SELECT $aba# )sql"; - TCompletion c = engine->Complete(SharpedInput(query)).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(c.CompletedToken.Content, "$aba"); - } - } - - Y_UNIT_TEST(TableFunction) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {FunctionName, "CONCAT()", 1}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT * FROM Conca#"), expected); - } - { - TVector<TCandidate> expected = {}; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT Conca#"), expected); - } - } - - Y_UNIT_TEST(TableAsFunctionArgument) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {FolderName, "`.sys/`", 1}, - {FolderName, "`local/`", 1}, - {FolderName, "`prod/`", 1}, - {FolderName, "`test/`", 1}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(4, engine, "SELECT * FROM CONCAT(#)"), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(4, engine, "SELECT * FROM CONCAT(a, #)"), expected); - } - { - TVector<TCandidate> expected = { - {TableName, "`people`"}, - {FolderName, "`yql/`", 1}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "USE example; SELECT * FROM Concat(#)"), expected); - } - { - UNIT_ASSERT_VALUES_EQUAL( - CompleteTop(1, engine, "SELECT * FROM Concat(`#`)").at(0).Kind, FolderName); - } - { - UNIT_ASSERT_VALUES_EQUAL( - CompleteTop(1, engine, "SELECT * FROM Range(#)").at(0).Kind, FolderName); - UNIT_ASSERT_VALUES_EQUAL( - CompleteTop(1, engine, "SELECT * FROM Range(``, #)").at(0).Kind, FolderName); - } - { - TVector<TCandidate> expected = { - {TableName, "example"}, - }; - UNIT_ASSERT_VALUES_EQUAL( - CompleteTop(10, engine, "SELECT * FROM Range(`test/service`, `#`)"), expected); - UNIT_ASSERT_VALUES_EQUAL( - CompleteTop(10, engine, "SELECT * FROM Range(`test/service`, ``, `#`)"), expected); - } - { - UNIT_ASSERT_VALUES_UNEQUAL(CompleteTop(1, engine, "SELECT Max(#)").at(0).Kind, FolderName); - UNIT_ASSERT_VALUES_UNEQUAL(CompleteTop(1, engine, "SELECT Concat(#)").at(0).Kind, FolderName); - } - } - - Y_UNIT_TEST(TableFunctionCluster) { - auto engine = MakeSqlCompletionEngineUT(); + TCompletion c = engine->Complete(SharpedInput(query)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(c.CompletedToken.Content, "$aba"); + } +} + +Y_UNIT_TEST(TableFunction) { + auto engine = MakeSqlCompletionEngineUT(); + { + TVector<TCandidate> expected = { + {FunctionName, "CONCAT()", 1}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT * FROM Conca#"), expected); + } + { + TVector<TCandidate> expected = {}; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT Conca#"), expected); + } +} + +Y_UNIT_TEST(TableAsFunctionArgument) { + auto engine = MakeSqlCompletionEngineUT(); + { + TVector<TCandidate> expected = { + {FolderName, "`.sys/`", 1}, + {FolderName, "`local/`", 1}, + {FolderName, "`prod/`", 1}, + {FolderName, "`test/`", 1}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(4, engine, "SELECT * FROM CONCAT(#)"), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(4, engine, "SELECT * FROM CONCAT(a, #)"), expected); + } + { TVector<TCandidate> expected = { {TableName, "`people`"}, {FolderName, "`yql/`", 1}, }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT * FROM example.Concat(#)"), expected); - } - - Y_UNIT_TEST(ColumnsAtSimpleSelect) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT # FROM example.`/people`"), expected); - } - { - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {Keyword, "ALL"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT a# FROM example.`/people`"), expected); - } - { - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "USE example; SELECT # FROM `/people`"), expected); - } - { - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - {ColumnName, "x.Age"}, - {ColumnName, "x.Name"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, "SELECT # FROM example.`/people` AS x"), expected); - } - { - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, "SELECT x.# FROM example.`/people` AS x"), expected); - } - { - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT x.a# FROM example.`/people` AS x"), expected); - } - { - TVector<TCandidate> expected = {}; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT y.a# FROM example.`/people` AS x"), expected); - } - } - - Y_UNIT_TEST(ColumnsAtJoin) { - auto engine = MakeSqlCompletionEngineUT(); - { - TString query = R"( + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "USE example; SELECT * FROM Concat(#)"), expected); + } + { + UNIT_ASSERT_VALUES_EQUAL( + CompleteTop(1, engine, "SELECT * FROM Concat(`#`)").at(0).Kind, FolderName); + } + { + UNIT_ASSERT_VALUES_EQUAL( + CompleteTop(1, engine, "SELECT * FROM Range(#)").at(0).Kind, FolderName); + UNIT_ASSERT_VALUES_EQUAL( + CompleteTop(1, engine, "SELECT * FROM Range(``, #)").at(0).Kind, FolderName); + } + { + TVector<TCandidate> expected = { + {TableName, "example"}, + }; + UNIT_ASSERT_VALUES_EQUAL( + CompleteTop(10, engine, "SELECT * FROM Range(`test/service`, `#`)"), expected); + UNIT_ASSERT_VALUES_EQUAL( + CompleteTop(10, engine, "SELECT * FROM Range(`test/service`, ``, `#`)"), expected); + } + { + UNIT_ASSERT_VALUES_UNEQUAL(CompleteTop(1, engine, "SELECT Max(#)").at(0).Kind, FolderName); + UNIT_ASSERT_VALUES_UNEQUAL(CompleteTop(1, engine, "SELECT Concat(#)").at(0).Kind, FolderName); + } +} + +Y_UNIT_TEST(TableFunctionCluster) { + auto engine = MakeSqlCompletionEngineUT(); + TVector<TCandidate> expected = { + {TableName, "`people`"}, + {FolderName, "`yql/`", 1}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT * FROM example.Concat(#)"), expected); +} + +Y_UNIT_TEST(ColumnsAtSimpleSelect) { + auto engine = MakeSqlCompletionEngineUT(); + { + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT # FROM example.`/people`"), expected); + } + { + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {Keyword, "ALL"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT a# FROM example.`/people`"), expected); + } + { + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "USE example; SELECT # FROM `/people`"), expected); + } + { + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + {ColumnName, "x.Age"}, + {ColumnName, "x.Name"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, "SELECT # FROM example.`/people` AS x"), expected); + } + { + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, "SELECT x.# FROM example.`/people` AS x"), expected); + } + { + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT x.a# FROM example.`/people` AS x"), expected); + } + { + TVector<TCandidate> expected = {}; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT y.a# FROM example.`/people` AS x"), expected); + } +} + +Y_UNIT_TEST(ColumnsAtJoin) { + auto engine = MakeSqlCompletionEngineUT(); + { + TString query = R"( SELECT # FROM example.`/people` AS ep JOIN example.`/yql/tutorial` AS et ON 1 = 1 )"; - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - {ColumnName, "course"}, - {ColumnName, "room"}, - {ColumnName, "time"}, - {ColumnName, "ep.Age"}, - {ColumnName, "ep.Name"}, - {ColumnName, "et.course"}, - {ColumnName, "et.room"}, - {ColumnName, "et.time"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } - } - - Y_UNIT_TEST(ColumnsAtSubquery) { - auto engine = MakeSqlCompletionEngineUT(); - { - TString query = R"( + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + {ColumnName, "course"}, + {ColumnName, "room"}, + {ColumnName, "time"}, + {ColumnName, "ep.Age"}, + {ColumnName, "ep.Name"}, + {ColumnName, "et.course"}, + {ColumnName, "et.room"}, + {ColumnName, "et.time"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); + } +} + +Y_UNIT_TEST(ColumnsAtSubquery) { + auto engine = MakeSqlCompletionEngineUT(); + { + TString query = R"( SELECT # FROM (SELECT * FROM example.`/people`) AS ep JOIN (SELECT room AS Room, time FROM example.`/yql/tutorial`) AS et ON 1 = 1 )"; - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - {ColumnName, "Room"}, - {ColumnName, "time"}, - {ColumnName, "ep.Age"}, - {ColumnName, "ep.Name"}, - {ColumnName, "et.Room"}, - {ColumnName, "et.time"}, - {Keyword, "ALL"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } - { - TString query = R"( + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + {ColumnName, "Room"}, + {ColumnName, "time"}, + {ColumnName, "ep.Age"}, + {ColumnName, "ep.Name"}, + {ColumnName, "et.Room"}, + {ColumnName, "et.time"}, + {Keyword, "ALL"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); + } + { + TString query = R"( SELECT # FROM example.`/yql/tutorial` AS x JOIN example.`/yql/tutorial` AS y ON 1 = 1 )"; - TVector<TCandidate> expected = { - {ColumnName, "x.course"}, - {ColumnName, "x.room"}, - {ColumnName, "x.time"}, - {ColumnName, "y.course"}, - {ColumnName, "y.room"}, - {ColumnName, "y.time"}, - {Keyword, "ALL"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } - { - TString query = "SELECT # FROM (SELECT 1 AS x)"; - - TVector<TCandidate> expected = { - {ColumnName, "x"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query), expected); - } - { - TString query = R"( + TVector<TCandidate> expected = { + {ColumnName, "x.course"}, + {ColumnName, "x.room"}, + {ColumnName, "x.time"}, + {ColumnName, "y.course"}, + {ColumnName, "y.room"}, + {ColumnName, "y.time"}, + {Keyword, "ALL"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); + } + { + TString query = "SELECT # FROM (SELECT 1 AS x)"; + + TVector<TCandidate> expected = { + {ColumnName, "x"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query), expected); + } + { + TString query = R"( SELECT # FROM ( SELECT epp.*, test @@ -1379,19 +1379,19 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { ) AS ep )"; - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - {ColumnName, "test"}, - {ColumnName, "ep.Age"}, - {ColumnName, "ep.Name"}, - {ColumnName, "ep.test"}, - {Keyword, "ALL"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } - { - TString query = R"( + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + {ColumnName, "test"}, + {ColumnName, "ep.Age"}, + {ColumnName, "ep.Name"}, + {ColumnName, "ep.test"}, + {Keyword, "ALL"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); + } + { + TString query = R"( SELECT # FROM ( SELECT * WITHOUT Age, eqt.course @@ -1404,403 +1404,403 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { JOIN example.`/people` AS x ON TRUE )"; - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "room"}, - {ColumnName, "time"}, - {ColumnName, "ep.Name"}, - {ColumnName, "ep.room"}, - {ColumnName, "ep.time"}, - {ColumnName, "x.Age"}, - {ColumnName, "x.Name"}, - {Keyword, "ALL"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } - } - - Y_UNIT_TEST(ColumnsFromNamedExpr) { - auto engine = MakeSqlCompletionEngineUT(); - { - TVector<TString> queries = { - R"sql(SELECT # FROM $)sql", - R"sql(SELECT # FROM $$)sql", - R"sql(SELECT # FROM $x)sql", - }; - - TVector<TCandidate> expected = { - {Keyword, "ALL"}, - }; - - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, queries[0]), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, queries[1]), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, queries[2]), expected); - } - { - TString declare = R"sql(DECLARE $x AS String;)sql"; - - TVector<TString> queries = { - declare + R"sql(SELECT # FROM example.$x)sql", - declare + R"sql(USE example; SELECT # FROM $x)sql", - }; - - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - {BindingName, "$x"}, - }; - - TEnvironment env = { - .Parameters = {{"$x", "/people"}}, - }; - - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, queries[0], env), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, queries[1], env), expected); - } - { - TString query = R"sql( - USE example; - SELECT # FROM $x; - )sql"; + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "room"}, + {ColumnName, "time"}, + {ColumnName, "ep.Name"}, + {ColumnName, "ep.room"}, + {ColumnName, "ep.time"}, + {ColumnName, "x.Age"}, + {ColumnName, "x.Name"}, + {Keyword, "ALL"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); + } +} - TEnvironment env = { - .Parameters = {{"$x", "/people"}}, - }; +Y_UNIT_TEST(ColumnsFromNamedExpr) { + auto engine = MakeSqlCompletionEngineUT(); + { + TVector<TString> queries = { + R"sql(SELECT # FROM $)sql", + R"sql(SELECT # FROM $$)sql", + R"sql(SELECT # FROM $x)sql", + }; - TVector<TCandidate> expected = { - {Keyword, "ALL"}, - }; + TVector<TCandidate> expected = { + {Keyword, "ALL"}, + }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query, {}), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query, env), expected); - } + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, queries[0]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, queries[1]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, queries[2]), expected); } + { + TString declare = R"sql(DECLARE $x AS String;)sql"; - Y_UNIT_TEST(ColumnFromTableFunction) { - auto engine = MakeSqlCompletionEngineUT(); - - TVector<TString> input = { - R"sql(SELECT # FROM loggy.CONCAT(`yql/2025-01`))sql", - R"sql(SELECT # FROM loggy.CONCAT(`yql/2025-01`, `yql/2025-02`))sql", - R"sql(SELECT # FROM loggy.RANGE(`yql`, `2025-01`, `2025-03`))sql", + TVector<TString> queries = { + declare + R"sql(SELECT # FROM example.$x)sql", + declare + R"sql(USE example; SELECT # FROM $x)sql", }; TVector<TCandidate> expected = { - {ColumnName, "message"}, - {ColumnName, "timestamp"}, + {ColumnName, "Age"}, + {ColumnName, "Name"}, + {BindingName, "$x"}, + }; + + TEnvironment env = { + .Parameters = {{"$x", "/people"}}, }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, input[0]), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, input[1]), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, input[2]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, queries[0], env), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, queries[1], env), expected); } + { + TString query = R"sql( + USE example; + SELECT # FROM $x; + )sql"; - Y_UNIT_TEST(ColumnPositions) { - auto engine = MakeSqlCompletionEngineUT(); + TEnvironment env = { + .Parameters = {{"$x", "/people"}}, + }; TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, + {Keyword, "ALL"}, }; - { - TString query = "SELECT # FROM example.`/people`"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } - { - TString query = "SELECT f(#) FROM example.`/people`"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } - { - TString query = "SELECT * FROM example.`/people` WHERE #"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } - { - TString query = "SELECT * FROM example.`/people` WHERE a#"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query).at(0).Content, "Age"); - } - { - TString query = "SELECT * FROM example.`/people` WHERE f(#)"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } - { - TString query = "SELECT * FROM example.`/people` ORDER BY #"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } - { - TString query = "SELECT * FROM example.`/people` ORDER BY a#"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query).at(0).Content, "Age"); - } - { - TString query = "SELECT * FROM example.`/people` ORDER BY f(#)"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } - { - TString query = "SELECT * FROM example.`/people` GROUP BY #"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } - { - TString query = "SELECT * FROM example.`/people` GROUP BY a#"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query).at(0).Content, "Age"); - } - { - TString query = R"( + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query, {}), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query, env), expected); + } +} + +Y_UNIT_TEST(ColumnFromTableFunction) { + auto engine = MakeSqlCompletionEngineUT(); + + TVector<TString> input = { + R"sql(SELECT # FROM loggy.CONCAT(`yql/2025-01`))sql", + R"sql(SELECT # FROM loggy.CONCAT(`yql/2025-01`, `yql/2025-02`))sql", + R"sql(SELECT # FROM loggy.RANGE(`yql`, `2025-01`, `2025-03`))sql", + }; + + TVector<TCandidate> expected = { + {ColumnName, "message"}, + {ColumnName, "timestamp"}, + }; + + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, input[0]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, input[1]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, input[2]), expected); +} + +Y_UNIT_TEST(ColumnPositions) { + auto engine = MakeSqlCompletionEngineUT(); + + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + }; + + { + TString query = "SELECT # FROM example.`/people`"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); + } + { + TString query = "SELECT f(#) FROM example.`/people`"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); + } + { + TString query = "SELECT * FROM example.`/people` WHERE #"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); + } + { + TString query = "SELECT * FROM example.`/people` WHERE a#"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query).at(0).Content, "Age"); + } + { + TString query = "SELECT * FROM example.`/people` WHERE f(#)"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); + } + { + TString query = "SELECT * FROM example.`/people` ORDER BY #"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); + } + { + TString query = "SELECT * FROM example.`/people` ORDER BY a#"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query).at(0).Content, "Age"); + } + { + TString query = "SELECT * FROM example.`/people` ORDER BY f(#)"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); + } + { + TString query = "SELECT * FROM example.`/people` GROUP BY #"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); + } + { + TString query = "SELECT * FROM example.`/people` GROUP BY a#"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, query).at(0).Content, "Age"); + } + { + TString query = R"( SELECT * FROM example.`/people` AS a JOIN example.`/people` AS b ON a.# )"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); } +} - Y_UNIT_TEST(ColumnFiltration) { - auto engine = MakeSqlCompletionEngineUT(); +Y_UNIT_TEST(ColumnFiltration) { + auto engine = MakeSqlCompletionEngineUT(); - TString query = R"sql( + TString query = R"sql( SELECT roo# FROM example.`/people` AS roommate JOIN example.`/yql/tutorial` AS query ON 1 = 1; )sql"; - TVector<TCandidate> expected = { - {ColumnName, "room"}, - {ColumnName, "query.room"}, - {ColumnName, "roommate.Age"}, - {ColumnName, "roommate.Name"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } + TVector<TCandidate> expected = { + {ColumnName, "room"}, + {ColumnName, "query.room"}, + {ColumnName, "roommate.Age"}, + {ColumnName, "roommate.Name"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); +} + +Y_UNIT_TEST(QualifiedColumnAtWhere) { + auto engine = MakeSqlCompletionEngineUT(); + + TString prefix = R"sql(SELECT * FROM example.`/people` AS x )sql"; + + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + }; + + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, prefix + "WHERE x.#"), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, prefix + "GROUP BY x.#"), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, prefix + "HAVING x.#"), expected); +} + +Y_UNIT_TEST(ColumnFromQualifiedAtWhere) { + auto engine = MakeSqlCompletionEngineUT(); + + TString prefix = R"sql(SELECT * FROM example.`/people` AS x )sql"; + + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + {ColumnName, "x.Age"}, + {ColumnName, "x.Name"}, + }; - Y_UNIT_TEST(QualifiedColumnAtWhere) { - auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, prefix + "WHERE #"), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, prefix + "GROUP BY #"), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, prefix + "HAVING #"), expected); +} - TString prefix = R"sql(SELECT * FROM example.`/people` AS x )sql"; +Y_UNIT_TEST(ColumnFromQuotedAlias) { + auto engine = MakeSqlCompletionEngineUT(); + { + TString query; TVector<TCandidate> expected = { {ColumnName, "Age"}, {ColumnName, "Name"}, + {ColumnName, "`per son`.Age"}, + {ColumnName, "`per son`.Name"}, }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, prefix + "WHERE x.#"), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, prefix + "GROUP BY x.#"), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, prefix + "HAVING x.#"), expected); + query = R"sql(SELECT # FROM example.`/people` AS `per son`)sql"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); } + { + TString query = R"sql(SELECT per# FROM example.`/people` AS `per son`)sql"; - Y_UNIT_TEST(ColumnFromQualifiedAtWhere) { - auto engine = MakeSqlCompletionEngineUT(); + TVector<TCandidate> expected = { + {ColumnName, "`per son`.Age"}, + {ColumnName, "`per son`.Name"}, + }; - TString prefix = R"sql(SELECT * FROM example.`/people` AS x )sql"; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); + } + { + TString query = R"sql(SELECT `per son`.# FROM example.`/people` AS `per son`)sql"; TVector<TCandidate> expected = { {ColumnName, "Age"}, {ColumnName, "Name"}, - {ColumnName, "x.Age"}, - {ColumnName, "x.Name"}, }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, prefix + "WHERE #"), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, prefix + "GROUP BY #"), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, prefix + "HAVING #"), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); } +} - Y_UNIT_TEST(ColumnFromQuotedAlias) { - auto engine = MakeSqlCompletionEngineUT(); - { - TString query; - - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - {ColumnName, "`per son`.Age"}, - {ColumnName, "`per son`.Name"}, - }; - - query = R"sql(SELECT # FROM example.`/people` AS `per son`)sql"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } - { - TString query = R"sql(SELECT per# FROM example.`/people` AS `per son`)sql"; - - TVector<TCandidate> expected = { - {ColumnName, "`per son`.Age"}, - {ColumnName, "`per son`.Name"}, - }; +Y_UNIT_TEST(ProjectionVisibility) { + auto engine = MakeSqlCompletionEngineUT(); + { + TString query = "SELECT Age as a, # FROM example.`/people`"; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } - { - TString query = R"sql(SELECT `per son`.# FROM example.`/people` AS `per son`)sql"; - - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - }; + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); } + { + TString query = "SELECT Age as a, b FROM example.`/people` ORDER BY #"; - Y_UNIT_TEST(ProjectionVisibility) { - auto engine = MakeSqlCompletionEngineUT(); - { - TString query = "SELECT Age as a, # FROM example.`/people`"; - - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - }; - - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } - { - TString query = "SELECT Age as a, b FROM example.`/people` ORDER BY #"; - - TVector<TCandidate> expected = { - {ColumnName, "a"}, - {ColumnName, "b"}, - }; + TVector<TCandidate> expected = { + {ColumnName, "a"}, + {ColumnName, "b"}, + }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); - } + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, query), expected); } +} - Y_UNIT_TEST(ColumnFromNamedNode) { - auto engine = MakeSqlCompletionEngineUT(); +Y_UNIT_TEST(ColumnFromNamedNode) { + auto engine = MakeSqlCompletionEngineUT(); - TString prefix = R"sql( + TString prefix = R"sql( USE example; $source = '/peo' || 'ple'; )sql"; - TVector<TString> input = { - prefix + R"sql(SELECT # FROM $source)sql", - prefix + R"sql(SELECT * FROM $source WHERE #)sql", - prefix + R"sql(SELECT * FROM $source GROUP BY #)sql", - prefix + R"sql(SELECT * FROM $source AS x FROM x.#)sql", - }; + TVector<TString> input = { + prefix + R"sql(SELECT # FROM $source)sql", + prefix + R"sql(SELECT * FROM $source WHERE #)sql", + prefix + R"sql(SELECT * FROM $source GROUP BY #)sql", + prefix + R"sql(SELECT * FROM $source AS x FROM x.#)sql", + }; - TVector<TCandidate> expected = { - {ColumnName, "Age"}, - {ColumnName, "Name"}, - {BindingName, "$source"}, - }; + TVector<TCandidate> expected = { + {ColumnName, "Age"}, + {ColumnName, "Name"}, + {BindingName, "$source"}, + }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, input[0]), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, input[1]), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, input[2]), expected); - } + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, input[0]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, input[1]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(3, engine, input[2]), expected); +} - Y_UNIT_TEST(ColumnFromIndirectNamedNode) { - auto engine = MakeSqlCompletionEngineUT(); +Y_UNIT_TEST(ColumnFromIndirectNamedNode) { + auto engine = MakeSqlCompletionEngineUT(); - TString query = R"sql( + TString query = R"sql( $x = (SELECT 1 AS a); $y = $x; SELECT # FROM $y; )sql"; - TVector<TCandidate> expected = { - {ColumnName, "a"}, - }; + TVector<TCandidate> expected = { + {ColumnName, "a"}, + }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); +} - Y_UNIT_TEST(ColumnQuoted) { - auto engine = MakeSqlCompletionEngineUT(); +Y_UNIT_TEST(ColumnQuoted) { + auto engine = MakeSqlCompletionEngineUT(); - TVector<TCandidate> expected = { - {ColumnName, "`Y Q L`"}, - {ColumnName, "`o````o`"}, - }; + TVector<TCandidate> expected = { + {ColumnName, "`Y Q L`"}, + {ColumnName, "`o````o`"}, + }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT # FROM saurus.maxim"), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT Y# FROM saurus.maxim").at(0), expected.at(0)); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `# FROM saurus.maxim").size(), 0); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `#` FROM saurus.maxim").size(), 0); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `Y #` FROM saurus.maxim").size(), 0); - } + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT # FROM saurus.maxim"), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT Y# FROM saurus.maxim").at(0), expected.at(0)); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `# FROM saurus.maxim").size(), 0); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `#` FROM saurus.maxim").size(), 0); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT `Y #` FROM saurus.maxim").size(), 0); +} - Y_UNIT_TEST(ColumnReplicationConflict) { - auto engine = MakeSqlCompletionEngineUT(); +Y_UNIT_TEST(ColumnReplicationConflict) { + auto engine = MakeSqlCompletionEngineUT(); - TString query = R"sql( + TString query = R"sql( SELECT # FROM (SELECT a, b) AS x JOIN (SELECT a, b) AS y )sql"; - TVector<TCandidate> expected = { - {ColumnName, "x.a"}, - {ColumnName, "x.b"}, - {ColumnName, "y.a"}, - {ColumnName, "y.b"}, - }; + TVector<TCandidate> expected = { + {ColumnName, "x.a"}, + {ColumnName, "x.b"}, + {ColumnName, "y.a"}, + {ColumnName, "y.b"}, + }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); +} - Y_UNIT_TEST(ColumnReplication) { - auto engine = MakeSqlCompletionEngineUT(); +Y_UNIT_TEST(ColumnReplication) { + auto engine = MakeSqlCompletionEngineUT(); - TString query = R"sql( + TString query = R"sql( SELECT # FROM (SELECT a, b) AS x JOIN (SELECT b, c) AS y )sql"; - TVector<TCandidate> expected = { - {ColumnName, "a"}, - {ColumnName, "c"}, - {ColumnName, "x.a"}, - {ColumnName, "x.b"}, - {ColumnName, "y.b"}, - {ColumnName, "y.c"}, - }; + TVector<TCandidate> expected = { + {ColumnName, "a"}, + {ColumnName, "c"}, + {ColumnName, "x.a"}, + {ColumnName, "x.b"}, + {ColumnName, "y.b"}, + {ColumnName, "y.c"}, + }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); +} - Y_UNIT_TEST(ColumnReplicationCaseSensivity) { - auto engine = MakeSqlCompletionEngineUT(); +Y_UNIT_TEST(ColumnReplicationCaseSensivity) { + auto engine = MakeSqlCompletionEngineUT(); - TString query = R"sql( + TString query = R"sql( SELECT # FROM (SELECT A, B) AS x JOIN (SELECT a, b) AS y )sql"; - TVector<TCandidate> expected = { - {ColumnName, "A"}, - {ColumnName, "B"}, - {ColumnName, "a"}, - {ColumnName, "b"}, - }; + TVector<TCandidate> expected = { + {ColumnName, "A"}, + {ColumnName, "B"}, + {ColumnName, "a"}, + {ColumnName, "b"}, + }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); +} - Y_UNIT_TEST(ColumnReplicationFiltration) { - auto engine = MakeSqlCompletionEngineUT(); +Y_UNIT_TEST(ColumnReplicationFiltration) { + auto engine = MakeSqlCompletionEngineUT(); - TVector<TString> queries = { - R"sql(SELECT x# FROM (SELECT XXX) AS xxx)sql", - R"sql(SELECT X# FROM (SELECT XXX) AS xxx)sql", - }; + TVector<TString> queries = { + R"sql(SELECT x# FROM (SELECT XXX) AS xxx)sql", + R"sql(SELECT X# FROM (SELECT XXX) AS xxx)sql", + }; - TVector<TCandidate> expected = { - {ColumnName, "XXX"}, - {ColumnName, "xxx.XXX"}, - }; + TVector<TCandidate> expected = { + {ColumnName, "XXX"}, + {ColumnName, "xxx.XXX"}, + }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, queries[0]), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, queries[1]), expected); - } + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, queries[0]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, queries[1]), expected); +} - Y_UNIT_TEST(ColumnAtWhereInSubquery) { - auto engine = MakeSqlCompletionEngineUT(); +Y_UNIT_TEST(ColumnAtWhereInSubquery) { + auto engine = MakeSqlCompletionEngineUT(); - TString query = R"sql( + TString query = R"sql( SELECT * FROM ( SELECT a AS b FROM (SELECT 1 AS a) AS x @@ -1808,65 +1808,65 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { ); )sql"; - TVector<TCandidate> expected = { - {ColumnName, "a"}, - }; - - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); - } - - Y_UNIT_TEST(ColumnAtSubqueryExpresson) { - auto engine = MakeSqlCompletionEngineUT(); - - TVector<TString> input = { - R"sql(SELECT (SELECT # FROM (SELECT 1 AS a));)sql", - R"sql(SELECT 1 + (SELECT # FROM (SELECT 1 AS a));)sql", - R"sql(SELECT * FROM t WHERE (SELECT # FROM (SELECT 1 AS a));)sql", - R"sql(SELECT * FROM t WHERE 1 < (SELECT # FROM (SELECT 1 AS a));)sql", - }; - - TVector<TCandidate> expected = { - {ColumnName, "a"}, - }; - - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[0]), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[1]), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[2]), expected); - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[3]), expected); - } - - Y_UNIT_TEST(NoBindingAtQuoted) { - auto engine = MakeSqlCompletionEngineUT(); - - TVector<TCandidate> expected = { - {FolderName, ".sys/"}, - {FolderName, "local/"}, - {FolderName, "prod/"}, - {FolderName, "test/"}, - }; - - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "$x = 1; SELECT * FROM `#`"), expected); - } - - Y_UNIT_TEST(Typing) { - const auto queryUtf16 = TUtf16String::FromUtf8( - "SELECT \n" - " 123467, \"Hello, {name}! 编码\"}, \n" - " (1 + (5 * 1 / 0)), MIN(identifier), \n" - " Bool(field), Math::Sin(var) \n" - "FROM `local/test/space/table` JOIN test;"); - - auto engine = MakeSqlCompletionEngineUT(); - - for (std::size_t size = 0; size <= queryUtf16.size(); ++size) { - const TWtringBuf prefixUtf16(queryUtf16, 0, size); - TCompletion completion = engine->Complete({TString::FromUtf16(prefixUtf16)}).GetValueSync(); - Y_DO_NOT_OPTIMIZE_AWAY(completion); - } - } - - Y_UNIT_TEST(Tabbing) { - TString query = R"( + TVector<TCandidate> expected = { + {ColumnName, "a"}, + }; + + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); +} + +Y_UNIT_TEST(ColumnAtSubqueryExpresson) { + auto engine = MakeSqlCompletionEngineUT(); + + TVector<TString> input = { + R"sql(SELECT (SELECT # FROM (SELECT 1 AS a));)sql", + R"sql(SELECT 1 + (SELECT # FROM (SELECT 1 AS a));)sql", + R"sql(SELECT * FROM t WHERE (SELECT # FROM (SELECT 1 AS a));)sql", + R"sql(SELECT * FROM t WHERE 1 < (SELECT # FROM (SELECT 1 AS a));)sql", + }; + + TVector<TCandidate> expected = { + {ColumnName, "a"}, + }; + + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[0]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[1]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[2]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[3]), expected); +} + +Y_UNIT_TEST(NoBindingAtQuoted) { + auto engine = MakeSqlCompletionEngineUT(); + + TVector<TCandidate> expected = { + {FolderName, ".sys/"}, + {FolderName, "local/"}, + {FolderName, "prod/"}, + {FolderName, "test/"}, + }; + + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "$x = 1; SELECT * FROM `#`"), expected); +} + +Y_UNIT_TEST(Typing) { + const auto queryUtf16 = TUtf16String::FromUtf8( + "SELECT \n" + " 123467, \"Hello, {name}! 编码\"}, \n" + " (1 + (5 * 1 / 0)), MIN(identifier), \n" + " Bool(field), Math::Sin(var) \n" + "FROM `local/test/space/table` JOIN test;"); + + auto engine = MakeSqlCompletionEngineUT(); + + for (std::size_t size = 0; size <= queryUtf16.size(); ++size) { + const TWtringBuf prefixUtf16(queryUtf16, 0, size); + TCompletion completion = engine->Complete({TString::FromUtf16(prefixUtf16)}).GetValueSync(); + Y_DO_NOT_OPTIMIZE_AWAY(completion); + } +} + +Y_UNIT_TEST(Tabbing) { + TString query = R"( USE example; SELECT @@ -1877,289 +1877,289 @@ FROM `local/test/space/table` JOIN yt:$cluster_name.test; )"; - query += query + ";"; - query += query + ";"; + query += query + ";"; + query += query + ";"; - auto engine = MakeSqlCompletionEngineUT(); + auto engine = MakeSqlCompletionEngineUT(); - const auto* begin = reinterpret_cast<const unsigned char*>(query.c_str()); - const auto* end = reinterpret_cast<const unsigned char*>(begin + query.size()); - const auto* ptr = begin; + const auto* begin = reinterpret_cast<const unsigned char*>(query.c_str()); + const auto* end = reinterpret_cast<const unsigned char*>(begin + query.size()); + const auto* ptr = begin; - wchar32 rune; - while (ptr < end) { - Y_ENSURE(ReadUTF8CharAndAdvance(rune, ptr, end) == RECODE_OK); - TCompletionInput input = { - .Text = query, - .CursorPosition = static_cast<size_t>(std::distance(begin, ptr)), - }; - TCompletion completion = engine->Complete(input).GetValueSync(); - Y_DO_NOT_OPTIMIZE_AWAY(completion); - } + wchar32 rune; + while (ptr < end) { + Y_ENSURE(ReadUTF8CharAndAdvance(rune, ptr, end) == RECODE_OK); + TCompletionInput input = { + .Text = query, + .CursorPosition = static_cast<size_t>(std::distance(begin, ptr)), + }; + TCompletion completion = engine->Complete(input).GetValueSync(); + Y_DO_NOT_OPTIMIZE_AWAY(completion); + } +} + +Y_UNIT_TEST(CaseInsensitivity) { + TVector<TCandidate> expected = { + {Keyword, "SELECT"}, + }; + + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "se"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "sE"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "Se"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SE"), expected); +} + +Y_UNIT_TEST(InvalidStatementsRecovery) { + auto engine = MakeSqlCompletionEngineUT(); + UNIT_ASSERT_GE(Complete(engine, "select select; ").size(), 35); + UNIT_ASSERT_GE(Complete(engine, "select select;").size(), 35); + UNIT_ASSERT_GE(Complete(engine, "#;select select;").size(), 35); + UNIT_ASSERT_GE(Complete(engine, "# ;select select;").size(), 35); + UNIT_ASSERT_GE(Complete(engine, ";#;").size(), 35); + UNIT_ASSERT_GE(Complete(engine, "#;;").size(), 35); + UNIT_ASSERT_GE(Complete(engine, ";;#").size(), 35); + UNIT_ASSERT_VALUES_EQUAL_C(Complete(engine, "!;").size(), 0, "Lexer failing"); +} + +Y_UNIT_TEST(InvalidCursorPosition) { + auto engine = MakeSqlCompletionEngineUT(); + + UNIT_ASSERT_NO_EXCEPTION(engine->Complete({"", 0}).GetValueSync()); + UNIT_ASSERT_EXCEPTION(engine->Complete({"", 1}).GetValueSync(), yexception); + + UNIT_ASSERT_NO_EXCEPTION(engine->Complete({"s", 0}).GetValueSync()); + UNIT_ASSERT_NO_EXCEPTION(engine->Complete({"s", 1}).GetValueSync()); + + UNIT_ASSERT_NO_EXCEPTION(engine->Complete({"ы", 0}).GetValueSync()); + UNIT_ASSERT_EXCEPTION(engine->Complete({"ы", 1}).GetValueSync(), yexception); + UNIT_ASSERT_NO_EXCEPTION(engine->Complete({"ы", 2}).GetValueSync()); +} + +Y_UNIT_TEST(DefaultNameService) { + auto service = MakeStaticNameService(LoadDefaultNameSet(), LoadFrequencyData()); + auto engine = MakeSqlCompletionEngine(MakePureLexerSupplier(), std::move(service)); + { + TVector<TCandidate> expected = { + {TypeName, "Uint64"}, + {TypeName, "Uint32"}, + {TypeName, "Utf8"}, + {TypeName, "Uuid"}, + {TypeName, "Uint8"}, + {TypeName, "Unit"}, + {TypeName, "Uint16"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Optional<U"), expected); } - - Y_UNIT_TEST(CaseInsensitivity) { + { TVector<TCandidate> expected = { - {Keyword, "SELECT"}, + {PragmaName, "yson.DisableStrict"}, + {PragmaName, "yson.AutoConvert"}, + {PragmaName, "yson.Strict"}, + {PragmaName, "yson.CastToString"}, + {PragmaName, "yson.DisableCastToString"}, }; - - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "se"), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "sE"), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "Se"), expected); - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SE"), expected); - } - - Y_UNIT_TEST(InvalidStatementsRecovery) { - auto engine = MakeSqlCompletionEngineUT(); - UNIT_ASSERT_GE(Complete(engine, "select select; ").size(), 35); - UNIT_ASSERT_GE(Complete(engine, "select select;").size(), 35); - UNIT_ASSERT_GE(Complete(engine, "#;select select;").size(), 35); - UNIT_ASSERT_GE(Complete(engine, "# ;select select;").size(), 35); - UNIT_ASSERT_GE(Complete(engine, ";#;").size(), 35); - UNIT_ASSERT_GE(Complete(engine, "#;;").size(), 35); - UNIT_ASSERT_GE(Complete(engine, ";;#").size(), 35); - UNIT_ASSERT_VALUES_EQUAL_C(Complete(engine, "!;").size(), 0, "Lexer failing"); - } - - Y_UNIT_TEST(InvalidCursorPosition) { - auto engine = MakeSqlCompletionEngineUT(); - - UNIT_ASSERT_NO_EXCEPTION(engine->Complete({"", 0}).GetValueSync()); - UNIT_ASSERT_EXCEPTION(engine->Complete({"", 1}).GetValueSync(), yexception); - - UNIT_ASSERT_NO_EXCEPTION(engine->Complete({"s", 0}).GetValueSync()); - UNIT_ASSERT_NO_EXCEPTION(engine->Complete({"s", 1}).GetValueSync()); - - UNIT_ASSERT_NO_EXCEPTION(engine->Complete({"ы", 0}).GetValueSync()); - UNIT_ASSERT_EXCEPTION(engine->Complete({"ы", 1}).GetValueSync(), yexception); - UNIT_ASSERT_NO_EXCEPTION(engine->Complete({"ы", 2}).GetValueSync()); - } - - Y_UNIT_TEST(DefaultNameService) { - auto service = MakeStaticNameService(LoadDefaultNameSet(), LoadFrequencyData()); - auto engine = MakeSqlCompletionEngine(MakePureLexerSupplier(), std::move(service)); - { - TVector<TCandidate> expected = { - {TypeName, "Uint64"}, - {TypeName, "Uint32"}, - {TypeName, "Utf8"}, - {TypeName, "Uuid"}, - {TypeName, "Uint8"}, - {TypeName, "Unit"}, - {TypeName, "Uint16"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Optional<U"), expected); - } - { - TVector<TCandidate> expected = { - {PragmaName, "yson.DisableStrict"}, - {PragmaName, "yson.AutoConvert"}, - {PragmaName, "yson.Strict"}, - {PragmaName, "yson.CastToString"}, - {PragmaName, "yson.DisableCastToString"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "PRAGMA yson"), expected); - } - { - TVector<TCandidate> expected = { - {HintName, "IGNORE_TYPE_V3"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "REDUCE a WITH ig"), expected); - } - } - - Y_UNIT_TEST(OnFailingNameService) { - auto service = MakeIntrusive<TFailingNameService>(); - auto engine = MakeSqlCompletionEngine(MakePureLexerSupplier(), std::move(service)); - UNIT_ASSERT_EXCEPTION(Complete(engine, ""), TDummyException); - UNIT_ASSERT_EXCEPTION(Complete(engine, "SELECT Optional<U"), TDummyException); - UNIT_ASSERT_EXCEPTION(Complete(engine, "SELECT CAST (1 AS ").size(), TDummyException); - } - - Y_UNIT_TEST(NameNormalization) { - auto service = MakeStaticNameService(LoadDefaultNameSet(), LoadFrequencyData()); - auto engine = MakeSqlCompletionEngine(MakePureLexerSupplier(), std::move(service)); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "PRAGMA yson"), expected); + } + { TVector<TCandidate> expected = { {HintName, "IGNORE_TYPE_V3"}, }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, {"REDUCE a WITH ignoret"}), expected); - } - - Y_UNIT_TEST(Ranking) { - TFrequencyData frequency = { - .Keywords = { - {"select", 2}, - {"insert", 4}, - }, - .Pragmas = { - {"yt.defaultmemorylimit", 16}, - {"yt.annotations", 8}, - }, - .Types = { - {"int32", 128}, - {"int64", 64}, - {"interval", 32}, - {"interval64", 32}, - }, - .Functions = { - {"min", 128}, - {"max", 64}, - {"maxof", 64}, - {"minby", 32}, - {"maxby", 32}, - }, - .Hints = { - {"xlock", 4}, - {"unordered", 2}, - }, - }; - auto service = MakeStaticNameService( - Pruned(LoadDefaultNameSet(), LoadFrequencyData()), - std::move(frequency)); - auto engine = MakeSqlCompletionEngine(MakePureLexerSupplier(), std::move(service)); - { - TVector<TCandidate> expected = { - {Keyword, "INSERT"}, - {Keyword, "SELECT"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, ""), expected); - } - { - TVector<TCandidate> expected = { - {PragmaName, "DefaultMemoryLimit"}, - {PragmaName, "Annotations"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, "PRAGMA yt."), expected); - } - { - TVector<TCandidate> expected = { - {TypeName, "Int32"}, - {TypeName, "Int64"}, - {TypeName, "Interval"}, - {TypeName, "Interval64"}, - {TypeName, "Int16"}, - {TypeName, "Int8"}, - }; - UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Optional<I"), expected); - } - { - TVector<TCandidate> expected = { - {FunctionName, "Min()", 1}, - {FunctionName, "Max()", 1}, - {FunctionName, "MaxOf()", 1}, - {FunctionName, "MaxBy()", 1}, - {FunctionName, "MinBy()", 1}, - {FunctionName, "Math::Abs()", 1}, - {FunctionName, "Math::Acos()", 1}, - {FunctionName, "Math::Asin()", 1}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, "SELECT m"), expected); - } - { - TVector<TCandidate> expected = { - {HintName, "XLOCK"}, - {HintName, "UNORDERED"}, - {Keyword, "COLUMNS"}, - {HintName, "FORCE_INFER_SCHEMA"}, - }; - UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, "SELECT * FROM a WITH "), expected); - } - } - - Y_UNIT_TEST(IgnoredRules) { - auto lexer = MakePureLexerSupplier(); - - TNameSet names; - TFrequencyData frequency; - auto service = MakeStaticNameService(names, MakeDefaultRanking(frequency)); - - { - auto engine = MakeSqlCompletionEngine(lexer, service); - UNIT_ASSERT_UNEQUAL(Complete(engine, {"UPDA"}).size(), 0); - UNIT_ASSERT_UNEQUAL(Complete(engine, {"DELE"}).size(), 0); - UNIT_ASSERT_UNEQUAL(Complete(engine, {"ROLL"}).size(), 0); - UNIT_ASSERT_UNEQUAL(Complete(engine, {"INSE"}).size(), 0); - UNIT_ASSERT_UNEQUAL(Complete(engine, {"SELE"}).size(), 0); - } - - auto config = MakeYQLConfiguration(); - auto engine = MakeSqlCompletionEngine(lexer, std::move(service), config); - - UNIT_ASSERT_EQUAL(Complete(engine, {"UPDA"}).size(), 0); - UNIT_ASSERT_EQUAL(Complete(engine, {"DELE"}).size(), 0); - UNIT_ASSERT_EQUAL(Complete(engine, {"ROLL"}).size(), 0); - UNIT_ASSERT_UNEQUAL(Complete(engine, {"INSE"}).size(), 0); - UNIT_ASSERT_UNEQUAL(Complete(engine, {"SELE"}).size(), 0); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "REDUCE a WITH ig"), expected); + } +} + +Y_UNIT_TEST(OnFailingNameService) { + auto service = MakeIntrusive<TFailingNameService>(); + auto engine = MakeSqlCompletionEngine(MakePureLexerSupplier(), std::move(service)); + UNIT_ASSERT_EXCEPTION(Complete(engine, ""), TDummyException); + UNIT_ASSERT_EXCEPTION(Complete(engine, "SELECT Optional<U"), TDummyException); + UNIT_ASSERT_EXCEPTION(Complete(engine, "SELECT CAST (1 AS ").size(), TDummyException); +} + +Y_UNIT_TEST(NameNormalization) { + auto service = MakeStaticNameService(LoadDefaultNameSet(), LoadFrequencyData()); + auto engine = MakeSqlCompletionEngine(MakePureLexerSupplier(), std::move(service)); + TVector<TCandidate> expected = { + {HintName, "IGNORE_TYPE_V3"}, + }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, {"REDUCE a WITH ignoret"}), expected); +} + +Y_UNIT_TEST(Ranking) { + TFrequencyData frequency = { + .Keywords = { + {"select", 2}, + {"insert", 4}, + }, + .Pragmas = { + {"yt.defaultmemorylimit", 16}, + {"yt.annotations", 8}, + }, + .Types = { + {"int32", 128}, + {"int64", 64}, + {"interval", 32}, + {"interval64", 32}, + }, + .Functions = { + {"min", 128}, + {"max", 64}, + {"maxof", 64}, + {"minby", 32}, + {"maxby", 32}, + }, + .Hints = { + {"xlock", 4}, + {"unordered", 2}, + }, + }; + auto service = MakeStaticNameService( + Pruned(LoadDefaultNameSet(), LoadFrequencyData()), + std::move(frequency)); + auto engine = MakeSqlCompletionEngine(MakePureLexerSupplier(), std::move(service)); + { + TVector<TCandidate> expected = { + {Keyword, "INSERT"}, + {Keyword, "SELECT"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, ""), expected); } - - Y_UNIT_TEST(IgnoredTokens) { - auto lexer = MakePureLexerSupplier(); - - TNameSet names; - TFrequencyData frequency; - auto service = MakeStaticNameService(names, MakeDefaultRanking(frequency)); - - auto config = MakeYQLConfiguration(); - auto engine = MakeSqlCompletionEngine(lexer, std::move(service), config); - - UNIT_ASSERT(!FindPtr(Complete(engine, {""}), TCandidate{Keyword, "FOR"})); - UNIT_ASSERT(!FindPtr(Complete(engine, {""}), TCandidate{Keyword, "PARALLEL"})); - - UNIT_ASSERT(FindPtr(Complete(engine, {"EVALUATE "}), TCandidate{Keyword, "FOR"})); - UNIT_ASSERT(FindPtr(Complete(engine, {"EVALUATE "}), TCandidate{Keyword, "FOR"})); - UNIT_ASSERT(FindPtr(Complete(engine, {"EVALUATE /**/"}), TCandidate{Keyword, "FOR"})); + { + TVector<TCandidate> expected = { + {PragmaName, "DefaultMemoryLimit"}, + {PragmaName, "Annotations"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, "PRAGMA yt."), expected); } - - Y_UNIT_TEST(CachedSchema) { - TLexerSupplier lexer = MakePureLexerSupplier(); - - auto time = NMonotonic::CreateDefaultMonotonicTimeProvider(); - TSchemaCaches caches = { - .List = MakeLocalCache< - TSchemaDescribeCacheKey, TVector<TFolderEntry>>(time, {}), - .DescribeTable = MakeLocalCache< - TSchemaDescribeCacheKey, TMaybe<TTableDetails>>(time, {}), + { + TVector<TCandidate> expected = { + {TypeName, "Int32"}, + {TypeName, "Int64"}, + {TypeName, "Interval"}, + {TypeName, "Interval64"}, + {TypeName, "Int16"}, + {TypeName, "Int8"}, }; + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT Optional<I"), expected); + } + { + TVector<TCandidate> expected = { + {FunctionName, "Min()", 1}, + {FunctionName, "Max()", 1}, + {FunctionName, "MaxOf()", 1}, + {FunctionName, "MaxBy()", 1}, + {FunctionName, "MinBy()", 1}, + {FunctionName, "Math::Abs()", 1}, + {FunctionName, "Math::Acos()", 1}, + {FunctionName, "Math::Asin()", 1}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, "SELECT m"), expected); + } + { + TVector<TCandidate> expected = { + {HintName, "XLOCK"}, + {HintName, "UNORDERED"}, + {Keyword, "COLUMNS"}, + {HintName, "FORCE_INFER_SCHEMA"}, + }; + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, "SELECT * FROM a WITH "), expected); + } +} - auto aliceService = MakeSchemaNameService( - MakeSimpleSchema( - MakeCachedSimpleSchema( - caches, "alice", - MakeStaticSimpleSchema(TSchemaData{ - .Folders = {{"", {{"/", {{"Table", "alice"}}}}}}, - .Tables = {{"", {{"/alice", {{"alice"}}}}}}, - })))); - - auto petyaService = MakeSchemaNameService( - MakeSimpleSchema( - MakeCachedSimpleSchema( - caches, "petya", - MakeStaticSimpleSchema(TSchemaData{ - .Folders = {{"", {{"/", {{"Table", "petya"}}}}}}, - .Tables = {{"", {{"/petya", {{"petya"}}}}}}, - })))); - - auto aliceEngine = MakeSqlCompletionEngine(lexer, std::move(aliceService)); - auto petyaEngine = MakeSqlCompletionEngine(lexer, std::move(petyaService)); - - TVector<TCandidate> empty; - { - TVector<TCandidate> aliceExpected = {{TableName, "`alice`"}}; - TVector<TCandidate> petyaExpected = {{TableName, "`petya`"}}; +Y_UNIT_TEST(IgnoredRules) { + auto lexer = MakePureLexerSupplier(); - // Updates in backround - UNIT_ASSERT_VALUES_EQUAL(Complete(aliceEngine, "SELECT * FROM "), aliceExpected); - UNIT_ASSERT_VALUES_EQUAL(Complete(petyaEngine, "SELECT * FROM "), petyaExpected); - } - { - TVector<TCandidate> aliceExpected = {{ColumnName, "alice"}}; - TVector<TCandidate> petyaExpected = {{ColumnName, "petya"}}; + TNameSet names; + TFrequencyData frequency; + auto service = MakeStaticNameService(names, MakeDefaultRanking(frequency)); - // Updates in backround - UNIT_ASSERT_VALUES_EQUAL(Complete(aliceEngine, "SELECT a# FROM alice"), aliceExpected); - UNIT_ASSERT_VALUES_EQUAL(Complete(petyaEngine, "SELECT p# FROM petya"), petyaExpected); - } + { + auto engine = MakeSqlCompletionEngine(lexer, service); + UNIT_ASSERT_UNEQUAL(Complete(engine, {"UPDA"}).size(), 0); + UNIT_ASSERT_UNEQUAL(Complete(engine, {"DELE"}).size(), 0); + UNIT_ASSERT_UNEQUAL(Complete(engine, {"ROLL"}).size(), 0); + UNIT_ASSERT_UNEQUAL(Complete(engine, {"INSE"}).size(), 0); + UNIT_ASSERT_UNEQUAL(Complete(engine, {"SELE"}).size(), 0); } + auto config = MakeYQLConfiguration(); + auto engine = MakeSqlCompletionEngine(lexer, std::move(service), config); + + UNIT_ASSERT_EQUAL(Complete(engine, {"UPDA"}).size(), 0); + UNIT_ASSERT_EQUAL(Complete(engine, {"DELE"}).size(), 0); + UNIT_ASSERT_EQUAL(Complete(engine, {"ROLL"}).size(), 0); + UNIT_ASSERT_UNEQUAL(Complete(engine, {"INSE"}).size(), 0); + UNIT_ASSERT_UNEQUAL(Complete(engine, {"SELE"}).size(), 0); +} + +Y_UNIT_TEST(IgnoredTokens) { + auto lexer = MakePureLexerSupplier(); + + TNameSet names; + TFrequencyData frequency; + auto service = MakeStaticNameService(names, MakeDefaultRanking(frequency)); + + auto config = MakeYQLConfiguration(); + auto engine = MakeSqlCompletionEngine(lexer, std::move(service), config); + + UNIT_ASSERT(!FindPtr(Complete(engine, {""}), TCandidate{Keyword, "FOR"})); + UNIT_ASSERT(!FindPtr(Complete(engine, {""}), TCandidate{Keyword, "PARALLEL"})); + + UNIT_ASSERT(FindPtr(Complete(engine, {"EVALUATE "}), TCandidate{Keyword, "FOR"})); + UNIT_ASSERT(FindPtr(Complete(engine, {"EVALUATE "}), TCandidate{Keyword, "FOR"})); + UNIT_ASSERT(FindPtr(Complete(engine, {"EVALUATE /**/"}), TCandidate{Keyword, "FOR"})); +} + +Y_UNIT_TEST(CachedSchema) { + TLexerSupplier lexer = MakePureLexerSupplier(); + + auto time = NMonotonic::CreateDefaultMonotonicTimeProvider(); + TSchemaCaches caches = { + .List = MakeLocalCache< + TSchemaDescribeCacheKey, TVector<TFolderEntry>>(time, {}), + .DescribeTable = MakeLocalCache< + TSchemaDescribeCacheKey, TMaybe<TTableDetails>>(time, {}), + }; + + auto aliceService = MakeSchemaNameService( + MakeSimpleSchema( + MakeCachedSimpleSchema( + caches, "alice", + MakeStaticSimpleSchema(TSchemaData{ + .Folders = {{"", {{"/", {{"Table", "alice"}}}}}}, + .Tables = {{"", {{"/alice", {{"alice"}}}}}}, + })))); + + auto petyaService = MakeSchemaNameService( + MakeSimpleSchema( + MakeCachedSimpleSchema( + caches, "petya", + MakeStaticSimpleSchema(TSchemaData{ + .Folders = {{"", {{"/", {{"Table", "petya"}}}}}}, + .Tables = {{"", {{"/petya", {{"petya"}}}}}}, + })))); + + auto aliceEngine = MakeSqlCompletionEngine(lexer, std::move(aliceService)); + auto petyaEngine = MakeSqlCompletionEngine(lexer, std::move(petyaService)); + + TVector<TCandidate> empty; + { + TVector<TCandidate> aliceExpected = {{TableName, "`alice`"}}; + TVector<TCandidate> petyaExpected = {{TableName, "`petya`"}}; + + // Updates in backround + UNIT_ASSERT_VALUES_EQUAL(Complete(aliceEngine, "SELECT * FROM "), aliceExpected); + UNIT_ASSERT_VALUES_EQUAL(Complete(petyaEngine, "SELECT * FROM "), petyaExpected); + } + { + TVector<TCandidate> aliceExpected = {{ColumnName, "alice"}}; + TVector<TCandidate> petyaExpected = {{ColumnName, "petya"}}; + + // Updates in backround + UNIT_ASSERT_VALUES_EQUAL(Complete(aliceEngine, "SELECT a# FROM alice"), aliceExpected); + UNIT_ASSERT_VALUES_EQUAL(Complete(petyaEngine, "SELECT p# FROM petya"), petyaExpected); + } +} + } // Y_UNIT_TEST_SUITE(SqlCompleteTests) diff --git a/yql/essentials/sql/v1/complete/syntax/ansi.cpp b/yql/essentials/sql/v1/complete/syntax/ansi.cpp index 7ca153e44ce..fcd627cb336 100644 --- a/yql/essentials/sql/v1/complete/syntax/ansi.cpp +++ b/yql/essentials/sql/v1/complete/syntax/ansi.cpp @@ -5,15 +5,15 @@ namespace NSQLComplete { - using NSQLTranslation::ParseTranslationSettings; - using NSQLTranslation::TTranslationSettings; - using NYql::TIssues; +using NSQLTranslation::ParseTranslationSettings; +using NSQLTranslation::TTranslationSettings; +using NYql::TIssues; - bool IsAnsiQuery(const TString& query) { - TTranslationSettings settings; - TIssues issues; - ParseTranslationSettings(query, settings, issues); - return settings.AnsiLexer; - } +bool IsAnsiQuery(const TString& query) { + TTranslationSettings settings; + TIssues issues; + ParseTranslationSettings(query, settings, issues); + return settings.AnsiLexer; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/syntax/ansi.h b/yql/essentials/sql/v1/complete/syntax/ansi.h index f03cbc9fb99..702ff4c339f 100644 --- a/yql/essentials/sql/v1/complete/syntax/ansi.h +++ b/yql/essentials/sql/v1/complete/syntax/ansi.h @@ -4,7 +4,7 @@ namespace NSQLComplete { - // Permits invalid special comments - bool IsAnsiQuery(const TString& query); +// Permits invalid special comments +bool IsAnsiQuery(const TString& query); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/syntax/format.cpp b/yql/essentials/sql/v1/complete/syntax/format.cpp index 57a314feb20..4c6b63f6330 100644 --- a/yql/essentials/sql/v1/complete/syntax/format.cpp +++ b/yql/essentials/sql/v1/complete/syntax/format.cpp @@ -9,63 +9,63 @@ namespace NSQLComplete { - namespace { +namespace { - const THashSet<std::string> Keywords = [] { - const auto& grammar = GetSqlGrammar(); - const auto& vocabulary = grammar.GetVocabulary(); +const THashSet<std::string> Keywords = [] { + const auto& grammar = GetSqlGrammar(); + const auto& vocabulary = grammar.GetVocabulary(); - THashSet<std::string> keywords; - for (auto& token : grammar.GetKeywordTokens()) { - keywords.emplace(Display(vocabulary, token)); - } - return keywords; - }(); - - } // namespace - - TString FormatKeywords(const TVector<TString>& seq) { - if (seq.empty()) { - return ""; - } - - TString text = seq[0]; - for (size_t i = 1; i < seq.size(); ++i) { - const auto& token = seq[i]; - if (Keywords.contains(token)) { - text += " "; - } - text += token; - } - return text; + THashSet<std::string> keywords; + for (auto& token : grammar.GetKeywordTokens()) { + keywords.emplace(Display(vocabulary, token)); } + return keywords; +}(); - bool IsPlain(TStringBuf content) { - return GetSqlGrammar().IsPlainIdentifier(content); - } +} // namespace - bool IsQuoted(TStringBuf content) { - return 2 <= content.size() && content.front() == '`' && content.back() == '`'; +TString FormatKeywords(const TVector<TString>& seq) { + if (seq.empty()) { + return ""; } - TString Quoted(TString content) { - content.prepend('`'); - content.append('`'); - return content; - } - - TStringBuf Unquoted(TStringBuf content) { - Y_ENSURE(IsQuoted(content)); - return content.SubStr(1, content.size() - 2); - } - - bool IsBinding(TStringBuf content) { - return 1 <= content.size() && content.front() == '$'; - } - - TStringBuf Unbinded(TStringBuf content) { - Y_ENSURE(IsBinding(content)); - return content.SubStr(1); + TString text = seq[0]; + for (size_t i = 1; i < seq.size(); ++i) { + const auto& token = seq[i]; + if (Keywords.contains(token)) { + text += " "; + } + text += token; } + return text; +} + +bool IsPlain(TStringBuf content) { + return GetSqlGrammar().IsPlainIdentifier(content); +} + +bool IsQuoted(TStringBuf content) { + return 2 <= content.size() && content.front() == '`' && content.back() == '`'; +} + +TString Quoted(TString content) { + content.prepend('`'); + content.append('`'); + return content; +} + +TStringBuf Unquoted(TStringBuf content) { + Y_ENSURE(IsQuoted(content)); + return content.SubStr(1, content.size() - 2); +} + +bool IsBinding(TStringBuf content) { + return 1 <= content.size() && content.front() == '$'; +} + +TStringBuf Unbinded(TStringBuf content) { + Y_ENSURE(IsBinding(content)); + return content.SubStr(1); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/syntax/format.h b/yql/essentials/sql/v1/complete/syntax/format.h index 8527788f209..fe2a9193c39 100644 --- a/yql/essentials/sql/v1/complete/syntax/format.h +++ b/yql/essentials/sql/v1/complete/syntax/format.h @@ -5,18 +5,18 @@ namespace NSQLComplete { - TString FormatKeywords(const TVector<TString>& seq); +TString FormatKeywords(const TVector<TString>& seq); - bool IsPlain(TStringBuf content); +bool IsPlain(TStringBuf content); - bool IsQuoted(TStringBuf content); +bool IsQuoted(TStringBuf content); - TString Quoted(TString content); +TString Quoted(TString content); - TStringBuf Unquoted(TStringBuf content); +TStringBuf Unquoted(TStringBuf content); - bool IsBinding(TStringBuf content); +bool IsBinding(TStringBuf content); - TStringBuf Unbinded(TStringBuf content); +TStringBuf Unbinded(TStringBuf content); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/syntax/grammar.cpp b/yql/essentials/sql/v1/complete/syntax/grammar.cpp index 9e15a8e2347..fc70c488b63 100644 --- a/yql/essentials/sql/v1/complete/syntax/grammar.cpp +++ b/yql/essentials/sql/v1/complete/syntax/grammar.cpp @@ -9,123 +9,123 @@ namespace NSQLComplete { - class TSqlGrammar: public ISqlGrammar { - public: - TSqlGrammar(const NSQLReflect::TLexerGrammar& grammar) - : Parser_(MakeDummyParser()) - , AllTokens_(ComputeAllTokens()) - , KeywordTokens_(ComputeKeywordTokens(grammar)) - , PunctuationTokens_(ComputePunctuationTokens(grammar)) - , IdPlainRegex_(ComputeIdPlainRegex(grammar)) - { - } - - const antlr4::dfa::Vocabulary& GetVocabulary() const override { - return Parser_->getVocabulary(); - } +class TSqlGrammar: public ISqlGrammar { +public: + TSqlGrammar(const NSQLReflect::TLexerGrammar& grammar) + : Parser_(MakeDummyParser()) + , AllTokens_(ComputeAllTokens()) + , KeywordTokens_(ComputeKeywordTokens(grammar)) + , PunctuationTokens_(ComputePunctuationTokens(grammar)) + , IdPlainRegex_(ComputeIdPlainRegex(grammar)) + { + } - const std::unordered_set<TTokenId>& GetAllTokens() const override { - return AllTokens_; - } + const antlr4::dfa::Vocabulary& GetVocabulary() const override { + return Parser_->getVocabulary(); + } - const std::unordered_set<TTokenId>& GetKeywordTokens() const override { - return KeywordTokens_; - } + const std::unordered_set<TTokenId>& GetAllTokens() const override { + return AllTokens_; + } - const std::unordered_set<TTokenId>& GetPunctuationTokens() const override { - return PunctuationTokens_; - } + const std::unordered_set<TTokenId>& GetKeywordTokens() const override { + return KeywordTokens_; + } - const std::string& SymbolizedRule(TRuleId rule) const override { - return Parser_->getRuleNames().at(rule); - } + const std::unordered_set<TTokenId>& GetPunctuationTokens() const override { + return PunctuationTokens_; + } - TTokenId GetTokenId(std::string_view symbolized) const override { - TTokenId type = Parser_->getTokenType(symbolized); - Y_ENSURE(type != antlr4::Token::INVALID_TYPE, "Not found " << symbolized); - return type; - } + const std::string& SymbolizedRule(TRuleId rule) const override { + return Parser_->getRuleNames().at(rule); + } - TRuleId GetRuleId(std::string_view symbolized) const override { - TRuleId index = Parser_->getRuleIndex(std::string(symbolized)); - if (index == INVALID_INDEX) { - ythrow yexception() << "Rule \"" << symbolized << "\" not found"; - } - return index; - } + TTokenId GetTokenId(std::string_view symbolized) const override { + TTokenId type = Parser_->getTokenType(symbolized); + Y_ENSURE(type != antlr4::Token::INVALID_TYPE, "Not found " << symbolized); + return type; + } - const std::vector<std::string>& GetAllRules() const override { - return Parser_->getRuleNames(); + TRuleId GetRuleId(std::string_view symbolized) const override { + TRuleId index = Parser_->getRuleIndex(std::string(symbolized)); + if (index == INVALID_INDEX) { + ythrow yexception() << "Rule \"" << symbolized << "\" not found"; } + return index; + } - bool IsPlainIdentifier(TStringBuf content) const override { - return RE2::FullMatch(content, IdPlainRegex_); - } + const std::vector<std::string>& GetAllRules() const override { + return Parser_->getRuleNames(); + } - private: - static THolder<antlr4::Parser> MakeDummyParser() { - return MakeHolder<NALADefaultAntlr4::SQLv1Antlr4Parser>(nullptr); - } + bool IsPlainIdentifier(TStringBuf content) const override { + return RE2::FullMatch(content, IdPlainRegex_); + } - std::unordered_set<TTokenId> ComputeAllTokens() { - const auto& vocabulary = GetVocabulary(); +private: + static THolder<antlr4::Parser> MakeDummyParser() { + return MakeHolder<NALADefaultAntlr4::SQLv1Antlr4Parser>(nullptr); + } - std::unordered_set<TTokenId> allTokens; + std::unordered_set<TTokenId> ComputeAllTokens() { + const auto& vocabulary = GetVocabulary(); - for (size_t type = 1; type <= vocabulary.getMaxTokenType(); ++type) { - allTokens.emplace(type); - } + std::unordered_set<TTokenId> allTokens; - return allTokens; + for (size_t type = 1; type <= vocabulary.getMaxTokenType(); ++type) { + allTokens.emplace(type); } - std::unordered_set<TTokenId> ComputeKeywordTokens( - const NSQLReflect::TLexerGrammar& grammar) { - const auto& vocabulary = GetVocabulary(); - - auto keywordTokens = GetAllTokens(); - std::erase_if(keywordTokens, [&](TTokenId token) { - return !grammar.KeywordNames.contains(vocabulary.getSymbolicName(token)); - }); - keywordTokens.erase(TOKEN_EOF); + return allTokens; + } - return keywordTokens; - } + std::unordered_set<TTokenId> ComputeKeywordTokens( + const NSQLReflect::TLexerGrammar& grammar) { + const auto& vocabulary = GetVocabulary(); - std::unordered_set<TTokenId> ComputePunctuationTokens( - const NSQLReflect::TLexerGrammar& grammar) { - const auto& vocabulary = GetVocabulary(); + auto keywordTokens = GetAllTokens(); + std::erase_if(keywordTokens, [&](TTokenId token) { + return !grammar.KeywordNames.contains(vocabulary.getSymbolicName(token)); + }); + keywordTokens.erase(TOKEN_EOF); - auto punctuationTokens = GetAllTokens(); - std::erase_if(punctuationTokens, [&](TTokenId token) { - return !grammar.PunctuationNames.contains(vocabulary.getSymbolicName(token)); - }); + return keywordTokens; + } - return punctuationTokens; - } + std::unordered_set<TTokenId> ComputePunctuationTokens( + const NSQLReflect::TLexerGrammar& grammar) { + const auto& vocabulary = GetVocabulary(); - static TString ComputeIdPlainRegex(const NSQLReflect::TLexerGrammar& grammar) { - TVector<std::tuple<TString, TString>> regexes = - NSQLTranslationV1::MakeRegexByOtherName(grammar, /* ansi = */ false); + auto punctuationTokens = GetAllTokens(); + std::erase_if(punctuationTokens, [&](TTokenId token) { + return !grammar.PunctuationNames.contains(vocabulary.getSymbolicName(token)); + }); - std::tuple<TString, TString>* regex = FindIfPtr(regexes, [&](const auto& x) { - return std::get<0>(x) == "ID_PLAIN"; - }); + return punctuationTokens; + } - Y_ENSURE(regex, "ID_PLAIN regex not found"); - return std::get<1>(*regex); - } + static TString ComputeIdPlainRegex(const NSQLReflect::TLexerGrammar& grammar) { + TVector<std::tuple<TString, TString>> regexes = + NSQLTranslationV1::MakeRegexByOtherName(grammar, /* ansi = */ false); - const THolder<antlr4::Parser> Parser_; - const std::unordered_set<TTokenId> AllTokens_; - const std::unordered_set<TTokenId> KeywordTokens_; - const std::unordered_set<TTokenId> PunctuationTokens_; - const RE2 IdPlainRegex_; - }; + std::tuple<TString, TString>* regex = FindIfPtr(regexes, [&](const auto& x) { + return std::get<0>(x) == "ID_PLAIN"; + }); - const ISqlGrammar& GetSqlGrammar() { - const static TSqlGrammar DefaultSqlGrammar(NSQLReflect::LoadLexerGrammar()); - return DefaultSqlGrammar; + Y_ENSURE(regex, "ID_PLAIN regex not found"); + return std::get<1>(*regex); } + const THolder<antlr4::Parser> Parser_; + const std::unordered_set<TTokenId> AllTokens_; + const std::unordered_set<TTokenId> KeywordTokens_; + const std::unordered_set<TTokenId> PunctuationTokens_; + const RE2 IdPlainRegex_; +}; + +const ISqlGrammar& GetSqlGrammar() { + const static TSqlGrammar DefaultSqlGrammar(NSQLReflect::LoadLexerGrammar()); + return DefaultSqlGrammar; +} + } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/syntax/grammar.h b/yql/essentials/sql/v1/complete/syntax/grammar.h index 9db650b58c7..26909d98494 100644 --- a/yql/essentials/sql/v1/complete/syntax/grammar.h +++ b/yql/essentials/sql/v1/complete/syntax/grammar.h @@ -19,20 +19,20 @@ namespace NSQLComplete { - class ISqlGrammar { - public: - virtual ~ISqlGrammar() = default; - virtual const antlr4::dfa::Vocabulary& GetVocabulary() const = 0; - virtual const std::string& SymbolizedRule(TRuleId rule) const = 0; - virtual TTokenId GetTokenId(std::string_view symbolized) const = 0; - virtual TRuleId GetRuleId(std::string_view symbolized) const = 0; - virtual const std::vector<std::string>& GetAllRules() const = 0; - virtual const std::unordered_set<TTokenId>& GetAllTokens() const = 0; - virtual const std::unordered_set<TTokenId>& GetKeywordTokens() const = 0; - virtual const std::unordered_set<TTokenId>& GetPunctuationTokens() const = 0; - virtual bool IsPlainIdentifier(TStringBuf content) const = 0; - }; - - const ISqlGrammar& GetSqlGrammar(); +class ISqlGrammar { +public: + virtual ~ISqlGrammar() = default; + virtual const antlr4::dfa::Vocabulary& GetVocabulary() const = 0; + virtual const std::string& SymbolizedRule(TRuleId rule) const = 0; + virtual TTokenId GetTokenId(std::string_view symbolized) const = 0; + virtual TRuleId GetRuleId(std::string_view symbolized) const = 0; + virtual const std::vector<std::string>& GetAllRules() const = 0; + virtual const std::unordered_set<TTokenId>& GetAllTokens() const = 0; + virtual const std::unordered_set<TTokenId>& GetKeywordTokens() const = 0; + virtual const std::unordered_set<TTokenId>& GetPunctuationTokens() const = 0; + virtual bool IsPlainIdentifier(TStringBuf content) const = 0; +}; + +const ISqlGrammar& GetSqlGrammar(); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/syntax/grammar_ut.cpp b/yql/essentials/sql/v1/complete/syntax/grammar_ut.cpp index 50fb6b43054..b478a0e7e8a 100644 --- a/yql/essentials/sql/v1/complete/syntax/grammar_ut.cpp +++ b/yql/essentials/sql/v1/complete/syntax/grammar_ut.cpp @@ -4,34 +4,34 @@ #include <library/cpp/testing/unittest/registar.h> Y_UNIT_TEST_SUITE(RuleTests) { - THolder<antlr4::Parser> GetDummyParser(bool ansi) { - if (ansi) { - return MakeHolder<NALAAnsiAntlr4::SQLv1Antlr4Parser>(nullptr); - } - return MakeHolder<NALADefaultAntlr4::SQLv1Antlr4Parser>(nullptr); +THolder<antlr4::Parser> GetDummyParser(bool ansi) { + if (ansi) { + return MakeHolder<NALAAnsiAntlr4::SQLv1Antlr4Parser>(nullptr); } + return MakeHolder<NALADefaultAntlr4::SQLv1Antlr4Parser>(nullptr); +} - Y_UNIT_TEST(RuleIndexModeIndependent) { - auto defaultRules = GetDummyParser(/* ansi = */ false)->getRuleIndexMap(); - auto ansiRules = GetDummyParser(/* ansi = */ true)->getRuleIndexMap(); +Y_UNIT_TEST(RuleIndexModeIndependent) { + auto defaultRules = GetDummyParser(/* ansi = */ false)->getRuleIndexMap(); + auto ansiRules = GetDummyParser(/* ansi = */ true)->getRuleIndexMap(); - UNIT_ASSERT_EQUAL(defaultRules, ansiRules); - } + UNIT_ASSERT_EQUAL(defaultRules, ansiRules); +} - Y_UNIT_TEST(TokenTypeModeIndependent) { - auto defaultVocab = GetDummyParser(/* ansi = */ false)->getVocabulary(); - auto ansiVocab = GetDummyParser(/* ansi = */ true)->getVocabulary(); +Y_UNIT_TEST(TokenTypeModeIndependent) { + auto defaultVocab = GetDummyParser(/* ansi = */ false)->getVocabulary(); + auto ansiVocab = GetDummyParser(/* ansi = */ true)->getVocabulary(); - UNIT_ASSERT_VALUES_EQUAL(defaultVocab.getMaxTokenType(), ansiVocab.getMaxTokenType()); + UNIT_ASSERT_VALUES_EQUAL(defaultVocab.getMaxTokenType(), ansiVocab.getMaxTokenType()); - for (size_t type = 0; type <= defaultVocab.getMaxTokenType(); ++type) { - UNIT_ASSERT_VALUES_EQUAL( - defaultVocab.getSymbolicName(type), ansiVocab.getSymbolicName(type)); - UNIT_ASSERT_VALUES_EQUAL( - defaultVocab.getDisplayName(type), ansiVocab.getDisplayName(type)); - UNIT_ASSERT_VALUES_EQUAL( - defaultVocab.getLiteralName(type), ansiVocab.getLiteralName(type)); - } + for (size_t type = 0; type <= defaultVocab.getMaxTokenType(); ++type) { + UNIT_ASSERT_VALUES_EQUAL( + defaultVocab.getSymbolicName(type), ansiVocab.getSymbolicName(type)); + UNIT_ASSERT_VALUES_EQUAL( + defaultVocab.getDisplayName(type), ansiVocab.getDisplayName(type)); + UNIT_ASSERT_VALUES_EQUAL( + defaultVocab.getLiteralName(type), ansiVocab.getLiteralName(type)); } +} } // Y_UNIT_TEST_SUITE(RuleTests) diff --git a/yql/essentials/sql/v1/complete/text/case.cpp b/yql/essentials/sql/v1/complete/text/case.cpp index ea1b39e1613..cedac5c6374 100644 --- a/yql/essentials/sql/v1/complete/text/case.cpp +++ b/yql/essentials/sql/v1/complete/text/case.cpp @@ -4,8 +4,8 @@ namespace NSQLComplete { - bool NoCaseCompare(const TString& lhs, const TString& rhs) { - return AsciiCompareIgnoreCase(lhs, rhs) < 0; - } +bool NoCaseCompare(const TString& lhs, const TString& rhs) { + return AsciiCompareIgnoreCase(lhs, rhs) < 0; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/text/case.h b/yql/essentials/sql/v1/complete/text/case.h index 883cb7f5048..8cad09412e6 100644 --- a/yql/essentials/sql/v1/complete/text/case.h +++ b/yql/essentials/sql/v1/complete/text/case.h @@ -4,12 +4,12 @@ namespace NSQLComplete { - bool NoCaseCompare(const TString& lhs, const TString& rhs); +bool NoCaseCompare(const TString& lhs, const TString& rhs); - inline auto NoCaseCompareLimit(size_t size) { - return [size](const TString& lhs, const TString& rhs) -> bool { - return strncasecmp(lhs.data(), rhs.data(), size) < 0; - }; - } +inline auto NoCaseCompareLimit(size_t size) { + return [size](const TString& lhs, const TString& rhs) -> bool { + return strncasecmp(lhs.data(), rhs.data(), size) < 0; + }; +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/text/word.cpp b/yql/essentials/sql/v1/complete/text/word.cpp index 0468f62b031..0cbd547ea90 100644 --- a/yql/essentials/sql/v1/complete/text/word.cpp +++ b/yql/essentials/sql/v1/complete/text/word.cpp @@ -4,26 +4,26 @@ namespace NSQLComplete { - bool IsWordBoundary(char ch) { // Is optimized into table lookup by clang - for (size_t i = 0; i < sizeof(WordBreakCharacters) - 1; ++i) { - if (WordBreakCharacters[i] == ch) { - return true; - } +bool IsWordBoundary(char ch) { // Is optimized into table lookup by clang + for (size_t i = 0; i < sizeof(WordBreakCharacters) - 1; ++i) { + if (WordBreakCharacters[i] == ch) { + return true; } - return false; } + return false; +} - size_t LastWordIndex(TStringBuf text) { - for (auto it = std::rbegin(text); it != std::rend(text); std::advance(it, 1)) { - if (IsWordBoundary(*it)) { - return std::distance(it, std::rend(text)); - } +size_t LastWordIndex(TStringBuf text) { + for (auto it = std::rbegin(text); it != std::rend(text); std::advance(it, 1)) { + if (IsWordBoundary(*it)) { + return std::distance(it, std::rend(text)); } - return 0; } + return 0; +} - TStringBuf LastWord(TStringBuf text) { - return text.SubStr(LastWordIndex(text)); - } +TStringBuf LastWord(TStringBuf text) { + return text.SubStr(LastWordIndex(text)); +} } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/text/word.h b/yql/essentials/sql/v1/complete/text/word.h index e56f023940f..b4b0726ac33 100644 --- a/yql/essentials/sql/v1/complete/text/word.h +++ b/yql/essentials/sql/v1/complete/text/word.h @@ -4,12 +4,12 @@ namespace NSQLComplete { - static const char WordBreakCharacters[] = " \t\v\f\a\b\r\n`~!@#$%^&*-=+[](){}\\|;:'\".,<>/?"; +static const char WordBreakCharacters[] = " \t\v\f\a\b\r\n`~!@#$%^&*-=+[](){}\\|;:'\".,<>/?"; - bool IsWordBoundary(char ch); +bool IsWordBoundary(char ch); - size_t LastWordIndex(TStringBuf text); +size_t LastWordIndex(TStringBuf text); - TStringBuf LastWord(TStringBuf text); +TStringBuf LastWord(TStringBuf text); } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/text/word_ut.cpp b/yql/essentials/sql/v1/complete/text/word_ut.cpp index 0eff931b1af..e33f0676b5b 100644 --- a/yql/essentials/sql/v1/complete/text/word_ut.cpp +++ b/yql/essentials/sql/v1/complete/text/word_ut.cpp @@ -5,17 +5,17 @@ using namespace NSQLComplete; Y_UNIT_TEST_SUITE(WordTest) { - Y_UNIT_TEST(Blank) { - UNIT_ASSERT_VALUES_EQUAL(LastWord(""), ""); - UNIT_ASSERT_VALUES_EQUAL(LastWord(" "), ""); - UNIT_ASSERT_VALUES_EQUAL(LastWord(" "), ""); - UNIT_ASSERT_VALUES_EQUAL(LastWord(" "), ""); - } +Y_UNIT_TEST(Blank) { + UNIT_ASSERT_VALUES_EQUAL(LastWord(""), ""); + UNIT_ASSERT_VALUES_EQUAL(LastWord(" "), ""); + UNIT_ASSERT_VALUES_EQUAL(LastWord(" "), ""); + UNIT_ASSERT_VALUES_EQUAL(LastWord(" "), ""); +} - Y_UNIT_TEST(Space) { - UNIT_ASSERT_VALUES_EQUAL(LastWord("two "), ""); - UNIT_ASSERT_VALUES_EQUAL(LastWord("one two "), ""); - UNIT_ASSERT_VALUES_EQUAL(LastWord("two"), "two"); - UNIT_ASSERT_VALUES_EQUAL(LastWord("one two"), "two"); - } +Y_UNIT_TEST(Space) { + UNIT_ASSERT_VALUES_EQUAL(LastWord("two "), ""); + UNIT_ASSERT_VALUES_EQUAL(LastWord("one two "), ""); + UNIT_ASSERT_VALUES_EQUAL(LastWord("two"), "two"); + UNIT_ASSERT_VALUES_EQUAL(LastWord("one two"), "two"); +} } // Y_UNIT_TEST_SUITE(WordTest) diff --git a/yql/essentials/sql/v1/complete/ya.make b/yql/essentials/sql/v1/complete/ya.make index b0b5ee4be21..8df41ab8013 100644 --- a/yql/essentials/sql/v1/complete/ya.make +++ b/yql/essentials/sql/v1/complete/ya.make @@ -1,5 +1,7 @@ LIBRARY() +ENABLE(YQL_STYLE_CPP) + SRCS( configuration.cpp name_mapping.cpp diff --git a/yql/essentials/sql/v1/context.cpp b/yql/essentials/sql/v1/context.cpp index f24258da66f..32aae0989de 100644 --- a/yql/essentials/sql/v1/context.cpp +++ b/yql/essentials/sql/v1/context.cpp @@ -10,7 +10,7 @@ #include <util/generic/scope.h> #ifdef GetMessage -#undef GetMessage + #undef GetMessage #endif using namespace NYql; @@ -29,10 +29,10 @@ TNodePtr AddTablePathPrefix(TContext& ctx, TStringBuf prefixPath, const TDeferre } auto pathNode = path.Build(); - pathNode = new TCallNodeImpl(pathNode->GetPos(), "String", { pathNode }); + pathNode = new TCallNodeImpl(pathNode->GetPos(), "String", {pathNode}); auto prefixNode = BuildLiteralRawString(pathNode->GetPos(), TString(prefixPath)); - TNodePtr buildPathNode = new TCallNodeImpl(pathNode->GetPos(), "BuildTablePath", { prefixNode, pathNode }); + TNodePtr buildPathNode = new TCallNodeImpl(pathNode->GetPos(), "BuildTablePath", {prefixNode, pathNode}); TDeferredAtom result; MakeTableFromExpression(ctx.Pos(), ctx, buildPathNode, result); @@ -135,7 +135,7 @@ TContext::TContext(const TLexers& lexers, const TParsers& parsers, Position_.File = settings.File; - for (auto& flag: settings.Flags) { + for (auto& flag : settings.Flags) { bool value = true; TStringBuf key = flag; auto ptr = CTX_PRAGMA_FIELDS.FindPtr(key); @@ -156,7 +156,7 @@ TContext::TContext(const TLexers& lexers, const TParsers& parsers, TContext::~TContext() { - for (auto& x: AllScopes) { + for (auto& x : AllScopes) { x->Clear(); } } @@ -202,7 +202,7 @@ IOutputStream& TContext::Error(NYql::TPosition pos, NYql::TIssueCode code) { } bool TContext::Warning(NYql::TPosition pos, NYql::TIssueCode code, std::function<void(IOutputStream&)> message, - bool forceError) { + bool forceError) { bool isError; IOutputStream& out = MakeIssue(TSeverityIds::S_WARNING, code, pos, forceError, isError); message(out); @@ -250,7 +250,7 @@ bool TContext::WarnUnusedHints() { } IOutputStream& TContext::MakeIssue(ESeverity severity, TIssueCode code, NYql::TPosition pos, - bool forceError, bool& isError) { + bool forceError, bool& isError) { isError = (severity == TSeverityIds::S_ERROR); if (severity == TSeverityIds::S_WARNING) { @@ -312,10 +312,7 @@ bool TContext::IsDynamicCluster(const TDeferredAtom& cluster) const { bool TContext::SetPathPrefix(const TString& value, TMaybe<TString> arg) { if (arg.Defined()) { - if (*arg == YtProviderName - || *arg == KikimrProviderName - || *arg == RtmrProviderName - ) + if (*arg == YtProviderName || *arg == KikimrProviderName || *arg == RtmrProviderName) { ProviderPathPrefixes_[*arg] = value; return true; @@ -349,8 +346,8 @@ TStringBuf TContext::GetPrefixPath(const TString& service, const TDeferredAtom& return {}; } auto* clusterPrefix = cluster.GetLiteral() - ? ClusterPathPrefixes_.FindPtr(*cluster.GetLiteral()) - : nullptr; + ? ClusterPathPrefixes_.FindPtr(*cluster.GetLiteral()) + : nullptr; if (clusterPrefix && !clusterPrefix->empty()) { return *clusterPrefix; } else { @@ -471,7 +468,7 @@ TNodePtr TScopedState::WrapCluster(const TDeferredAtom& cluster, TContext& ctx) } void TScopedState::Clear() { - *this = TScopedState(); + *this = TScopedState(); } TNodePtr TScopedState::LookupNode(const TString& name) { @@ -489,13 +486,13 @@ bool TContext::HasNonYtProvider(const ISource& source) const { source.GetInputTables(tableList); TSet<TString> clusters; - for (auto& it: tableList) { + for (auto& it : tableList) { if (it.Service != YtProviderName) { return true; } } - for (auto& cl: Scoped->Local.UsedClusters) { + for (auto& cl : Scoped->Local.UsedClusters) { if (cl.first != YtProviderName) { return true; } @@ -551,36 +548,36 @@ TMaybe<EColumnRefState> GetFunctionArgColumnStatus(TContext& ctx, const TString& "variantunderlyingtype", }; static const TMap<std::pair<TStringBuf, size_t>, EColumnRefState> positionalArgsCustomStatus = { - { {"frombytes", 1}, EColumnRefState::Deny }, - { {"enum", 0}, EColumnRefState::Deny }, - { {"asenum", 0}, EColumnRefState::Deny }, - { {"variant", 1}, EColumnRefState::Deny }, - { {"variant", 2}, EColumnRefState::Deny }, - { {"asvariant", 1}, EColumnRefState::Deny }, - { {"astagged", 1}, EColumnRefState::Deny }, - { {"ensuretype", 1}, EColumnRefState::Deny }, - { {"ensuretype", 2}, EColumnRefState::Deny }, - { {"ensureconvertibleto", 1}, EColumnRefState::Deny }, - { {"ensureconvertibleto", 2}, EColumnRefState::Deny }, - - { {"nothing", 0}, EColumnRefState::Deny }, - { {"formattype", 0}, EColumnRefState::Deny }, - { {"instanceof", 0}, EColumnRefState::Deny }, - { {"pgtype", 0}, EColumnRefState::AsPgType }, - { {"pgconst", 0}, EColumnRefState::Deny }, - { {"pgconst", 1}, EColumnRefState::AsPgType }, - { {"pgcast", 1}, EColumnRefState::AsPgType }, - - { {"unpickle", 0}, EColumnRefState::Deny }, - { {"typehandle", 0}, EColumnRefState::Deny }, - - { {"listcreate", 0}, EColumnRefState::Deny }, - { {"setcreate", 0}, EColumnRefState::Deny }, - { {"dictcreate", 0}, EColumnRefState::Deny }, - { {"dictcreate", 1}, EColumnRefState::Deny }, - { {"weakfield", 1}, EColumnRefState::Deny }, - - { {"Yson::ConvertTo", 1}, EColumnRefState::Deny }, + {{"frombytes", 1}, EColumnRefState::Deny}, + {{"enum", 0}, EColumnRefState::Deny}, + {{"asenum", 0}, EColumnRefState::Deny}, + {{"variant", 1}, EColumnRefState::Deny}, + {{"variant", 2}, EColumnRefState::Deny}, + {{"asvariant", 1}, EColumnRefState::Deny}, + {{"astagged", 1}, EColumnRefState::Deny}, + {{"ensuretype", 1}, EColumnRefState::Deny}, + {{"ensuretype", 2}, EColumnRefState::Deny}, + {{"ensureconvertibleto", 1}, EColumnRefState::Deny}, + {{"ensureconvertibleto", 2}, EColumnRefState::Deny}, + + {{"nothing", 0}, EColumnRefState::Deny}, + {{"formattype", 0}, EColumnRefState::Deny}, + {{"instanceof", 0}, EColumnRefState::Deny}, + {{"pgtype", 0}, EColumnRefState::AsPgType}, + {{"pgconst", 0}, EColumnRefState::Deny}, + {{"pgconst", 1}, EColumnRefState::AsPgType}, + {{"pgcast", 1}, EColumnRefState::AsPgType}, + + {{"unpickle", 0}, EColumnRefState::Deny}, + {{"typehandle", 0}, EColumnRefState::Deny}, + + {{"listcreate", 0}, EColumnRefState::Deny}, + {{"setcreate", 0}, EColumnRefState::Deny}, + {{"dictcreate", 0}, EColumnRefState::Deny}, + {{"dictcreate", 1}, EColumnRefState::Deny}, + {{"weakfield", 1}, EColumnRefState::Deny}, + + {{"Yson::ConvertTo", 1}, EColumnRefState::Deny}, }; TString normalized; @@ -652,7 +649,7 @@ TString TTranslation::PushNamedNode(TPosition namePos, const TString& name, cons return resultName; } -TString TTranslation::PushNamedNode(NYql::TPosition namePos, const TString &name, NSQLTranslationV1::TNodePtr node) { +TString TTranslation::PushNamedNode(NYql::TPosition namePos, const TString& name, NSQLTranslationV1::TNodePtr node) { return PushNamedNode(namePos, name, [node](const TString&) { return node; }); } @@ -678,8 +675,8 @@ bool TTranslation::PopNamedNode(const TString& name) { auto& top = mapIt->second.front(); if (!top->IsUsed && !Ctx_.HasPendingErrors && !name.StartsWith("$_")) { if (!Ctx_.Warning(top->NamePos, TIssuesIds::YQL_UNUSED_SYMBOL, [&](auto& out) { - out << "Symbol " << name << " is not used"; - })) { + out << "Symbol " << name << " is not used"; + })) { return false; } } @@ -692,7 +689,7 @@ bool TTranslation::WarnUnusedNodes() const { return true; } - for (const auto& [name, items]: Ctx_.Scoped->NamedNodes) { + for (const auto& [name, items] : Ctx_.Scoped->NamedNodes) { if (name.StartsWith("$_")) { continue; } @@ -700,8 +697,8 @@ bool TTranslation::WarnUnusedNodes() const { for (const auto& item : items) { if (!item->IsUsed && item->Level == Ctx_.ScopeLevel) { if (!Ctx_.Warning(item->NamePos, TIssuesIds::YQL_UNUSED_SYMBOL, [&](auto& out) { - out << "Symbol " << name << " is not used"; - })) { + out << "Symbol " << name << " is not used"; + })) { return false; } } diff --git a/yql/essentials/sql/v1/context.h b/yql/essentials/sql/v1/context.h index 6bd89f16e29..1f6d660c7fb 100644 --- a/yql/essentials/sql/v1/context.h +++ b/yql/essentials/sql/v1/context.h @@ -19,479 +19,478 @@ #include <util/generic/vector.h> namespace NSQLTranslationV1 { - inline bool IsAnonymousName(const TString& name) { - return name == "$_"; +inline bool IsAnonymousName(const TString& name) { + return name == "$_"; +} + +inline bool IsStreamingService(const TString& service) { + return service == NYql::RtmrProviderName || service == NYql::PqProviderName; +} + +struct TNodeWithUsageInfo: public TThrRefBase { + explicit TNodeWithUsageInfo(const TNodePtr& node, TPosition namePos, int level) + : Node(node) + , NamePos(namePos) + , Level(level) + { } - inline bool IsStreamingService(const TString& service) { - return service == NYql::RtmrProviderName || service == NYql::PqProviderName; - } - - - struct TNodeWithUsageInfo : public TThrRefBase { - explicit TNodeWithUsageInfo(const TNodePtr& node, TPosition namePos, int level) - : Node(node) - , NamePos(namePos) - , Level(level) - {} - - TNodePtr Node; - TPosition NamePos; - int Level = 0; - bool IsUsed = false; + TNodePtr Node; + TPosition NamePos; + int Level = 0; + bool IsUsed = false; +}; + +using TNodeWithUsageInfoPtr = TIntrusivePtr<TNodeWithUsageInfo>; +using TNamedNodesMap = THashMap<TString, TDeque<TNodeWithUsageInfoPtr>>; +using TBlocks = TVector<TNodePtr>; + +struct TScopedState: public TThrRefBase { + TString CurrService; + TDeferredAtom CurrCluster; + bool PragmaClassicDivision = true; + bool PragmaCheckedOps = false; + bool StrictJoinKeyTypes = false; + bool UnicodeLiterals = false; + bool WarnUntypedStringLiterals = false; + TNamedNodesMap NamedNodes; + + struct TLocal { + TVector<std::pair<TString, TDeferredAtom>> UsedClusters; + THashSet<TString> UsedPlainClusters; + THashSet<INode*> UsedExprClusters; + THashMap<INode*, std::pair<TString, TNodePtr>> ExprClustersMap; + TVector<TNodePtr> ExprClusters; }; - using TNodeWithUsageInfoPtr = TIntrusivePtr<TNodeWithUsageInfo>; - using TNamedNodesMap = THashMap<TString, TDeque<TNodeWithUsageInfoPtr>>; - using TBlocks = TVector<TNodePtr>; - - struct TScopedState : public TThrRefBase { - TString CurrService; - TDeferredAtom CurrCluster; - bool PragmaClassicDivision = true; - bool PragmaCheckedOps = false; - bool StrictJoinKeyTypes = false; - bool UnicodeLiterals = false; - bool WarnUntypedStringLiterals = false; - TNamedNodesMap NamedNodes; - - struct TLocal { - TVector<std::pair<TString, TDeferredAtom>> UsedClusters; - THashSet<TString> UsedPlainClusters; - THashSet<INode*> UsedExprClusters; - THashMap<INode*, std::pair<TString, TNodePtr>> ExprClustersMap; - TVector<TNodePtr> ExprClusters; - }; - - TLocal Local; - - void UseCluster(const TString& service, const TDeferredAtom& cluster); - const TVector<std::pair<TString, TDeferredAtom>>& GetUsedClusters(); - TNodePtr WrapCluster(const TDeferredAtom& cluster, TContext& ctx); - void AddExprCluster(TNodePtr expr, TContext& ctx); - void Clear(); - TNodePtr LookupNode(const TString& name); - }; - - using TScopedStatePtr = TIntrusivePtr<TScopedState>; - - class TColumnRefScope; - enum class EColumnRefState { - Deny, - Allow, - AsStringLiteral, - AsPgType, - MatchRecognizeMeasures, - MatchRecognizeDefine, - MatchRecognizeDefineAggregate, - }; - - class TContext { - public: - TContext(const TLexers& lexers, - const TParsers& parsers, - const NSQLTranslation::TTranslationSettings& settings, - const NSQLTranslation::TSQLHints& hints, - NYql::TIssues& issues, - const TString& query = {}); - - virtual ~TContext(); - - const NYql::TPosition& Pos() const; - - void PushCurrentBlocks(TBlocks* blocks); - void PopCurrentBlocks(); - TBlocks& GetCurrentBlocks() const; - - TString MakeName(const TString& name); - - IOutputStream& Error(NYql::TIssueCode code = NYql::TIssuesIds::DEFAULT_ERROR); - IOutputStream& Error(NYql::TPosition pos, NYql::TIssueCode code = NYql::TIssuesIds::DEFAULT_ERROR); - bool Warning(NYql::TPosition pos, NYql::TIssueCode code, std::function<void(IOutputStream&)> message, - bool forceError = false); - IOutputStream& Info(NYql::TPosition pos); - - void SetWarningPolicyFor(NYql::TIssueCode code, NYql::EWarningAction action); - - const TString& Token(const NSQLv1Generated::TToken& token) { - Position_.Row = token.GetLine(); - Position_.Column = token.GetColumn() + 1; - return token.GetValue(); - } + TLocal Local; + + void UseCluster(const TString& service, const TDeferredAtom& cluster); + const TVector<std::pair<TString, TDeferredAtom>>& GetUsedClusters(); + TNodePtr WrapCluster(const TDeferredAtom& cluster, TContext& ctx); + void AddExprCluster(TNodePtr expr, TContext& ctx); + void Clear(); + TNodePtr LookupNode(const TString& name); +}; + +using TScopedStatePtr = TIntrusivePtr<TScopedState>; + +class TColumnRefScope; +enum class EColumnRefState { + Deny, + Allow, + AsStringLiteral, + AsPgType, + MatchRecognizeMeasures, + MatchRecognizeDefine, + MatchRecognizeDefineAggregate, +}; + +class TContext { +public: + TContext(const TLexers& lexers, + const TParsers& parsers, + const NSQLTranslation::TTranslationSettings& settings, + const NSQLTranslation::TSQLHints& hints, + NYql::TIssues& issues, + const TString& query = {}); + + virtual ~TContext(); + + const NYql::TPosition& Pos() const; + + void PushCurrentBlocks(TBlocks* blocks); + void PopCurrentBlocks(); + TBlocks& GetCurrentBlocks() const; + + TString MakeName(const TString& name); + + IOutputStream& Error(NYql::TIssueCode code = NYql::TIssuesIds::DEFAULT_ERROR); + IOutputStream& Error(NYql::TPosition pos, NYql::TIssueCode code = NYql::TIssuesIds::DEFAULT_ERROR); + bool Warning(NYql::TPosition pos, NYql::TIssueCode code, std::function<void(IOutputStream&)> message, + bool forceError = false); + IOutputStream& Info(NYql::TPosition pos); + + void SetWarningPolicyFor(NYql::TIssueCode code, NYql::EWarningAction action); + + const TString& Token(const NSQLv1Generated::TToken& token) { + Position_.Row = token.GetLine(); + Position_.Column = token.GetColumn() + 1; + return token.GetValue(); + } - TPosition TokenPosition(const NSQLv1Generated::TToken& token) { - TPosition pos = Position_; - pos.Row = token.GetLine(); - pos.Column = token.GetColumn() + 1; - return pos; - } + TPosition TokenPosition(const NSQLv1Generated::TToken& token) { + TPosition pos = Position_; + pos.Row = token.GetLine(); + pos.Column = token.GetColumn() + 1; + return pos; + } - inline void IncrementMonCounter(const TString& name, const TString& value) { - if (IncrementMonCounterFunction) { - IncrementMonCounterFunction(name, value); - } + inline void IncrementMonCounter(const TString& name, const TString& value) { + if (IncrementMonCounterFunction) { + IncrementMonCounterFunction(name, value); } + } - bool HasCluster(const TString& cluster) const { - return GetClusterProvider(cluster).Defined(); - } + bool HasCluster(const TString& cluster) const { + return GetClusterProvider(cluster).Defined(); + } - TMaybe<TString> GetClusterProvider(const TString& cluster) const { - TString unusedNormalizedClusterName; - return GetClusterProvider(cluster, unusedNormalizedClusterName); - } + TMaybe<TString> GetClusterProvider(const TString& cluster) const { + TString unusedNormalizedClusterName; + return GetClusterProvider(cluster, unusedNormalizedClusterName); + } - TMaybe<TString> GetClusterProvider(const TString& cluster, TString& normalizedClusterName) const { - auto provider = ClusterMapping_.GetClusterProvider(cluster, normalizedClusterName); - if (!provider) { - if (Settings.AssumeYdbOnClusterWithSlash && cluster.StartsWith('/')) { - normalizedClusterName = cluster; - return TString(NYql::KikimrProviderName); - } - if (Settings.DynamicClusterProvider) { - normalizedClusterName = cluster.StartsWith('/') ? cluster : Settings.PathPrefix + "/" + cluster; - return Settings.DynamicClusterProvider; - } - return Nothing(); + TMaybe<TString> GetClusterProvider(const TString& cluster, TString& normalizedClusterName) const { + auto provider = ClusterMapping_.GetClusterProvider(cluster, normalizedClusterName); + if (!provider) { + if (Settings.AssumeYdbOnClusterWithSlash && cluster.StartsWith('/')) { + normalizedClusterName = cluster; + return TString(NYql::KikimrProviderName); } - - return provider; + if (Settings.DynamicClusterProvider) { + normalizedClusterName = cluster.StartsWith('/') ? cluster : Settings.PathPrefix + "/" + cluster; + return Settings.DynamicClusterProvider; + } + return Nothing(); } - bool IsDynamicCluster(const TDeferredAtom& cluster) const; - bool HasNonYtProvider(const ISource& source) const; - bool UseUnordered(const ISource& source) const; - bool UseUnordered(const TTableRef& table) const; + return provider; + } - bool SetPathPrefix(const TString& value, TMaybe<TString> arg = TMaybe<TString>()); + bool IsDynamicCluster(const TDeferredAtom& cluster) const; + bool HasNonYtProvider(const ISource& source) const; + bool UseUnordered(const ISource& source) const; + bool UseUnordered(const TTableRef& table) const; - TNodePtr GetPrefixedPath(const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& path); - TStringBuf GetPrefixPath(const TString& service, const TDeferredAtom& cluster) const; + bool SetPathPrefix(const TString& value, TMaybe<TString> arg = TMaybe<TString>()); - TNodePtr UniversalAlias(const TString& baseName, TNodePtr&& node); + TNodePtr GetPrefixedPath(const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& path); + TStringBuf GetPrefixPath(const TString& service, const TDeferredAtom& cluster) const; - void BodyPart() { - IntoHeading_ = false; - } + TNodePtr UniversalAlias(const TString& baseName, TNodePtr&& node); - bool IsParseHeading() const { - return IntoHeading_; - } + void BodyPart() { + IntoHeading_ = false; + } - bool IsAlreadyDeclared(const TString& varName) const; - void DeclareVariable(const TString& varName, const TPosition& pos, const TNodePtr& typeNode, bool isWeak = false); + bool IsParseHeading() const { + return IntoHeading_; + } - bool AddExport(TPosition symbolPos, const TString& symbolName); - TString AddImport(const TVector<TString>& modulePath); - TString AddSimpleUdf(const TString& udf); - void SetPackageVersion(const TString& packageName, ui32 version); + bool IsAlreadyDeclared(const TString& varName) const; + void DeclareVariable(const TString& varName, const TPosition& pos, const TNodePtr& typeNode, bool isWeak = false); - bool IsStreamingService(const TStringBuf service) const; + bool AddExport(TPosition symbolPos, const TString& symbolName); + TString AddImport(const TVector<TString>& modulePath); + TString AddSimpleUdf(const TString& udf); + void SetPackageVersion(const TString& packageName, ui32 version); - bool CheckColumnReference(TPosition pos, const TString& name) { - const bool allowed = GetColumnReferenceState() != EColumnRefState::Deny; - if (!allowed) { - Error(pos) << "Column reference \"" << name << "\" is not allowed " << NoColumnErrorContext_; - IncrementMonCounter("sql_errors", "ColumnReferenceInScopeIsNotAllowed"); - } - return allowed; - } + bool IsStreamingService(const TStringBuf service) const; - EColumnRefState GetColumnReferenceState() const { - return ColumnReferenceState_; + bool CheckColumnReference(TPosition pos, const TString& name) { + const bool allowed = GetColumnReferenceState() != EColumnRefState::Deny; + if (!allowed) { + Error(pos) << "Column reference \"" << name << "\" is not allowed " << NoColumnErrorContext_; + IncrementMonCounter("sql_errors", "ColumnReferenceInScopeIsNotAllowed"); } + return allowed; + } - EColumnRefState GetTopLevelColumnReferenceState() const { - return TopLevelColumnReferenceState_; - } + EColumnRefState GetColumnReferenceState() const { + return ColumnReferenceState_; + } - [[nodiscard]] TString GetMatchRecognizeDefineVar() const { - YQL_ENSURE(EColumnRefState::MatchRecognizeMeasures == ColumnReferenceState_ - || EColumnRefState::MatchRecognizeDefine == ColumnReferenceState_ - || EColumnRefState::MatchRecognizeDefineAggregate == ColumnReferenceState_, - "MATCH_RECOGNIZE Var can only be accessed within processing of MATCH_RECOGNIZE lambdas"); - return MatchRecognizeDefineVar_; - } + EColumnRefState GetTopLevelColumnReferenceState() const { + return TopLevelColumnReferenceState_; + } - TString ExtractMatchRecognizeAggrVar() { - YQL_ENSURE(EColumnRefState::MatchRecognizeMeasures == ColumnReferenceState_ - || EColumnRefState::MatchRecognizeDefine == ColumnReferenceState_ - || EColumnRefState::MatchRecognizeDefineAggregate == ColumnReferenceState_, - "MATCH_RECOGNIZE Var can only be accessed within processing of MATCH_RECOGNIZE lambdas"); - return std::exchange(MatchRecognizeAggrVar_, ""); - } + [[nodiscard]] TString GetMatchRecognizeDefineVar() const { + YQL_ENSURE(EColumnRefState::MatchRecognizeMeasures == ColumnReferenceState_ || + EColumnRefState::MatchRecognizeDefine == ColumnReferenceState_ || + EColumnRefState::MatchRecognizeDefineAggregate == ColumnReferenceState_, + "MATCH_RECOGNIZE Var can only be accessed within processing of MATCH_RECOGNIZE lambdas"); + return MatchRecognizeDefineVar_; + } - [[nodiscard]] bool SetMatchRecognizeAggrVar(TString var) { - YQL_ENSURE(EColumnRefState::MatchRecognizeMeasures == ColumnReferenceState_ - || EColumnRefState::MatchRecognizeDefine == ColumnReferenceState_ - || EColumnRefState::MatchRecognizeDefineAggregate == ColumnReferenceState_, - "MATCH_RECOGNIZE Var can only be accessed within processing of MATCH_RECOGNIZE lambdas"); - if (MatchRecognizeAggrVar_.empty()) { - MatchRecognizeAggrVar_ = std::move(var); - } else if (MatchRecognizeAggrVar_ != var) { - Error() << "Illegal use of aggregates or navigation operators in MATCH_RECOGNIZE"; - return false; - } - return true; - } + TString ExtractMatchRecognizeAggrVar() { + YQL_ENSURE(EColumnRefState::MatchRecognizeMeasures == ColumnReferenceState_ || + EColumnRefState::MatchRecognizeDefine == ColumnReferenceState_ || + EColumnRefState::MatchRecognizeDefineAggregate == ColumnReferenceState_, + "MATCH_RECOGNIZE Var can only be accessed within processing of MATCH_RECOGNIZE lambdas"); + return std::exchange(MatchRecognizeAggrVar_, ""); + } - [[nodiscard]] auto& GetMatchRecognizeAggregations() { - YQL_ENSURE(EColumnRefState::MatchRecognizeMeasures == ColumnReferenceState_ - || EColumnRefState::MatchRecognizeDefine == ColumnReferenceState_ - || EColumnRefState::MatchRecognizeDefineAggregate == ColumnReferenceState_, - "MATCH_RECOGNIZE Var can only be accessed within processing of MATCH_RECOGNIZE lambdas"); - return MatchRecognizeAggregations_; + [[nodiscard]] bool SetMatchRecognizeAggrVar(TString var) { + YQL_ENSURE(EColumnRefState::MatchRecognizeMeasures == ColumnReferenceState_ || + EColumnRefState::MatchRecognizeDefine == ColumnReferenceState_ || + EColumnRefState::MatchRecognizeDefineAggregate == ColumnReferenceState_, + "MATCH_RECOGNIZE Var can only be accessed within processing of MATCH_RECOGNIZE lambdas"); + if (MatchRecognizeAggrVar_.empty()) { + MatchRecognizeAggrVar_ = std::move(var); + } else if (MatchRecognizeAggrVar_ != var) { + Error() << "Illegal use of aggregates or navigation operators in MATCH_RECOGNIZE"; + return false; } + return true; + } - TVector<NSQLTranslation::TSQLHint> PullHintForToken(NYql::TPosition tokenPos); - bool WarnUnusedHints(); - - TScopedStatePtr CreateScopedState() const; - - private: - IOutputStream& MakeIssue( - NYql::ESeverity severity, - NYql::TIssueCode code, - NYql::TPosition pos, - bool forceError, - bool& isError); - - public: - const TLexers Lexers; - const TParsers Parsers; - - private: - NYql::TPosition Position_; - THolder<TStringOutput> IssueMsgHolder_; - NSQLTranslation::TClusterMapping ClusterMapping_; - TString PathPrefix_; - THashMap<TString, TString> ProviderPathPrefixes_; - THashMap<TString, TString> ClusterPathPrefixes_; - bool IntoHeading_ = true; - NSQLTranslation::TSQLHints SqlHints_; - - friend class TColumnRefScope; - - EColumnRefState ColumnReferenceState_ = EColumnRefState::Deny; - EColumnRefState TopLevelColumnReferenceState_ = EColumnRefState::Deny; - TString MatchRecognizeDefineVar_; - TString MatchRecognizeAggrVar_; - struct TMatchRecognizeAggregation { - TString Var; - TAggregationPtr Aggr; - }; - TVector<TMatchRecognizeAggregation> MatchRecognizeAggregations_; - TString NoColumnErrorContext_ = "in current scope"; - TVector<TBlocks*> CurrentBlocks_; - - public: - THashMap<TString, std::pair<TPosition, TNodePtr>> Variables; - THashSet<TString> WeakVariables; - NSQLTranslation::TTranslationSettings Settings; - const TString Query; - std::unique_ptr<TMemoryPool> Pool; - NYql::TIssues& Issues; - TMap<TString, TNodePtr> UniversalAliases; - THashSet<TString> Exports; - THashMap<TString, TString> ImportModuleAliases; - THashMap<TString, TString> RequiredModules; - TMap<TString, TString> SimpleUdfs; - NSQLTranslation::TIncrementMonCounterFunction IncrementMonCounterFunction; - TScopedStatePtr Scoped; - int ScopeLevel = 0; - size_t AnonymousNameIndex = 0; - TDeque<TScopedStatePtr> AllScopes; - bool HasPendingErrors; - THashMap<TString, ui32> GenIndexes; - using TWinSpecsRef = std::reference_wrapper<TWinSpecs>; - TDeque<TWinSpecsRef> WinSpecsScopes; - bool PragmaRefSelect = false; - bool PragmaSampleSelect = false; - bool PragmaAllowDotInAlias = false; - bool PragmaInferSchema = false; - bool PragmaAutoCommit = false; - bool PragmaUseTablePrefixForEach = false; - bool SimpleColumns = true; - bool CoalesceJoinKeysOnQualifiedAll = false; - bool PragmaDirectRead = false; - bool PragmaYsonFast = true; - bool PragmaYsonAutoConvert = false; - bool PragmaYsonStrict = true; - bool PragmaRegexUseRe2 = true; - bool PragmaPullUpFlatMapOverJoin = true; - bool FilterPushdownOverJoinOptionalSide = false; - bool RotateJoinTree = true; - bool WarnUnnamedColumns = false; - bool DiscoveryMode = false; - bool ExceptIntersectBefore202503 = true; // TODO(YQL-20367) - bool EnableSystemColumns = true; - bool DqEngineEnable = false; - bool DqEngineForce = false; - TString CostBasedOptimizer; - TMaybe<bool> JsonQueryReturnsJsonDocument; - TMaybe<bool> AnsiInForEmptyOrNullableItemsCollections; - TMaybe<bool> AnsiRankForNullableKeys = true; - const bool AnsiQuotedIdentifiers; - bool AnsiOptionalAs = true; - bool OrderedColumns = false; - bool DeriveColumnOrder = false; - bool PositionalUnionAll = false; - bool BogousStarInGroupByOverJoin = false; - bool UnorderedSubqueries = true; - bool PragmaDataWatermarks = true; - bool WarnOnAnsiAliasShadowing = true; - ui32 ResultRowsLimit = 0; - ui64 ResultSizeLimit = 0; - TString RuntimeLogLevel; - ui32 PragmaGroupByLimit = 1 << 6; - ui32 PragmaGroupByCubeLimit = 5; - // if FlexibleTypes=true, emit TypeOrMember callable and resolve Type/Column uncertainty on type annotation stage, otherwise always emit Type - bool FlexibleTypes = true; - // see YQL-10265 - bool AnsiCurrentRow = false; - TMaybe<bool> YsonCastToString; - using TLiteralWithPosition = std::pair<TString, TPosition>; - using TLibraryStuff = std::tuple<TPosition, std::optional<TLiteralWithPosition>, std::optional<TLiteralWithPosition>>; - std::unordered_map<TString, TLibraryStuff> Libraries; // alias -> optional file with token - using TPackageStuff = std::tuple< - TPosition, TLiteralWithPosition, - std::optional<TLiteralWithPosition> - >; - - std::unordered_map<TString, TPackageStuff> Packages; // alias -> url with optional token - - using TOverrideLibraryStuff = std::tuple<TPosition>; - std::unordered_map<TString, TOverrideLibraryStuff> OverrideLibraries; // alias -> position - - THashMap<TString, ui32> PackageVersions; - NYql::TWarningPolicy WarningPolicy; - TString PqReadByRtmrCluster; - bool EmitStartsWith = true; - TMaybe<bool> EmitAggApply; - bool UseBlocks = false; - bool EmitTableSource = false; - bool AnsiLike = false; - bool FeatureR010 = false; //Row pattern recognition: FROM clause - TMaybe<bool> CompactGroupBy; - bool BlockEngineEnable = false; - bool BlockEngineForce = false; - bool UnorderedResult = false; - ui64 ParallelModeCount = 0; - bool CompactNamedExprs = true; - bool ValidateUnusedExprs = false; - bool AnsiImplicitCrossJoin = false; // select * from A,B - bool DistinctOverWindow = false; - bool SeqMode = false; - bool DistinctOverKeys = false; - bool GroupByExprAfterWhere = false; - bool FailOnGroupByExprOverride = false; - bool EmitUnionMerge = false; - bool OptimizeSimpleIlike = false; - bool PersistableFlattenAndAggrExprs = false; - bool DisableLegacyNotNull = false; - bool DebugPositions = false; - bool StrictWarningAsError = false; - TMaybe<bool> DirectRowDependsOn; - TVector<size_t> ForAllStatementsParts; - - TMaybe<TString> Engine; - }; + [[nodiscard]] auto& GetMatchRecognizeAggregations() { + YQL_ENSURE(EColumnRefState::MatchRecognizeMeasures == ColumnReferenceState_ || + EColumnRefState::MatchRecognizeDefine == ColumnReferenceState_ || + EColumnRefState::MatchRecognizeDefineAggregate == ColumnReferenceState_, + "MATCH_RECOGNIZE Var can only be accessed within processing of MATCH_RECOGNIZE lambdas"); + return MatchRecognizeAggregations_; + } - class TColumnRefScope { - public: - TColumnRefScope(TContext& ctx, EColumnRefState state, bool isTopLevelExpr = true, const TString& defineVar = "") - : PrevTop_(ctx.TopLevelColumnReferenceState_) - , Prev_(ctx.ColumnReferenceState_) - , PrevErr_(ctx.NoColumnErrorContext_) - , PrevDefineVar_(ctx.MatchRecognizeDefineVar_) - , Ctx_(ctx) - { - if (isTopLevelExpr) { - Ctx_.ColumnReferenceState_ = Ctx_.TopLevelColumnReferenceState_ = state; - } else { - Ctx_.ColumnReferenceState_ = state; - } - YQL_ENSURE( - defineVar.empty() - || EColumnRefState::MatchRecognizeMeasures == state - || EColumnRefState::MatchRecognizeDefine == state - || EColumnRefState::MatchRecognizeDefineAggregate == state, - "Internal logic error" - ); - ctx.MatchRecognizeDefineVar_ = defineVar; + TVector<NSQLTranslation::TSQLHint> PullHintForToken(NYql::TPosition tokenPos); + bool WarnUnusedHints(); + + TScopedStatePtr CreateScopedState() const; + +private: + IOutputStream& MakeIssue( + NYql::ESeverity severity, + NYql::TIssueCode code, + NYql::TPosition pos, + bool forceError, + bool& isError); + +public: + const TLexers Lexers; + const TParsers Parsers; + +private: + NYql::TPosition Position_; + THolder<TStringOutput> IssueMsgHolder_; + NSQLTranslation::TClusterMapping ClusterMapping_; + TString PathPrefix_; + THashMap<TString, TString> ProviderPathPrefixes_; + THashMap<TString, TString> ClusterPathPrefixes_; + bool IntoHeading_ = true; + NSQLTranslation::TSQLHints SqlHints_; + + friend class TColumnRefScope; + + EColumnRefState ColumnReferenceState_ = EColumnRefState::Deny; + EColumnRefState TopLevelColumnReferenceState_ = EColumnRefState::Deny; + TString MatchRecognizeDefineVar_; + TString MatchRecognizeAggrVar_; + struct TMatchRecognizeAggregation { + TString Var; + TAggregationPtr Aggr; + }; + TVector<TMatchRecognizeAggregation> MatchRecognizeAggregations_; + TString NoColumnErrorContext_ = "in current scope"; + TVector<TBlocks*> CurrentBlocks_; + +public: + THashMap<TString, std::pair<TPosition, TNodePtr>> Variables; + THashSet<TString> WeakVariables; + NSQLTranslation::TTranslationSettings Settings; + const TString Query; + std::unique_ptr<TMemoryPool> Pool; + NYql::TIssues& Issues; + TMap<TString, TNodePtr> UniversalAliases; + THashSet<TString> Exports; + THashMap<TString, TString> ImportModuleAliases; + THashMap<TString, TString> RequiredModules; + TMap<TString, TString> SimpleUdfs; + NSQLTranslation::TIncrementMonCounterFunction IncrementMonCounterFunction; + TScopedStatePtr Scoped; + int ScopeLevel = 0; + size_t AnonymousNameIndex = 0; + TDeque<TScopedStatePtr> AllScopes; + bool HasPendingErrors; + THashMap<TString, ui32> GenIndexes; + using TWinSpecsRef = std::reference_wrapper<TWinSpecs>; + TDeque<TWinSpecsRef> WinSpecsScopes; + bool PragmaRefSelect = false; + bool PragmaSampleSelect = false; + bool PragmaAllowDotInAlias = false; + bool PragmaInferSchema = false; + bool PragmaAutoCommit = false; + bool PragmaUseTablePrefixForEach = false; + bool SimpleColumns = true; + bool CoalesceJoinKeysOnQualifiedAll = false; + bool PragmaDirectRead = false; + bool PragmaYsonFast = true; + bool PragmaYsonAutoConvert = false; + bool PragmaYsonStrict = true; + bool PragmaRegexUseRe2 = true; + bool PragmaPullUpFlatMapOverJoin = true; + bool FilterPushdownOverJoinOptionalSide = false; + bool RotateJoinTree = true; + bool WarnUnnamedColumns = false; + bool DiscoveryMode = false; + bool ExceptIntersectBefore202503 = true; // TODO(YQL-20367) + bool EnableSystemColumns = true; + bool DqEngineEnable = false; + bool DqEngineForce = false; + TString CostBasedOptimizer; + TMaybe<bool> JsonQueryReturnsJsonDocument; + TMaybe<bool> AnsiInForEmptyOrNullableItemsCollections; + TMaybe<bool> AnsiRankForNullableKeys = true; + const bool AnsiQuotedIdentifiers; + bool AnsiOptionalAs = true; + bool OrderedColumns = false; + bool DeriveColumnOrder = false; + bool PositionalUnionAll = false; + bool BogousStarInGroupByOverJoin = false; + bool UnorderedSubqueries = true; + bool PragmaDataWatermarks = true; + bool WarnOnAnsiAliasShadowing = true; + ui32 ResultRowsLimit = 0; + ui64 ResultSizeLimit = 0; + TString RuntimeLogLevel; + ui32 PragmaGroupByLimit = 1 << 6; + ui32 PragmaGroupByCubeLimit = 5; + // if FlexibleTypes=true, emit TypeOrMember callable and resolve Type/Column uncertainty on type annotation stage, otherwise always emit Type + bool FlexibleTypes = true; + // see YQL-10265 + bool AnsiCurrentRow = false; + TMaybe<bool> YsonCastToString; + using TLiteralWithPosition = std::pair<TString, TPosition>; + using TLibraryStuff = std::tuple<TPosition, std::optional<TLiteralWithPosition>, std::optional<TLiteralWithPosition>>; + std::unordered_map<TString, TLibraryStuff> Libraries; // alias -> optional file with token + using TPackageStuff = std::tuple< + TPosition, TLiteralWithPosition, + std::optional<TLiteralWithPosition>>; + + std::unordered_map<TString, TPackageStuff> Packages; // alias -> url with optional token + + using TOverrideLibraryStuff = std::tuple<TPosition>; + std::unordered_map<TString, TOverrideLibraryStuff> OverrideLibraries; // alias -> position + + THashMap<TString, ui32> PackageVersions; + NYql::TWarningPolicy WarningPolicy; + TString PqReadByRtmrCluster; + bool EmitStartsWith = true; + TMaybe<bool> EmitAggApply; + bool UseBlocks = false; + bool EmitTableSource = false; + bool AnsiLike = false; + bool FeatureR010 = false; // Row pattern recognition: FROM clause + TMaybe<bool> CompactGroupBy; + bool BlockEngineEnable = false; + bool BlockEngineForce = false; + bool UnorderedResult = false; + ui64 ParallelModeCount = 0; + bool CompactNamedExprs = true; + bool ValidateUnusedExprs = false; + bool AnsiImplicitCrossJoin = false; // select * from A,B + bool DistinctOverWindow = false; + bool SeqMode = false; + bool DistinctOverKeys = false; + bool GroupByExprAfterWhere = false; + bool FailOnGroupByExprOverride = false; + bool EmitUnionMerge = false; + bool OptimizeSimpleIlike = false; + bool PersistableFlattenAndAggrExprs = false; + bool DisableLegacyNotNull = false; + bool DebugPositions = false; + bool StrictWarningAsError = false; + TMaybe<bool> DirectRowDependsOn; + TVector<size_t> ForAllStatementsParts; + + TMaybe<TString> Engine; +}; + +class TColumnRefScope { +public: + TColumnRefScope(TContext& ctx, EColumnRefState state, bool isTopLevelExpr = true, const TString& defineVar = "") + : PrevTop_(ctx.TopLevelColumnReferenceState_) + , Prev_(ctx.ColumnReferenceState_) + , PrevErr_(ctx.NoColumnErrorContext_) + , PrevDefineVar_(ctx.MatchRecognizeDefineVar_) + , Ctx_(ctx) + { + if (isTopLevelExpr) { + Ctx_.ColumnReferenceState_ = Ctx_.TopLevelColumnReferenceState_ = state; + } else { + Ctx_.ColumnReferenceState_ = state; } + YQL_ENSURE( + defineVar.empty() || + EColumnRefState::MatchRecognizeMeasures == state || + EColumnRefState::MatchRecognizeDefine == state || + EColumnRefState::MatchRecognizeDefineAggregate == state, + "Internal logic error"); + ctx.MatchRecognizeDefineVar_ = defineVar; + } - void SetNoColumnErrContext(const TString& msg) { - Ctx_.NoColumnErrorContext_ = msg; - } + void SetNoColumnErrContext(const TString& msg) { + Ctx_.NoColumnErrorContext_ = msg; + } - ~TColumnRefScope() { - Ctx_.TopLevelColumnReferenceState_ = PrevTop_; - Ctx_.ColumnReferenceState_ = Prev_; - std::swap(Ctx_.NoColumnErrorContext_, PrevErr_); - std::swap(Ctx_.MatchRecognizeDefineVar_, PrevDefineVar_); - } - private: - const EColumnRefState PrevTop_; - const EColumnRefState Prev_; - TString PrevErr_; - TString PrevDefineVar_; - TContext& Ctx_; - }; + ~TColumnRefScope() { + Ctx_.TopLevelColumnReferenceState_ = PrevTop_; + Ctx_.ColumnReferenceState_ = Prev_; + std::swap(Ctx_.NoColumnErrorContext_, PrevErr_); + std::swap(Ctx_.MatchRecognizeDefineVar_, PrevDefineVar_); + } - TMaybe<EColumnRefState> GetFunctionArgColumnStatus(TContext& ctx, const TString& module, const TString& func, size_t argIndex); +private: + const EColumnRefState PrevTop_; + const EColumnRefState Prev_; + TString PrevErr_; + TString PrevDefineVar_; + TContext& Ctx_; +}; - class TTranslation { - protected: - typedef TSet<ui32> TSetType; +TMaybe<EColumnRefState> GetFunctionArgColumnStatus(TContext& ctx, const TString& module, const TString& func, size_t argIndex); - protected: - TTranslation(TContext& ctx); +class TTranslation { +protected: + typedef TSet<ui32> TSetType; - public: - TContext& Context(); - IOutputStream& Error(); +protected: + TTranslation(TContext& ctx); - const TString& Token(const NSQLv1Generated::TToken& token) { - return Ctx_.Token(token); - } +public: + TContext& Context(); + IOutputStream& Error(); - TString Identifier(const NSQLv1Generated::TToken& token) { - return IdContent(Ctx_, Token(token)); - } + const TString& Token(const NSQLv1Generated::TToken& token) { + return Ctx_.Token(token); + } - TString Identifier(const TString& str) const { - return IdContent(Ctx_, str); - } + TString Identifier(const NSQLv1Generated::TToken& token) { + return IdContent(Ctx_, Token(token)); + } - TNodePtr GetNamedNode(const TString& name); + TString Identifier(const TString& str) const { + return IdContent(Ctx_, str); + } - using TNodeBuilderByName = std::function<TNodePtr(const TString& effectiveName)>; - TString PushNamedNode(TPosition namePos, const TString& name, const TNodeBuilderByName& builder); - TString PushNamedNode(TPosition namePos, const TString& name, TNodePtr node); - TString PushNamedAtom(TPosition namePos, const TString& name); - bool PopNamedNode(const TString& name); - bool WarnUnusedNodes() const; + TNodePtr GetNamedNode(const TString& name); - template <typename TNode> - void AltNotImplemented(const TString& ruleName, const TNode& node) { - AltNotImplemented(ruleName, node.Alt_case(), node, TNode::descriptor()); - } + using TNodeBuilderByName = std::function<TNodePtr(const TString& effectiveName)>; + TString PushNamedNode(TPosition namePos, const TString& name, const TNodeBuilderByName& builder); + TString PushNamedNode(TPosition namePos, const TString& name, TNodePtr node); + TString PushNamedAtom(TPosition namePos, const TString& name); + bool PopNamedNode(const TString& name); + bool WarnUnusedNodes() const; - template <typename TNode> - TString AltDescription(const TNode& node) const { - return AltDescription(node, node.Alt_case(), TNode::descriptor()); - } + template <typename TNode> + void AltNotImplemented(const TString& ruleName, const TNode& node) { + AltNotImplemented(ruleName, node.Alt_case(), node, TNode::descriptor()); + } + + template <typename TNode> + TString AltDescription(const TNode& node) const { + return AltDescription(node, node.Alt_case(), TNode::descriptor()); + } - protected: - void AltNotImplemented(const TString& ruleName, ui32 altCase, const google::protobuf::Message& node, const google::protobuf::Descriptor* descr); - TString AltDescription(const google::protobuf::Message& node, ui32 altCase, const google::protobuf::Descriptor* descr) const; +protected: + void AltNotImplemented(const TString& ruleName, ui32 altCase, const google::protobuf::Message& node, const google::protobuf::Descriptor* descr); + TString AltDescription(const google::protobuf::Message& node, ui32 altCase, const google::protobuf::Descriptor* descr) const; - bool IsBackwardCompatibleFeatureAvailable(NYql::TLangVersion langVer) const; + bool IsBackwardCompatibleFeatureAvailable(NYql::TLangVersion langVer) const; - protected: - TContext& Ctx_; - }; +protected: + TContext& Ctx_; +}; - void EnumerateSqlFlags(std::function<void(std::string_view)> callback); -} // namespace NSQLTranslationV1 +void EnumerateSqlFlags(std::function<void(std::string_view)> callback); +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/format/sql_format.cpp b/yql/essentials/sql/v1/format/sql_format.cpp index d76b64df3b7..aed116585a6 100644 --- a/yql/essentials/sql/v1/format/sql_format.cpp +++ b/yql/essentials/sql/v1/format/sql_format.cpp @@ -16,7 +16,6 @@ #include <util/string/subst.h> #include <util/generic/hash_set.h> - namespace NSQLFormat { namespace { @@ -54,8 +53,7 @@ void SkipForValidate( TTokenIterator& out, const TParsedTokenList& query, const TParsedTokenList& formattedQuery, - i32& parenthesesBalance -) { + i32& parenthesesBalance) { in = SkipWS(in, query.end()); out = SkipWS(out, formattedQuery.end()); @@ -66,8 +64,7 @@ void SkipForValidate( out != formattedQuery.end() && out->Name == addedToken && (in == query.end() || in->Name != addedToken) && (beforeTokens.empty() || (inSkippedComments != query.end() && IsIn(beforeTokens, inSkippedComments->Name))) && - (afterTokens.empty() || (in != query.begin() && IsIn(afterTokens, SkipWSOrCommentBackward(in - 1, query.begin())->Name))) - ) { + (afterTokens.empty() || (in != query.begin() && IsIn(afterTokens, SkipWSOrCommentBackward(in - 1, query.begin())->Name)))) { out = SkipWS(++out, formattedQuery.end()); if (addedToken == "LPAREN") { ++parenthesesBalance; @@ -85,15 +82,15 @@ void SkipForValidate( if ( in != query.end() && in->Name == deletedToken && (out == formattedQuery.end() || out->Name != deletedToken) && - in != query.begin() && IsIn(afterTokens, SkipWSOrCommentBackward(in - 1, query.begin())->Name) - ) { + in != query.begin() && IsIn(afterTokens, SkipWSOrCommentBackward(in - 1, query.begin())->Name)) { in = SkipWS(++in, query.end()); return true; } return false; }; - while (skipDeletedToken("SEMICOLON", {"AS", "BEGIN", "LBRACE_CURLY", "SEMICOLON"})) {} + while (skipDeletedToken("SEMICOLON", {"AS", "BEGIN", "LBRACE_CURLY", "SEMICOLON"})) { + } } TParsedToken TransformTokenForValidate(TParsedToken token) { @@ -202,11 +199,13 @@ void VisitAllFieldsImpl(T* obj, const NProtoBuf::Descriptor* descr, const NProto } class TObfuscatingVisitor { -friend struct TStaticData; + friend struct TStaticData; + public: TObfuscatingVisitor() : StaticData_(TStaticData::GetInstance()) - {} + { + } TString Process(const NProtoBuf::Message& msg) { Scopes_.push_back(EScope::Default); @@ -247,42 +246,42 @@ private: void VisitPragmaValue(const TRule_pragma_value& msg) { switch (msg.Alt_case()) { - case TRule_pragma_value::kAltPragmaValue1: { - NextToken_ = "0"; - break; - } - case TRule_pragma_value::kAltPragmaValue3: { - NextToken_ = "'str'"; - break; - } - case TRule_pragma_value::kAltPragmaValue4: { - NextToken_ = "false"; - break; - } - default:; + case TRule_pragma_value::kAltPragmaValue1: { + NextToken_ = "0"; + break; + } + case TRule_pragma_value::kAltPragmaValue3: { + NextToken_ = "'str'"; + break; + } + case TRule_pragma_value::kAltPragmaValue4: { + NextToken_ = "false"; + break; + } + default:; } VisitAllFields(TRule_pragma_value::GetDescriptor(), msg); } void VisitLiteralValue(const TRule_literal_value& msg) { switch (msg.Alt_case()) { - case TRule_literal_value::kAltLiteralValue1: { - NextToken_ = "0"; - break; - } - case TRule_literal_value::kAltLiteralValue2: { - NextToken_ = "0.0"; - break; - } - case TRule_literal_value::kAltLiteralValue3: { - NextToken_ = "'str'"; - break; - } - case TRule_literal_value::kAltLiteralValue9: { - NextToken_ = "false"; - break; - } - default:; + case TRule_literal_value::kAltLiteralValue1: { + NextToken_ = "0"; + break; + } + case TRule_literal_value::kAltLiteralValue2: { + NextToken_ = "0.0"; + break; + } + case TRule_literal_value::kAltLiteralValue3: { + NextToken_ = "'str'"; + break; + } + case TRule_literal_value::kAltLiteralValue9: { + NextToken_ = "false"; + break; + } + default:; } VisitAllFields(TRule_literal_value::GetDescriptor(), msg); @@ -290,11 +289,11 @@ private: void VisitAtomExpr(const TRule_atom_expr& msg) { switch (msg.Alt_case()) { - case TRule_atom_expr::kAltAtomExpr7: { - FuncCall_ = true; - break; - } - default:; + case TRule_atom_expr::kAltAtomExpr7: { + FuncCall_ = true; + break; + } + default:; } VisitAllFields(TRule_atom_expr::GetDescriptor(), msg); @@ -303,11 +302,11 @@ private: void VisitInAtomExpr(const TRule_in_atom_expr& msg) { switch (msg.Alt_case()) { - case TRule_in_atom_expr::kAltInAtomExpr6: { - FuncCall_ = true; - break; - } - default:; + case TRule_in_atom_expr::kAltInAtomExpr6: { + FuncCall_ = true; + break; + } + default:; } VisitAllFields(TRule_in_atom_expr::GetDescriptor(), msg); @@ -318,11 +317,11 @@ private: bool invoke = false; for (auto& b : msg.GetRule_unary_subexpr_suffix2().GetBlock1()) { switch (b.GetBlock1().Alt_case()) { - case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt2: { - invoke = true; - break; - } - default:; + case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt2: { + invoke = true; + break; + } + default:; } break; @@ -344,11 +343,11 @@ private: bool invoke = false; for (auto& b : msg.GetRule_unary_subexpr_suffix2().GetBlock1()) { switch (b.GetBlock1().Alt_case()) { - case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt2: { - invoke = true; - break; - } - default:; + case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt2: { + invoke = true; + break; + } + default:; } break; @@ -398,7 +397,8 @@ private: }; class TPrettyVisitor { -friend struct TStaticData; + friend struct TStaticData; + public: TPrettyVisitor(const TParsedTokenList& parsedTokens, const TParsedTokenList& comments, bool ansiLexer) : StaticData_(TStaticData::GetInstance()) @@ -508,8 +508,7 @@ private: if (!text.StartsWith("--") && TokenIndex_ < ParsedTokens_.size() && Comments_[LastComment_].Line < ParsedTokens_[TokenIndex_].Line && - (LastComment_ + 1 >= Comments_.size() || Comments_[LastComment_].Line < Comments_[LastComment_ + 1].Line) - ) { + (LastComment_ + 1 >= Comments_.size() || Comments_[LastComment_].Line < Comments_[LastComment_ + 1].Line)) { Out('\n'); } } @@ -660,7 +659,7 @@ private: void Visit(const NProtoBuf::Message& msg) { const NProtoBuf::Descriptor* descr = msg.GetDescriptor(); - //Cerr << descr->name() << "\n"; + // Cerr << descr->name() << "\n"; auto scopePtr = StaticData_.ScopeDispatch.FindPtr(descr); if (descr == TRule_invoke_expr::GetDescriptor()) { AfterInvokeExpr_ = true; @@ -696,10 +695,10 @@ private: TMaybe<bool> IsSimpleStatement(const TRule_sql_stmt_core& msg) { switch (msg.Alt_case()) { - case TRule_sql_stmt_core::kAltSqlStmtCore1: // pragma - case TRule_sql_stmt_core::kAltSqlStmtCore5: // drop table - case TRule_sql_stmt_core::kAltSqlStmtCore6: // use - case TRule_sql_stmt_core::kAltSqlStmtCore8: // commit + case TRule_sql_stmt_core::kAltSqlStmtCore1: // pragma + case TRule_sql_stmt_core::kAltSqlStmtCore5: // drop table + case TRule_sql_stmt_core::kAltSqlStmtCore6: // use + case TRule_sql_stmt_core::kAltSqlStmtCore8: // commit case TRule_sql_stmt_core::kAltSqlStmtCore11: // rollback case TRule_sql_stmt_core::kAltSqlStmtCore12: // declare case TRule_sql_stmt_core::kAltSqlStmtCore13: // import @@ -714,10 +713,9 @@ private: case TRule_sql_stmt_core::kAltSqlStmtCore3: { // named nodes const auto& stmt = msg.GetAlt_sql_stmt_core3().GetRule_named_nodes_stmt1(); - const bool isSelect = ( - (stmt.GetBlock3().HasAlt1() && - IsSelect(stmt.GetBlock3().GetAlt1().GetRule_expr1())) || - (stmt.GetBlock3().HasAlt2())); + const bool isSelect = ((stmt.GetBlock3().HasAlt1() && + IsSelect(stmt.GetBlock3().GetAlt1().GetRule_expr1())) || + (stmt.GetBlock3().HasAlt2())); if (!isSelect) { return true; @@ -937,26 +935,26 @@ private: ExprLineIndent_ = CurrentIndent_; switch (msg.GetBlock3().Alt_case()) { - case TRule_named_nodes_stmt::TBlock3::kAlt1: { - const auto& alt = msg.GetBlock3().GetAlt1(); - Visit(alt); - break; - } + case TRule_named_nodes_stmt::TBlock3::kAlt1: { + const auto& alt = msg.GetBlock3().GetAlt1(); + Visit(alt); + break; + } - case TRule_named_nodes_stmt::TBlock3::kAlt2: { - const auto& alt = msg.GetBlock3().GetAlt2(); - Out(" ("); - NewLine(); - PushCurrentIndent(); - Visit(alt); - PopCurrentIndent(); - NewLine(); - Out(')'); - break; - } + case TRule_named_nodes_stmt::TBlock3::kAlt2: { + const auto& alt = msg.GetBlock3().GetAlt2(); + Out(" ("); + NewLine(); + PushCurrentIndent(); + Visit(alt); + PopCurrentIndent(); + NewLine(); + Out(')'); + break; + } - default: - ythrow yexception() << "Alt is not supported"; + default: + ythrow yexception() << "Alt is not supported"; } ExprLineIndent_ = 0; @@ -1081,107 +1079,106 @@ private: Visit(msg.GetToken2()); Visit(msg.GetRule_simple_table_ref3()); switch (msg.GetBlock4().Alt_case()) { - case TRule_update_stmt_TBlock4::kAlt1: { - const auto& alt = msg.GetBlock4().GetAlt1(); - NewLine(); - Visit(alt.GetToken1()); - const auto& choice = alt.GetRule_set_clause_choice2(); - NewLine(); - - switch (choice.Alt_case()) { - case TRule_set_clause_choice::kAltSetClauseChoice1: { - const auto& clauses = choice.GetAlt_set_clause_choice1().GetRule_set_clause_list1(); - NewLine(); - PushCurrentIndent(); - Visit(clauses.GetRule_set_clause1()); - for (auto& block : clauses.GetBlock2()) { - Visit(block.GetToken1()); - NewLine(); - Visit(block.GetRule_set_clause2()); - } - - PopCurrentIndent(); + case TRule_update_stmt_TBlock4::kAlt1: { + const auto& alt = msg.GetBlock4().GetAlt1(); NewLine(); - break; - } - case TRule_set_clause_choice::kAltSetClauseChoice2: { - const auto& multiColumn = choice.GetAlt_set_clause_choice2().GetRule_multiple_column_assignment1(); - const auto& targets = multiColumn.GetRule_set_target_list1(); - Visit(targets.GetToken1()); + Visit(alt.GetToken1()); + const auto& choice = alt.GetRule_set_clause_choice2(); NewLine(); - PushCurrentIndent(); - Visit(targets.GetRule_set_target2()); - for (auto& block : targets.GetBlock3()) { - Visit(block.GetToken1()); - NewLine(); - Visit(block.GetRule_set_target2()); - } - NewLine(); - PopCurrentIndent(); - Visit(targets.GetToken4()); - Visit(multiColumn.GetToken2()); - - const auto& parenthesis = multiColumn.GetRule_smart_parenthesis3(); + switch (choice.Alt_case()) { + case TRule_set_clause_choice::kAltSetClauseChoice1: { + const auto& clauses = choice.GetAlt_set_clause_choice1().GetRule_set_clause_list1(); + NewLine(); + PushCurrentIndent(); + Visit(clauses.GetRule_set_clause1()); + for (auto& block : clauses.GetBlock2()) { + Visit(block.GetToken1()); + NewLine(); + Visit(block.GetRule_set_clause2()); + } + + PopCurrentIndent(); + NewLine(); + break; + } + case TRule_set_clause_choice::kAltSetClauseChoice2: { + const auto& multiColumn = choice.GetAlt_set_clause_choice2().GetRule_multiple_column_assignment1(); + const auto& targets = multiColumn.GetRule_set_target_list1(); + Visit(targets.GetToken1()); + NewLine(); + PushCurrentIndent(); + Visit(targets.GetRule_set_target2()); + for (auto& block : targets.GetBlock3()) { + Visit(block.GetToken1()); + NewLine(); + Visit(block.GetRule_set_target2()); + } - const auto* tuple_or_expr = GetTupleOrExpr(parenthesis); - if (!tuple_or_expr) { - Visit(parenthesis); - break; - } + NewLine(); + PopCurrentIndent(); + Visit(targets.GetToken4()); + Visit(multiColumn.GetToken2()); + + const auto& parenthesis = multiColumn.GetRule_smart_parenthesis3(); + + const auto* tuple_or_expr = GetTupleOrExpr(parenthesis); + if (!tuple_or_expr) { + Visit(parenthesis); + break; + } + + const bool isHeadNamed = tuple_or_expr->HasBlock2(); + const bool isTailNamed = AnyOf(tuple_or_expr->GetBlock3(), [](const auto& block) { + return block.GetRule_named_expr2().HasBlock2(); + }); + if (isHeadNamed || isTailNamed) { + Visit(parenthesis); + break; + } + + Visit(parenthesis.GetToken1()); + PushCurrentIndent(); + NewLine(); - const bool isHeadNamed = tuple_or_expr->HasBlock2(); - const bool isTailNamed = AnyOf(tuple_or_expr->GetBlock3(), [](const auto& block) { - return block.GetRule_named_expr2().HasBlock2(); - }); - if (isHeadNamed || isTailNamed) { - Visit(parenthesis); - break; - } + Visit(tuple_or_expr->GetRule_expr1()); + for (auto& block : tuple_or_expr->GetBlock3()) { + Visit(block.GetToken1()); + NewLine(); + Visit(block.GetRule_named_expr2().GetRule_expr1()); + } + if (tuple_or_expr->HasBlock4()) { + Visit(tuple_or_expr->GetBlock4().GetToken1()); + } + NewLine(); + PopCurrentIndent(); + Visit(parenthesis.GetToken3()); - Visit(parenthesis.GetToken1()); - PushCurrentIndent(); - NewLine(); + break; + } + default: + ythrow yexception() << "Alt is not supported"; + } - Visit(tuple_or_expr->GetRule_expr1()); - for (auto& block : tuple_or_expr->GetBlock3()) { - Visit(block.GetToken1()); + PopCurrentIndent(); + if (alt.HasBlock3()) { NewLine(); - Visit(block.GetRule_named_expr2().GetRule_expr1()); - } - if (tuple_or_expr->HasBlock4()) { - Visit(tuple_or_expr->GetBlock4().GetToken1()); + Visit(alt.GetBlock3()); } - NewLine(); PopCurrentIndent(); - Visit(parenthesis.GetToken3()); - break; } - default: - ythrow yexception() << "Alt is not supported"; - } - - PopCurrentIndent(); - if (alt.HasBlock3()) { + case TRule_update_stmt_TBlock4::kAlt2: { + const auto& alt = msg.GetBlock4().GetAlt2(); NewLine(); - Visit(alt.GetBlock3()); + Visit(alt.GetToken1()); + Visit(alt.GetRule_into_values_source2()); + break; } - - PopCurrentIndent(); - break; - } - case TRule_update_stmt_TBlock4::kAlt2: { - const auto& alt = msg.GetBlock4().GetAlt2(); - NewLine(); - Visit(alt.GetToken1()); - Visit(alt.GetRule_into_values_source2()); - break; - } - default: - ythrow yexception() << "Alt is not supported"; + default: + ythrow yexception() << "Alt is not supported"; } } @@ -1192,20 +1189,20 @@ private: Visit(msg.GetRule_simple_table_ref4()); if (msg.HasBlock5()) { switch (msg.GetBlock5().Alt_case()) { - case TRule_delete_stmt_TBlock5::kAlt1: { - const auto& alt = msg.GetBlock5().GetAlt1(); - NewLine(); - Visit(alt); - break; - } - case TRule_delete_stmt_TBlock5::kAlt2: { - const auto& alt = msg.GetBlock5().GetAlt2(); - NewLine(); - Visit(alt); - break; - } - default: - ythrow yexception() << "Alt is not supported"; + case TRule_delete_stmt_TBlock5::kAlt1: { + const auto& alt = msg.GetBlock5().GetAlt1(); + NewLine(); + Visit(alt); + break; + } + case TRule_delete_stmt_TBlock5::kAlt2: { + const auto& alt = msg.GetBlock5().GetAlt2(); + NewLine(); + Visit(alt); + break; + } + default: + ythrow yexception() << "Alt is not supported"; } } } @@ -1289,35 +1286,35 @@ private: void VisitDo(const TRule_do_stmt& msg) { VisitKeyword(msg.GetToken1()); switch (msg.GetBlock2().Alt_case()) { - case TRule_do_stmt_TBlock2::kAlt1: { // CALL - PushCurrentIndent(); - NewLine(); - const auto& alt = msg.GetBlock2().GetAlt1().GetRule_call_action1(); - Visit(alt.GetBlock1()); - AfterInvokeExpr_ = true; - Visit(alt.GetToken2()); - if (alt.HasBlock3()) { - Visit(alt.GetBlock3()); + case TRule_do_stmt_TBlock2::kAlt1: { // CALL + PushCurrentIndent(); + NewLine(); + const auto& alt = msg.GetBlock2().GetAlt1().GetRule_call_action1(); + Visit(alt.GetBlock1()); + AfterInvokeExpr_ = true; + Visit(alt.GetToken2()); + if (alt.HasBlock3()) { + Visit(alt.GetBlock3()); + } + Visit(alt.GetToken4()); + PopCurrentIndent(); + NewLine(); + break; } - Visit(alt.GetToken4()); - PopCurrentIndent(); - NewLine(); - break; - } - case TRule_do_stmt_TBlock2::kAlt2: { // INLINE - const auto& alt = msg.GetBlock2().GetAlt2().GetRule_inline_action1(); - VisitKeyword(alt.GetToken1()); - PushCurrentIndent(); - NewLine(); - Visit(alt.GetRule_define_action_or_subquery_body2()); - PopCurrentIndent(); - NewLine(); - VisitKeyword(alt.GetToken3()); - VisitKeyword(alt.GetToken4()); - break; - } - default: - ythrow yexception() << "Alt is not supported"; + case TRule_do_stmt_TBlock2::kAlt2: { // INLINE + const auto& alt = msg.GetBlock2().GetAlt2().GetRule_inline_action1(); + VisitKeyword(alt.GetToken1()); + PushCurrentIndent(); + NewLine(); + Visit(alt.GetRule_define_action_or_subquery_body2()); + PopCurrentIndent(); + NewLine(); + VisitKeyword(alt.GetToken3()); + VisitKeyword(alt.GetToken4()); + break; + } + default: + ythrow yexception() << "Alt is not supported"; } } @@ -1597,26 +1594,26 @@ private: NewLine(); PushCurrentIndent(); switch (msg.GetBlock3().Alt_case()) { - case TRule_alter_backup_collection_stmt_TBlock3::kAlt1: { - Visit(msg.GetBlock3().GetAlt1().GetRule_alter_backup_collection_actions1().GetRule_alter_backup_collection_action1()); - for (const auto& action : msg.GetBlock3().GetAlt1().GetRule_alter_backup_collection_actions1().GetBlock2()) { - Visit(action.GetToken1()); // comma - NewLine(); - Visit(action.GetRule_alter_backup_collection_action2()); + case TRule_alter_backup_collection_stmt_TBlock3::kAlt1: { + Visit(msg.GetBlock3().GetAlt1().GetRule_alter_backup_collection_actions1().GetRule_alter_backup_collection_action1()); + for (const auto& action : msg.GetBlock3().GetAlt1().GetRule_alter_backup_collection_actions1().GetBlock2()) { + Visit(action.GetToken1()); // comma + NewLine(); + Visit(action.GetRule_alter_backup_collection_action2()); + } + break; } - break; - } - case TRule_alter_backup_collection_stmt_TBlock3::kAlt2: { - Visit(msg.GetBlock3().GetAlt2().GetRule_alter_backup_collection_entries1().GetRule_alter_backup_collection_entry1()); - for (const auto& entry : msg.GetBlock3().GetAlt2().GetRule_alter_backup_collection_entries1().GetBlock2()) { - Visit(entry.GetToken1()); // comma - NewLine(); - Visit(entry.GetRule_alter_backup_collection_entry2()); + case TRule_alter_backup_collection_stmt_TBlock3::kAlt2: { + Visit(msg.GetBlock3().GetAlt2().GetRule_alter_backup_collection_entries1().GetRule_alter_backup_collection_entry1()); + for (const auto& entry : msg.GetBlock3().GetAlt2().GetRule_alter_backup_collection_entries1().GetBlock2()) { + Visit(entry.GetToken1()); // comma + NewLine(); + Visit(entry.GetRule_alter_backup_collection_entry2()); + } + break; } - break; - } - default: - ythrow yexception() << "Alt is not supported"; + default: + ythrow yexception() << "Alt is not supported"; } PopCurrentIndent(); @@ -1733,21 +1730,22 @@ private: return; } - //Cerr << str << "\n"; + // Cerr << str << "\n"; auto currentScope = Scopes_.back(); if (!SkipSpaceAfterUnaryOp_ && !InMultiTokenOp_) { if (AfterLess_ && str == ">") { Out(' '); } else if (AfterDigits_ && str == ".") { Out(' '); - } else if (OutColumn_ && (currentScope == EScope::DoubleQuestion || str != "?") - && str != ":" && str != "." && str != "," && str != ";" && str != ")" && str != "]" - && str != "}" && str != "|>" && str != "::" && !AfterNamespace_ && !AfterBracket_ - && !AfterInvokeExpr_ && !AfterDollarOrAt_ && !AfterDot_ && (!AfterQuestion_ || str != "?") - && (!InsideType_ || (str != "<" && str != ">" && str != "<>")) - && (!InsideType_ || !AfterLess_) - && (!AfterKeyExpr_ || str != "[") - ) { + } else if (OutColumn_ && + (currentScope == EScope::DoubleQuestion || str != "?") && + str != ":" && str != "." && str != "," && str != ";" && str != ")" && + str != "]" && str != "}" && str != "|>" && str != "::" && + !AfterNamespace_ && !AfterBracket_ && !AfterInvokeExpr_ && + !AfterDollarOrAt_ && !AfterDot_ && (!AfterQuestion_ || str != "?") && + (!InsideType_ || (str != "<" && str != ">" && str != "<>")) && + (!InsideType_ || !AfterLess_) && (!AfterKeyExpr_ || str != "[")) + { Out(' '); } } @@ -1774,7 +1772,7 @@ private: if (forceKeyword) { str = to_upper(str); } else if (currentScope == EScope::Default) { - if (auto p = StaticData_.Keywords.find(to_upper(str)); p != StaticData_.Keywords.end()) { + if (auto p = StaticData_.Keywords.find(to_upper(str)); p != StaticData_.Keywords.end()) { str = *p; } } @@ -1830,8 +1828,7 @@ private: if (str == "," && !MarkTokenStack_.empty()) { const bool addNewline = - (TokenIndex_ + 1 < ParsedTokens_.size() && ParsedTokens_[TokenIndex_].Line != ParsedTokens_[TokenIndex_ + 1].Line) - || (TokenIndex_ > 0 && ParsedTokens_[TokenIndex_ - 1].Line != ParsedTokens_[TokenIndex_].Line); + (TokenIndex_ + 1 < ParsedTokens_.size() && ParsedTokens_[TokenIndex_].Line != ParsedTokens_[TokenIndex_ + 1].Line) || (TokenIndex_ > 0 && ParsedTokens_[TokenIndex_ - 1].Line != ParsedTokens_[TokenIndex_].Line); // add line for trailing comma if (addNewline) { NewLine(); @@ -1843,35 +1840,35 @@ private: void VisitIntoValuesSource(const TRule_into_values_source& msg) { switch (msg.Alt_case()) { - case TRule_into_values_source::kAltIntoValuesSource1: { - const auto& alt = msg.GetAlt_into_values_source1(); - if (alt.HasBlock1()) { - const auto& columns = alt.GetBlock1().GetRule_pure_column_list1(); - Visit(columns.GetToken1()); - NewLine(); - PushCurrentIndent(); - Visit(columns.GetRule_an_id2()); - for (const auto& block : columns.GetBlock3()) { - Visit(block.GetToken1()); + case TRule_into_values_source::kAltIntoValuesSource1: { + const auto& alt = msg.GetAlt_into_values_source1(); + if (alt.HasBlock1()) { + const auto& columns = alt.GetBlock1().GetRule_pure_column_list1(); + Visit(columns.GetToken1()); + NewLine(); + PushCurrentIndent(); + Visit(columns.GetRule_an_id2()); + for (const auto& block : columns.GetBlock3()) { + Visit(block.GetToken1()); + NewLine(); + Visit(block.GetRule_an_id2()); + } + + PopCurrentIndent(); + NewLine(); + Visit(columns.GetToken4()); NewLine(); - Visit(block.GetRule_an_id2()); } - PopCurrentIndent(); - NewLine(); - Visit(columns.GetToken4()); - NewLine(); + Visit(alt.GetRule_values_source2()); + break; } - - Visit(alt.GetRule_values_source2()); - break; - } - case TRule_into_values_source::kAltIntoValuesSource2: { - VisitAllFields(TRule_into_values_source::GetDescriptor(), msg); - break; - } - default: - ythrow yexception() << "Alt is not supported"; + case TRule_into_values_source::kAltIntoValuesSource2: { + VisitAllFields(TRule_into_values_source::GetDescriptor(), msg); + break; + } + default: + ythrow yexception() << "Alt is not supported"; } } @@ -2220,35 +2217,35 @@ private: void VisitSingleSource(const TRule_single_source& msg) { switch (msg.Alt_case()) { - case TRule_single_source::kAltSingleSource1: { - const auto& alt = msg.GetAlt_single_source1(); - Visit(alt); - break; - } - case TRule_single_source::kAltSingleSource2: { - const auto& alt = msg.GetAlt_single_source2(); - Visit(alt.GetToken1()); - NewLine(); - PushCurrentIndent(); - Visit(alt.GetRule_select_stmt2()); - PopCurrentIndent(); - NewLine(); - Visit(alt.GetToken3()); - break; - } - case TRule_single_source::kAltSingleSource3: { - const auto& alt = msg.GetAlt_single_source3(); - Visit(alt.GetToken1()); - NewLine(); - PushCurrentIndent(); - Visit(alt.GetRule_values_stmt2()); - PopCurrentIndent(); - NewLine(); - Visit(alt.GetToken3()); - break; - } - default: - ythrow yexception() << "Alt is not supported"; + case TRule_single_source::kAltSingleSource1: { + const auto& alt = msg.GetAlt_single_source1(); + Visit(alt); + break; + } + case TRule_single_source::kAltSingleSource2: { + const auto& alt = msg.GetAlt_single_source2(); + Visit(alt.GetToken1()); + NewLine(); + PushCurrentIndent(); + Visit(alt.GetRule_select_stmt2()); + PopCurrentIndent(); + NewLine(); + Visit(alt.GetToken3()); + break; + } + case TRule_single_source::kAltSingleSource3: { + const auto& alt = msg.GetAlt_single_source3(); + Visit(alt.GetToken1()); + NewLine(); + PushCurrentIndent(); + Visit(alt.GetRule_values_stmt2()); + PopCurrentIndent(); + NewLine(); + Visit(alt.GetToken3()); + break; + } + default: + ythrow yexception() << "Alt is not supported"; } } @@ -2377,35 +2374,35 @@ private: void VisitFlattenByArg(const TRule_flatten_by_arg& msg) { switch (msg.Alt_case()) { - case TRule_flatten_by_arg::kAltFlattenByArg1: { - const auto& alt = msg.GetAlt_flatten_by_arg1(); - Visit(alt); - break; - } - case TRule_flatten_by_arg::kAltFlattenByArg2: { - const auto& alt = msg.GetAlt_flatten_by_arg2(); - Visit(alt.GetToken1()); - NewLine(); - PushCurrentIndent(); - const auto& exprs = alt.GetRule_named_expr_list2(); - Visit(exprs.GetRule_named_expr1()); - for (const auto& block : exprs.GetBlock2()) { - Visit(block.GetToken1()); - NewLine(); - Visit(block.GetRule_named_expr2()); + case TRule_flatten_by_arg::kAltFlattenByArg1: { + const auto& alt = msg.GetAlt_flatten_by_arg1(); + Visit(alt); + break; } + case TRule_flatten_by_arg::kAltFlattenByArg2: { + const auto& alt = msg.GetAlt_flatten_by_arg2(); + Visit(alt.GetToken1()); + NewLine(); + PushCurrentIndent(); + const auto& exprs = alt.GetRule_named_expr_list2(); + Visit(exprs.GetRule_named_expr1()); + for (const auto& block : exprs.GetBlock2()) { + Visit(block.GetToken1()); + NewLine(); + Visit(block.GetRule_named_expr2()); + } - if (alt.HasBlock3()) { - Visit(alt.GetBlock3()); - } + if (alt.HasBlock3()) { + Visit(alt.GetBlock3()); + } - NewLine(); - PopCurrentIndent(); - Visit(alt.GetToken4()); - break; - } - default: - ythrow yexception() << "Alt is not supported"; + NewLine(); + PopCurrentIndent(); + Visit(alt.GetToken4()); + break; + } + default: + ythrow yexception() << "Alt is not supported"; } } @@ -2438,42 +2435,42 @@ private: const auto& block3 = msg.GetBlock3(); switch (block3.Alt_case()) { - case TRule_table_ref::TBlock3::kAlt1: { - const auto& alt = block3.GetAlt1(); - const auto& key = alt.GetRule_table_key1(); - Visit(key.GetRule_id_table_or_type1()); - Visit(key.GetBlock2()); + case TRule_table_ref::TBlock3::kAlt1: { + const auto& alt = block3.GetAlt1(); + const auto& key = alt.GetRule_table_key1(); + Visit(key.GetRule_id_table_or_type1()); + Visit(key.GetBlock2()); - break; - } - case TRule_table_ref::TBlock3::kAlt2: { - const auto& alt = block3.GetAlt2(); - Visit(alt.GetRule_an_id_expr1()); - AfterInvokeExpr_ = true; - Visit(alt.GetToken2()); - if (alt.HasBlock3()) { - Visit(alt.GetBlock3()); + break; } - - Visit(alt.GetToken4()); - break; - } - case TRule_table_ref::TBlock3::kAlt3: { - const auto& alt = block3.GetAlt3(); - Visit(alt.GetRule_bind_parameter1()); - if (alt.HasBlock2()) { + case TRule_table_ref::TBlock3::kAlt2: { + const auto& alt = block3.GetAlt2(); + Visit(alt.GetRule_an_id_expr1()); AfterInvokeExpr_ = true; - Visit(alt.GetBlock2()); - } + Visit(alt.GetToken2()); + if (alt.HasBlock3()) { + Visit(alt.GetBlock3()); + } - if (alt.HasBlock3()) { - Visit(alt.GetBlock3()); + Visit(alt.GetToken4()); + break; } + case TRule_table_ref::TBlock3::kAlt3: { + const auto& alt = block3.GetAlt3(); + Visit(alt.GetRule_bind_parameter1()); + if (alt.HasBlock2()) { + AfterInvokeExpr_ = true; + Visit(alt.GetBlock2()); + } - break; - } - default: - ythrow yexception() << "Alt is not supported"; + if (alt.HasBlock3()) { + Visit(alt.GetBlock3()); + } + + break; + } + default: + ythrow yexception() << "Alt is not supported"; } if (msg.HasBlock4()) { @@ -2835,43 +2832,43 @@ private: if (msg.HasBlock3()) { const auto& b = msg.GetBlock3(); switch (b.Alt_case()) { - case TRule_neq_subexpr_TBlock3::kAlt1: { - const auto& alt = b.GetAlt1(); - const bool hasFirstNewline = LastLine_ != ParsedTokens_[TokenIndex_].Line; - // 2 is `??` size in tokens - const bool hasSecondNewline = ParsedTokens_[TokenIndex_].Line != ParsedTokens_[TokenIndex_ + 2].Line; - const ui32 currentOutLine = OutLine_; - - if (currentOutLine != OutLine_ || (hasFirstNewline && hasSecondNewline)) { - NewLine(); - if (!pushedIndent) { - PushCurrentIndent(); - pushedIndent = true; + case TRule_neq_subexpr_TBlock3::kAlt1: { + const auto& alt = b.GetAlt1(); + const bool hasFirstNewline = LastLine_ != ParsedTokens_[TokenIndex_].Line; + // 2 is `??` size in tokens + const bool hasSecondNewline = ParsedTokens_[TokenIndex_].Line != ParsedTokens_[TokenIndex_ + 2].Line; + const ui32 currentOutLine = OutLine_; + + if (currentOutLine != OutLine_ || (hasFirstNewline && hasSecondNewline)) { + NewLine(); + if (!pushedIndent) { + PushCurrentIndent(); + pushedIndent = true; + } } - } - Visit(alt.GetRule_double_question1()); - if (hasFirstNewline || hasSecondNewline) { - NewLine(); - if (!pushedIndent) { - PushCurrentIndent(); - pushedIndent = true; + Visit(alt.GetRule_double_question1()); + if (hasFirstNewline || hasSecondNewline) { + NewLine(); + if (!pushedIndent) { + PushCurrentIndent(); + pushedIndent = true; + } } - } - VisitNeqSubexprImpl(alt.GetRule_neq_subexpr2(), pushedIndent, false); - if (pushedIndent && top) { - PopCurrentIndent(); - pushedIndent = false; - } + VisitNeqSubexprImpl(alt.GetRule_neq_subexpr2(), pushedIndent, false); + if (pushedIndent && top) { + PopCurrentIndent(); + pushedIndent = false; + } - break; - } - case TRule_neq_subexpr_TBlock3::kAlt2: - Visit(b.GetAlt2()); - break; - default: - ythrow yexception() << "Alt is not supported"; + break; + } + case TRule_neq_subexpr_TBlock3::kAlt2: + Visit(b.GetAlt2()); + break; + default: + ythrow yexception() << "Alt is not supported"; } } } @@ -2900,18 +2897,18 @@ private: ui32 BinaryOpTokenSize(const TRule_neq_subexpr::TBlock2::TBlock1& block) { switch (block.Alt_case()) { - case TRule_neq_subexpr::TBlock2::TBlock1::kAlt1: - case TRule_neq_subexpr::TBlock2::TBlock1::kAlt3: - case TRule_neq_subexpr::TBlock2::TBlock1::kAlt5: - case TRule_neq_subexpr::TBlock2::TBlock1::kAlt6: - case TRule_neq_subexpr::TBlock2::TBlock1::kAlt7: - return 1; - case TRule_neq_subexpr::TBlock2::TBlock1::kAlt2: - return 2; - case TRule_neq_subexpr::TBlock2::TBlock1::kAlt4: - return 3; - default: - ythrow yexception() << "Alt is not supported"; + case TRule_neq_subexpr::TBlock2::TBlock1::kAlt1: + case TRule_neq_subexpr::TBlock2::TBlock1::kAlt3: + case TRule_neq_subexpr::TBlock2::TBlock1::kAlt5: + case TRule_neq_subexpr::TBlock2::TBlock1::kAlt6: + case TRule_neq_subexpr::TBlock2::TBlock1::kAlt7: + return 1; + case TRule_neq_subexpr::TBlock2::TBlock1::kAlt2: + return 2; + case TRule_neq_subexpr::TBlock2::TBlock1::kAlt4: + return 3; + default: + ythrow yexception() << "Alt is not supported"; } } @@ -3036,161 +3033,161 @@ TObfuscatingFunctor MakeObfuscatingFunctor(void (TObfuscatingVisitor::*memberPtr TStaticData::TStaticData() : Keywords(GetKeywords()) , ScopeDispatch({ - {TRule_type_name::GetDescriptor(), EScope::TypeName}, - {TRule_type_name_composite::GetDescriptor(), EScope::TypeName}, - {TRule_double_question::GetDescriptor(), EScope::DoubleQuestion}, - {TRule_id::GetDescriptor(), EScope::Identifier}, - {TRule_id_or_type::GetDescriptor(), EScope::Identifier}, - {TRule_id_schema::GetDescriptor(), EScope::Identifier}, - {TRule_id_expr::GetDescriptor(), EScope::Identifier}, - {TRule_id_expr_in::GetDescriptor(), EScope::Identifier}, - {TRule_id_window::GetDescriptor(), EScope::Identifier}, - {TRule_id_table::GetDescriptor(), EScope::Identifier}, - {TRule_id_without::GetDescriptor(), EScope::Identifier}, - {TRule_id_hint::GetDescriptor(), EScope::Identifier}, - {TRule_identifier::GetDescriptor(), EScope::Identifier}, - {TRule_id_table_or_type::GetDescriptor(), EScope::Identifier}, - {TRule_bind_parameter::GetDescriptor(), EScope::Identifier}, - {TRule_an_id_as_compat::GetDescriptor(), EScope::Identifier}, - }) + {TRule_type_name::GetDescriptor(), EScope::TypeName}, + {TRule_type_name_composite::GetDescriptor(), EScope::TypeName}, + {TRule_double_question::GetDescriptor(), EScope::DoubleQuestion}, + {TRule_id::GetDescriptor(), EScope::Identifier}, + {TRule_id_or_type::GetDescriptor(), EScope::Identifier}, + {TRule_id_schema::GetDescriptor(), EScope::Identifier}, + {TRule_id_expr::GetDescriptor(), EScope::Identifier}, + {TRule_id_expr_in::GetDescriptor(), EScope::Identifier}, + {TRule_id_window::GetDescriptor(), EScope::Identifier}, + {TRule_id_table::GetDescriptor(), EScope::Identifier}, + {TRule_id_without::GetDescriptor(), EScope::Identifier}, + {TRule_id_hint::GetDescriptor(), EScope::Identifier}, + {TRule_identifier::GetDescriptor(), EScope::Identifier}, + {TRule_id_table_or_type::GetDescriptor(), EScope::Identifier}, + {TRule_bind_parameter::GetDescriptor(), EScope::Identifier}, + {TRule_an_id_as_compat::GetDescriptor(), EScope::Identifier}, + }) , PrettyVisitDispatch({ - {TToken::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitToken)}, - {TRule_value_constructor::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitValueConstructor)}, - {TRule_into_values_source::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitIntoValuesSource)}, - {TRule_select_kind::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectKind)}, - {TRule_process_core::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitProcessCore)}, - {TRule_reduce_core::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitReduceCore)}, - {TRule_sort_specification_list::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSortSpecificationList)}, - {TRule_select_core::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectCore)}, - {TRule_row_pattern_recognition_clause::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitRowPatternRecognitionClause)}, - {TRule_join_source::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitJoinSource)}, - {TRule_join_constraint::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitJoinConstraint)}, - {TRule_single_source::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSingleSource)}, - {TRule_flatten_source::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitFlattenSource)}, - {TRule_named_single_source::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitNamedSingleSource)}, - {TRule_table_hints::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitTableHints)}, - {TRule_simple_table_ref::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSimpleTableRef)}, - {TRule_into_simple_table_ref::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitIntoSimpleTableRef)}, - {TRule_select_kind_partial::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectKindPartial)}, - {TRule_flatten_by_arg::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitFlattenByArg)}, - {TRule_without_column_list::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitWithoutColumnList)}, - {TRule_table_ref::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitTableRef)}, - {TRule_grouping_element_list::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitGroupingElementList)}, - {TRule_group_by_clause::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitGroupByClause)}, - {TRule_window_definition_list::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitWindowDefinitionList)}, - {TRule_window_specification::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitWindowSpecification)}, - {TRule_window_partition_clause::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitWindowParitionClause)}, - {TRule_lambda_body::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitLambdaBody)}, - {TRule_select_kind_parenthesis::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectKindParenthesis)}, - {TRule_cast_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCastExpr)}, - {TRule_bitcast_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitBitCastExpr)}, - {TRule_ext_order_by_clause::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitExtOrderByClause)}, - {TRule_key_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitKeyExpr)}, - {TRule_define_action_or_subquery_body::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDefineActionOrSubqueryBody)}, - {TRule_exists_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitExistsExpr)}, - {TRule_case_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCaseExpr)}, - {TRule_with_table_settings::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitWithTableSettingsExpr)}, - {TRule_table_setting_value::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitTableSettingValue)}, - {TRule_ttl_tier_action::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitTtlTierAction)}, - - {TRule_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitExpr)}, - {TRule_cond_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCondExpr)}, - {TRule_or_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitOrSubexpr)}, - {TRule_and_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAndSubexpr)}, - {TRule_eq_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitEqSubexpr)}, - {TRule_neq_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitNeqSubexpr)}, - {TRule_bit_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitBitSubexpr)}, - {TRule_add_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAddSubexpr)}, - {TRule_mul_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitMulSubexpr)}, - - {TRule_rot_right::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitRotRight)}, - {TRule_shift_right::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitShiftRight)}, - - {TRule_pragma_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitPragma)}, - {TRule_select_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelect)}, - {TRule_select_stmt_intersect::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectIntersect)}, - {TRule_smart_parenthesis::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSmartParenthesis)}, - {TRule_select_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectSubExpr)}, - {TRule_select_subexpr_intersect::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectSubExprIntersect)}, - {TRule_select_unparenthesized_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectUnparenthesized)}, - {TRule_select_unparenthesized_stmt_intersect::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectUnparenthesizedIntersect)}, - {TRule_named_nodes_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitNamedNodes)}, - {TRule_create_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateTable)}, - {TRule_drop_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropTable)}, - {TRule_use_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitUse)}, - {TRule_into_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitIntoTable)}, - {TRule_commit_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCommit)}, - {TRule_update_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitUpdate)}, - {TRule_delete_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDelete)}, - {TRule_rollback_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitRollback)}, - {TRule_declare_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDeclare)}, - {TRule_import_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitImport)}, - {TRule_export_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitExport)}, - {TRule_alter_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterTable)}, - {TRule_alter_external_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterExternalTable)}, - {TRule_do_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDo)}, - {TRule_define_action_or_subquery_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAction)}, - {TRule_if_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitIf)}, - {TRule_for_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitFor)}, - {TRule_values_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitValues)}, - {TRule_create_user_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateUser)}, - {TRule_alter_user_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterUser)}, - {TRule_create_group_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateGroup)}, - {TRule_alter_group_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterGroup)}, - {TRule_drop_role_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropRole)}, - {TRule_upsert_object_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitUpsertObject)}, - {TRule_create_object_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateObject)}, - {TRule_alter_object_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterObject)}, - {TRule_drop_object_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropObject)}, - {TRule_create_external_data_source_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateExternalDataSource)}, - {TRule_alter_external_data_source_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterExternalDataSource)}, - {TRule_drop_external_data_source_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropExternalDataSource)}, - {TRule_create_replication_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateAsyncReplication)}, - {TRule_alter_replication_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterAsyncReplication)}, - {TRule_drop_replication_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropAsyncReplication)}, - {TRule_create_transfer_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateTransfer)}, - {TRule_alter_transfer_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterTransfer)}, - {TRule_drop_transfer_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropTransfer)}, - {TRule_create_topic_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateTopic)}, - {TRule_alter_topic_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterTopic)}, - {TRule_drop_topic_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropTopic)}, - {TRule_grant_permissions_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitGrantPermissions)}, - {TRule_revoke_permissions_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitRevokePermissions)}, - {TRule_alter_table_store_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterTableStore)}, - {TRule_create_view_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateView)}, - {TRule_drop_view_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropView)}, - {TRule_create_resource_pool_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateResourcePool)}, - {TRule_alter_resource_pool_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterResourcePool)}, - {TRule_drop_resource_pool_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropResourcePool)}, - {TRule_create_backup_collection_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateBackupCollection)}, - {TRule_alter_backup_collection_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterBackupCollection)}, - {TRule_drop_backup_collection_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropBackupCollection)}, - {TRule_analyze_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAnalyze)}, - {TRule_create_resource_pool_classifier_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateResourcePoolClassifier)}, - {TRule_alter_resource_pool_classifier_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterResourcePoolClassifier)}, - {TRule_drop_resource_pool_classifier_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropResourcePoolClassifier)}, - {TRule_backup_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitBackup)}, - {TRule_restore_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitRestore)}, - {TRule_alter_sequence_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterSequence)}, - {TRule_alter_database_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterDatabase)}, - {TRule_show_create_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitShowCreateTable)}, - {TRule_streaming_query_settings::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitStreamingQuerySettings)}, - {TRule_create_streaming_query_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateStreamingQuery)}, - {TRule_alter_streaming_query_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterStreamingQuery)}, - {TRule_drop_streaming_query_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropStreamingQuery)}, - {TRule_create_secret_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateSecret)}, - {TRule_alter_secret_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterSecret)}, - {TRule_drop_secret_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropSecret)}, - }) + {TToken::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitToken)}, + {TRule_value_constructor::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitValueConstructor)}, + {TRule_into_values_source::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitIntoValuesSource)}, + {TRule_select_kind::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectKind)}, + {TRule_process_core::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitProcessCore)}, + {TRule_reduce_core::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitReduceCore)}, + {TRule_sort_specification_list::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSortSpecificationList)}, + {TRule_select_core::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectCore)}, + {TRule_row_pattern_recognition_clause::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitRowPatternRecognitionClause)}, + {TRule_join_source::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitJoinSource)}, + {TRule_join_constraint::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitJoinConstraint)}, + {TRule_single_source::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSingleSource)}, + {TRule_flatten_source::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitFlattenSource)}, + {TRule_named_single_source::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitNamedSingleSource)}, + {TRule_table_hints::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitTableHints)}, + {TRule_simple_table_ref::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSimpleTableRef)}, + {TRule_into_simple_table_ref::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitIntoSimpleTableRef)}, + {TRule_select_kind_partial::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectKindPartial)}, + {TRule_flatten_by_arg::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitFlattenByArg)}, + {TRule_without_column_list::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitWithoutColumnList)}, + {TRule_table_ref::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitTableRef)}, + {TRule_grouping_element_list::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitGroupingElementList)}, + {TRule_group_by_clause::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitGroupByClause)}, + {TRule_window_definition_list::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitWindowDefinitionList)}, + {TRule_window_specification::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitWindowSpecification)}, + {TRule_window_partition_clause::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitWindowParitionClause)}, + {TRule_lambda_body::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitLambdaBody)}, + {TRule_select_kind_parenthesis::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectKindParenthesis)}, + {TRule_cast_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCastExpr)}, + {TRule_bitcast_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitBitCastExpr)}, + {TRule_ext_order_by_clause::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitExtOrderByClause)}, + {TRule_key_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitKeyExpr)}, + {TRule_define_action_or_subquery_body::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDefineActionOrSubqueryBody)}, + {TRule_exists_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitExistsExpr)}, + {TRule_case_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCaseExpr)}, + {TRule_with_table_settings::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitWithTableSettingsExpr)}, + {TRule_table_setting_value::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitTableSettingValue)}, + {TRule_ttl_tier_action::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitTtlTierAction)}, + + {TRule_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitExpr)}, + {TRule_cond_expr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCondExpr)}, + {TRule_or_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitOrSubexpr)}, + {TRule_and_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAndSubexpr)}, + {TRule_eq_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitEqSubexpr)}, + {TRule_neq_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitNeqSubexpr)}, + {TRule_bit_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitBitSubexpr)}, + {TRule_add_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAddSubexpr)}, + {TRule_mul_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitMulSubexpr)}, + + {TRule_rot_right::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitRotRight)}, + {TRule_shift_right::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitShiftRight)}, + + {TRule_pragma_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitPragma)}, + {TRule_select_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelect)}, + {TRule_select_stmt_intersect::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectIntersect)}, + {TRule_smart_parenthesis::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSmartParenthesis)}, + {TRule_select_subexpr::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectSubExpr)}, + {TRule_select_subexpr_intersect::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectSubExprIntersect)}, + {TRule_select_unparenthesized_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectUnparenthesized)}, + {TRule_select_unparenthesized_stmt_intersect::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitSelectUnparenthesizedIntersect)}, + {TRule_named_nodes_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitNamedNodes)}, + {TRule_create_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateTable)}, + {TRule_drop_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropTable)}, + {TRule_use_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitUse)}, + {TRule_into_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitIntoTable)}, + {TRule_commit_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCommit)}, + {TRule_update_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitUpdate)}, + {TRule_delete_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDelete)}, + {TRule_rollback_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitRollback)}, + {TRule_declare_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDeclare)}, + {TRule_import_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitImport)}, + {TRule_export_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitExport)}, + {TRule_alter_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterTable)}, + {TRule_alter_external_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterExternalTable)}, + {TRule_do_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDo)}, + {TRule_define_action_or_subquery_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAction)}, + {TRule_if_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitIf)}, + {TRule_for_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitFor)}, + {TRule_values_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitValues)}, + {TRule_create_user_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateUser)}, + {TRule_alter_user_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterUser)}, + {TRule_create_group_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateGroup)}, + {TRule_alter_group_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterGroup)}, + {TRule_drop_role_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropRole)}, + {TRule_upsert_object_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitUpsertObject)}, + {TRule_create_object_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateObject)}, + {TRule_alter_object_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterObject)}, + {TRule_drop_object_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropObject)}, + {TRule_create_external_data_source_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateExternalDataSource)}, + {TRule_alter_external_data_source_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterExternalDataSource)}, + {TRule_drop_external_data_source_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropExternalDataSource)}, + {TRule_create_replication_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateAsyncReplication)}, + {TRule_alter_replication_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterAsyncReplication)}, + {TRule_drop_replication_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropAsyncReplication)}, + {TRule_create_transfer_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateTransfer)}, + {TRule_alter_transfer_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterTransfer)}, + {TRule_drop_transfer_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropTransfer)}, + {TRule_create_topic_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateTopic)}, + {TRule_alter_topic_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterTopic)}, + {TRule_drop_topic_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropTopic)}, + {TRule_grant_permissions_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitGrantPermissions)}, + {TRule_revoke_permissions_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitRevokePermissions)}, + {TRule_alter_table_store_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterTableStore)}, + {TRule_create_view_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateView)}, + {TRule_drop_view_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropView)}, + {TRule_create_resource_pool_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateResourcePool)}, + {TRule_alter_resource_pool_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterResourcePool)}, + {TRule_drop_resource_pool_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropResourcePool)}, + {TRule_create_backup_collection_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateBackupCollection)}, + {TRule_alter_backup_collection_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterBackupCollection)}, + {TRule_drop_backup_collection_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropBackupCollection)}, + {TRule_analyze_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAnalyze)}, + {TRule_create_resource_pool_classifier_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateResourcePoolClassifier)}, + {TRule_alter_resource_pool_classifier_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterResourcePoolClassifier)}, + {TRule_drop_resource_pool_classifier_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropResourcePoolClassifier)}, + {TRule_backup_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitBackup)}, + {TRule_restore_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitRestore)}, + {TRule_alter_sequence_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterSequence)}, + {TRule_alter_database_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterDatabase)}, + {TRule_show_create_table_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitShowCreateTable)}, + {TRule_streaming_query_settings::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitStreamingQuerySettings)}, + {TRule_create_streaming_query_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateStreamingQuery)}, + {TRule_alter_streaming_query_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterStreamingQuery)}, + {TRule_drop_streaming_query_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropStreamingQuery)}, + {TRule_create_secret_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitCreateSecret)}, + {TRule_alter_secret_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitAlterSecret)}, + {TRule_drop_secret_stmt::GetDescriptor(), MakePrettyFunctor(&TPrettyVisitor::VisitDropSecret)}, + }) , ObfuscatingVisitDispatch({ - {TToken::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitToken)}, - {TRule_literal_value::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitLiteralValue)}, - {TRule_pragma_value::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitPragmaValue)}, - {TRule_atom_expr::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitAtomExpr)}, - {TRule_in_atom_expr::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitInAtomExpr)}, - {TRule_unary_casual_subexpr::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitUnaryCasualSubexpr)}, - {TRule_in_unary_casual_subexpr::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitInUnaryCasualSubexpr)}, - }) + {TToken::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitToken)}, + {TRule_literal_value::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitLiteralValue)}, + {TRule_pragma_value::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitPragmaValue)}, + {TRule_atom_expr::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitAtomExpr)}, + {TRule_in_atom_expr::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitInAtomExpr)}, + {TRule_unary_casual_subexpr::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitUnaryCasualSubexpr)}, + {TRule_in_unary_casual_subexpr::GetDescriptor(), MakeObfuscatingFunctor(&TObfuscatingVisitor::VisitInUnaryCasualSubexpr)}, + }) { // ensure that all statements have a visitor auto coreDescr = TRule_sql_stmt_core::GetDescriptor(); @@ -3213,15 +3210,16 @@ TStaticData::TStaticData() } } -class TSqlFormatter : public NSQLFormat::ISqlFormatter { +class TSqlFormatter: public NSQLFormat::ISqlFormatter { public: TSqlFormatter(const NSQLTranslationV1::TLexers& lexers, - const NSQLTranslationV1::TParsers& parsers, - const NSQLTranslation::TTranslationSettings& settings) + const NSQLTranslationV1::TParsers& parsers, + const NSQLTranslation::TTranslationSettings& settings) : Lexers_(lexers) , Parsers_(parsers) , Settings_(settings) - {} + { + } bool Format(const TString& query, TString& formattedQuery, NYql::TIssues& issues, EFormatMode mode) override { formattedQuery = (mode == EFormatMode::Obfuscate) ? "" : query; @@ -3323,16 +3321,16 @@ private: const NSQLTranslation::TTranslationSettings Settings_; }; -} +} // namespace ISqlFormatter::TPtr MakeSqlFormatter(const NSQLTranslationV1::TLexers& lexers, - const NSQLTranslationV1::TParsers& parsers, - const NSQLTranslation::TTranslationSettings& settings) { + const NSQLTranslationV1::TParsers& parsers, + const NSQLTranslation::TTranslationSettings& settings) { return ISqlFormatter::TPtr(new TSqlFormatter(lexers, parsers, settings)); } TString MutateQuery(const NSQLTranslationV1::TLexers& lexers, - const TString& query, const NSQLTranslation::TTranslationSettings& settings) { + const TString& query, const NSQLTranslation::TTranslationSettings& settings) { auto parsedSettings = settings; NYql::TIssues issues; if (!NSQLTranslation::ParseTranslationSettings(query, parsedSettings, issues)) { @@ -3363,8 +3361,8 @@ TString MutateQuery(const NSQLTranslationV1::TLexers& lexers, } bool SqlFormatSimple(const NSQLTranslationV1::TLexers& lexers, - const NSQLTranslationV1::TParsers& parsers, - const TString& query, TString& formattedQuery, TString& error) { + const NSQLTranslationV1::TParsers& parsers, + const TString& query, TString& formattedQuery, TString& error) { try { google::protobuf::Arena arena; NSQLTranslation::TTranslationSettings settings; @@ -3407,7 +3405,7 @@ THashSet<TString> GetKeywords() { SubstGlobal(after, " ", ""); SubstGlobal(after, "'", ""); if (after == before) { - //Cerr << before << "\n"; + // Cerr << before << "\n"; res.insert(before); } } diff --git a/yql/essentials/sql/v1/format/sql_format.h b/yql/essentials/sql/v1/format/sql_format.h index 55c34a462db..92be72b088a 100644 --- a/yql/essentials/sql/v1/format/sql_format.h +++ b/yql/essentials/sql/v1/format/sql_format.h @@ -21,20 +21,20 @@ public: using TPtr = THolder<ISqlFormatter>; virtual bool Format(const TString& query, TString& formattedQuery, NYql::TIssues& issues, - EFormatMode mode = EFormatMode::Pretty) = 0; + EFormatMode mode = EFormatMode::Pretty) = 0; virtual ~ISqlFormatter() = default; }; ISqlFormatter::TPtr MakeSqlFormatter(const NSQLTranslationV1::TLexers& lexers, - const NSQLTranslationV1::TParsers& parsers, - const NSQLTranslation::TTranslationSettings& settings = {}); + const NSQLTranslationV1::TParsers& parsers, + const NSQLTranslation::TTranslationSettings& settings = {}); // insert spaces and comments between each tokens TString MutateQuery(const NSQLTranslationV1::TLexers& lexers, const TString& query, const NSQLTranslation::TTranslationSettings& settings = {}); bool SqlFormatSimple(const NSQLTranslationV1::TLexers& lexers, - const NSQLTranslationV1::TParsers& parsers, const TString& query, TString& formattedQuery, TString& error); + const NSQLTranslationV1::TParsers& parsers, const TString& query, TString& formattedQuery, TString& error); THashSet<TString> GetKeywords(); -} +} // namespace NSQLFormat diff --git a/yql/essentials/sql/v1/format/sql_format_ut.cpp b/yql/essentials/sql/v1/format/sql_format_ut.cpp index 8714ee2d7c9..9a277f64b74 100644 --- a/yql/essentials/sql/v1/format/sql_format_ut.cpp +++ b/yql/essentials/sql/v1/format/sql_format_ut.cpp @@ -49,7 +49,6 @@ struct TSetup { UNIT_ASSERT_C(res2, issues.ToString()); UNIT_ASSERT_NO_DIFF(formatted, formatted2); - if (mode == NSQLFormat::EFormatMode::Pretty) { NSQLTranslation::TTranslationSettings settings; settings.Antlr4Parser = false; @@ -64,8 +63,8 @@ struct TSetup { NSQLFormat::ISqlFormatter::TPtr Formatter; }; -} +} // namespace Y_UNIT_TEST_SUITE(CheckSqlFormatter) { - #include "sql_format_ut.h" -} +#include "sql_format_ut.h" +} // Y_UNIT_TEST_SUITE(CheckSqlFormatter) diff --git a/yql/essentials/sql/v1/format/sql_format_ut.h b/yql/essentials/sql/v1/format/sql_format_ut.h index 395b12caa4e..0279753af48 100644 --- a/yql/essentials/sql/v1/format/sql_format_ut.h +++ b/yql/essentials/sql/v1/format/sql_format_ut.h @@ -1,3 +1,5 @@ +#pragma once + Y_UNIT_TEST(Pragma) { TCases cases = { {"pragma user = user;", "PRAGMA user = user;\n"}, @@ -13,7 +15,7 @@ Y_UNIT_TEST(Pragma) { Y_UNIT_TEST(DotAfterDigits) { TCases cases = { - {"select a.1 .b from plato.foo;","SELECT\n\ta.1 .b\nFROM\n\tplato.foo\n;\n"}, + {"select a.1 .b from plato.foo;", "SELECT\n\ta.1 .b\nFROM\n\tplato.foo\n;\n"}, }; TSetup setup; @@ -21,18 +23,17 @@ Y_UNIT_TEST(DotAfterDigits) { } Y_UNIT_TEST(AlterDatabase) { - TCases cases { + TCases cases{ {"use plato;alter database `/Root/test` owner to user1;", "USE plato;\n\nALTER DATABASE `/Root/test` OWNER TO user1;\n"}, {"use plato;alter database `/Root/test` set (key1 = 1);", "USE plato;\n\nALTER DATABASE `/Root/test` SET (key1 = 1);\n"}, - {"use plato;alter database `/Root/test` set (\n\tkey1 = 1,\n\tkey2 = \"2\"\n);", "USE plato;\n\nALTER DATABASE `/Root/test` SET (key1 = 1, key2 = '2');\n"} - }; + {"use plato;alter database `/Root/test` set (\n\tkey1 = 1,\n\tkey2 = \"2\"\n);", "USE plato;\n\nALTER DATABASE `/Root/test` SET (key1 = 1, key2 = '2');\n"}}; TSetup setup; setup.Run(cases); } Y_UNIT_TEST(GrantPermissions) { - TCases cases { + TCases cases{ {"use plato;grant connect, modify tables, list on `/Root` to user;", "USE plato;\n\nGRANT CONNECT, MODIFY TABLES, LIST ON `/Root` TO user;\n"}, {"use plato;grant select , select tables, select attributes on `/Root` to user;", "USE plato;\n\nGRANT SELECT, SELECT TABLES, SELECT ATTRIBUTES ON `/Root` TO user;\n"}, {"use plato;grant insert, modify attributes on `/Root` to user;", "USE plato;\n\nGRANT INSERT, MODIFY ATTRIBUTES ON `/Root` TO user;\n"}, @@ -44,15 +45,14 @@ Y_UNIT_TEST(GrantPermissions) { {"use plato;grant describe schema, alter schema on `/Root` to user;", "USE plato;\n\nGRANT DESCRIBE SCHEMA, ALTER SCHEMA ON `/Root` TO user;\n"}, {"use plato;grant select, on `/Root` to user, with grant option;", "USE plato;\n\nGRANT SELECT, ON `/Root` TO user, WITH GRANT OPTION;\n"}, {"use plato;grant all privileges on `/Root` to user;", "USE plato;\n\nGRANT ALL PRIVILEGES ON `/Root` TO user;\n"}, - {"use plato;grant list on `/Root/db1`, `/Root/db2` to user;", "USE plato;\n\nGRANT LIST ON `/Root/db1`, `/Root/db2` TO user;\n"} - }; + {"use plato;grant list on `/Root/db1`, `/Root/db2` to user;", "USE plato;\n\nGRANT LIST ON `/Root/db1`, `/Root/db2` TO user;\n"}}; TSetup setup; setup.Run(cases); } Y_UNIT_TEST(RevokePermissions) { - TCases cases { + TCases cases{ {"use plato;revoke connect, modify tables, list on `/Root` from user;", "USE plato;\n\nREVOKE CONNECT, MODIFY TABLES, LIST ON `/Root` FROM user;\n"}, {"use plato;revoke select , select tables, select attributes on `/Root` from user;", "USE plato;\n\nREVOKE SELECT, SELECT TABLES, SELECT ATTRIBUTES ON `/Root` FROM user;\n"}, {"use plato;revoke insert, modify attributes on `/Root` from user;", "USE plato;\n\nREVOKE INSERT, MODIFY ATTRIBUTES ON `/Root` FROM user;\n"}, @@ -64,8 +64,7 @@ Y_UNIT_TEST(RevokePermissions) { {"use plato;revoke describe schema, alter schema on `/Root` from user;", "USE plato;\n\nREVOKE DESCRIBE SCHEMA, ALTER SCHEMA ON `/Root` FROM user;\n"}, {"use plato;revoke grant option for insert, on `/Root` from user;", "USE plato;\n\nREVOKE GRANT OPTION FOR INSERT, ON `/Root` FROM user;\n"}, {"use plato;revoke all privileges on `/Root` from user;", "USE plato;\n\nREVOKE ALL PRIVILEGES ON `/Root` FROM user;\n"}, - {"use plato;revoke list on `/Root/db1`, `/Root/db2` from user;", "USE plato;\n\nREVOKE LIST ON `/Root/db1`, `/Root/db2` FROM user;\n"} - }; + {"use plato;revoke list on `/Root/db1`, `/Root/db2` from user;", "USE plato;\n\nREVOKE LIST ON `/Root/db1`, `/Root/db2` FROM user;\n"}}; TSetup setup; setup.Run(cases); @@ -73,9 +72,9 @@ Y_UNIT_TEST(RevokePermissions) { Y_UNIT_TEST(DropRole) { TCases cases = { - {"use plato;drop user user,user,user;","USE plato;\n\nDROP USER user, user, user;\n"}, - {"use plato;drop group if exists user;","USE plato;\n\nDROP GROUP IF EXISTS user;\n"}, - {"use plato;drop group user,;","USE plato;\n\nDROP GROUP user,;\n"}, + {"use plato;drop user user,user,user;", "USE plato;\n\nDROP USER user, user, user;\n"}, + {"use plato;drop group if exists user;", "USE plato;\n\nDROP GROUP IF EXISTS user;\n"}, + {"use plato;drop group user,;", "USE plato;\n\nDROP GROUP user,;\n"}, }; TSetup setup; @@ -92,7 +91,7 @@ Y_UNIT_TEST(CreateUser) { {"use plato;CREATE USER user1 LOGIN;", "USE plato;\n\nCREATE USER user1 LOGIN;\n"}, {"use plato;CREATE USER user1 NOLOGIN;", "USE plato;\n\nCREATE USER user1 NOLOGIN;\n"}, {"use plato;CReATE UseR user1 HasH '{\"hash\": \"p4ffeMugohqyBwyckYCK1TjJfz3LIHbKiGL+t+oEhzw=\",\"salt\": \"U+tzBtgo06EBQCjlARA6Jg==\",\"type\": \"argon2id\"}'", - "USE plato;\n\nCREATE USER user1 HASH '{\"hash\": \"p4ffeMugohqyBwyckYCK1TjJfz3LIHbKiGL+t+oEhzw=\",\"salt\": \"U+tzBtgo06EBQCjlARA6Jg==\",\"type\": \"argon2id\"}';\n"}, + "USE plato;\n\nCREATE USER user1 HASH '{\"hash\": \"p4ffeMugohqyBwyckYCK1TjJfz3LIHbKiGL+t+oEhzw=\",\"salt\": \"U+tzBtgo06EBQCjlARA6Jg==\",\"type\": \"argon2id\"}';\n"}, }; TSetup setup; @@ -101,9 +100,9 @@ Y_UNIT_TEST(CreateUser) { Y_UNIT_TEST(CreateGroup) { TCases cases = { - {"use plato;create group user;","USE plato;\n\nCREATE GROUP user;\n"}, - {"use plato;create group user with user user;","USE plato;\n\nCREATE GROUP user WITH USER user;\n"}, - {"use plato;create group user with user user, user,;","USE plato;\n\nCREATE GROUP user WITH USER user, user,;\n"}, + {"use plato;create group user;", "USE plato;\n\nCREATE GROUP user;\n"}, + {"use plato;create group user with user user;", "USE plato;\n\nCREATE GROUP user WITH USER user;\n"}, + {"use plato;create group user with user user, user,;", "USE plato;\n\nCREATE GROUP user WITH USER user, user,;\n"}, }; TSetup setup; @@ -112,12 +111,12 @@ Y_UNIT_TEST(CreateGroup) { Y_UNIT_TEST(AlterUser) { TCases cases = { - {"use plato;alter user user rename to user;","USE plato;\n\nALTER USER user RENAME TO user;\n"}, - {"use plato;alter user user encrypted password 'foo';","USE plato;\n\nALTER USER user ENCRYPTED PASSWORD 'foo';\n"}, - {"use plato;alter user user with encrypted password 'foo';","USE plato;\n\nALTER USER user WITH ENCRYPTED PASSWORD 'foo';\n"}, + {"use plato;alter user user rename to user;", "USE plato;\n\nALTER USER user RENAME TO user;\n"}, + {"use plato;alter user user encrypted password 'foo';", "USE plato;\n\nALTER USER user ENCRYPTED PASSWORD 'foo';\n"}, + {"use plato;alter user user with encrypted password 'foo';", "USE plato;\n\nALTER USER user WITH ENCRYPTED PASSWORD 'foo';\n"}, {"use plato;ALTER USER user1 NOLOGIN;", "USE plato;\n\nALTER USER user1 NOLOGIN;\n"}, {"use plato;alter UseR user1 HasH '{\"hash\": \"p4ffeMugohqyBwyckYCK1TjJfz3LIHbKiGL+t+oEhzw=\",\"salt\": \"U+tzBtgo06EBQCjlARA6Jg==\",\"type\": \"argon2id\"}'", - "USE plato;\n\nALTER USER user1 HASH '{\"hash\": \"p4ffeMugohqyBwyckYCK1TjJfz3LIHbKiGL+t+oEhzw=\",\"salt\": \"U+tzBtgo06EBQCjlARA6Jg==\",\"type\": \"argon2id\"}';\n"}, + "USE plato;\n\nALTER USER user1 HASH '{\"hash\": \"p4ffeMugohqyBwyckYCK1TjJfz3LIHbKiGL+t+oEhzw=\",\"salt\": \"U+tzBtgo06EBQCjlARA6Jg==\",\"type\": \"argon2id\"}';\n"}, }; TSetup setup; @@ -126,10 +125,10 @@ Y_UNIT_TEST(AlterUser) { Y_UNIT_TEST(AlterGroup) { TCases cases = { - {"use plato;alter group user add user user;","USE plato;\n\nALTER GROUP user ADD USER user;\n"}, - {"use plato;alter group user drop user user;","USE plato;\n\nALTER GROUP user DROP USER user;\n"}, - {"use plato;alter group user add user user, user,;","USE plato;\n\nALTER GROUP user ADD USER user, user,;\n"}, - {"use plato;alter group user rename to user;","USE plato;\n\nALTER GROUP user RENAME TO user;\n"}, + {"use plato;alter group user add user user;", "USE plato;\n\nALTER GROUP user ADD USER user;\n"}, + {"use plato;alter group user drop user user;", "USE plato;\n\nALTER GROUP user DROP USER user;\n"}, + {"use plato;alter group user add user user, user,;", "USE plato;\n\nALTER GROUP user ADD USER user, user,;\n"}, + {"use plato;alter group user rename to user;", "USE plato;\n\nALTER GROUP user RENAME TO user;\n"}, }; TSetup setup; @@ -138,8 +137,8 @@ Y_UNIT_TEST(AlterGroup) { Y_UNIT_TEST(AlterSequence) { TCases cases = { - {"use plato;alter sequence sequence start with 10 increment 2 restart with 5;","USE plato;\n\nALTER SEQUENCE sequence START WITH 10 INCREMENT 2 RESTART WITH 5;\n"}, - {"use plato;alter sequence if exists sequence increment 1000 start 100 restart;","USE plato;\n\nALTER SEQUENCE IF EXISTS sequence INCREMENT 1000 START 100 RESTART;\n"}, + {"use plato;alter sequence sequence start with 10 increment 2 restart with 5;", "USE plato;\n\nALTER SEQUENCE sequence START WITH 10 INCREMENT 2 RESTART WITH 5;\n"}, + {"use plato;alter sequence if exists sequence increment 1000 start 100 restart;", "USE plato;\n\nALTER SEQUENCE IF EXISTS sequence INCREMENT 1000 START 100 RESTART;\n"}, }; TSetup setup; @@ -148,7 +147,7 @@ Y_UNIT_TEST(AlterSequence) { Y_UNIT_TEST(ShowCreateTable) { TCases cases = { - {"use plato;show create table user;","USE plato;\n\nSHOW CREATE TABLE user;\n"}, + {"use plato;show create table user;", "USE plato;\n\nSHOW CREATE TABLE user;\n"}, }; TSetup setup; @@ -157,22 +156,18 @@ Y_UNIT_TEST(ShowCreateTable) { Y_UNIT_TEST(SecretOperations) { TCases cases = { - { // create with one setting - "use plato; create secret `secret-name` with (value=\"secret_value\");\n", - "USE plato;\n\nCREATE SECRET `secret-name` WITH (value = 'secret_value');\n" - }, - { // create with more than one setting - "use plato; create secret `secret-name` with (value=\"secret_value\",inherit_permissions=fALSe);\n", - "USE plato;\n\nCREATE SECRET `secret-name` WITH (value = 'secret_value', inherit_permissions = FALSE);\n" - }, - { // alter - "use plato; alter secret `secret-name` with (value=\"secret_value\");\n", - "USE plato;\n\nALTER SECRET `secret-name` WITH (value = 'secret_value');\n" - }, - { // drop - "use plato; drop secret `secret-name`;\n", - "USE plato;\n\nDROP SECRET `secret-name`;\n" - }, + {// create with one setting + "use plato; create secret `secret-name` with (value=\"secret_value\");\n", + "USE plato;\n\nCREATE SECRET `secret-name` WITH (value = 'secret_value');\n"}, + {// create with more than one setting + "use plato; create secret `secret-name` with (value=\"secret_value\",inherit_permissions=fALSe);\n", + "USE plato;\n\nCREATE SECRET `secret-name` WITH (value = 'secret_value', inherit_permissions = FALSE);\n"}, + {// alter + "use plato; alter secret `secret-name` with (value=\"secret_value\");\n", + "USE plato;\n\nALTER SECRET `secret-name` WITH (value = 'secret_value');\n"}, + {// drop + "use plato; drop secret `secret-name`;\n", + "USE plato;\n\nDROP SECRET `secret-name`;\n"}, }; TSetup setup; @@ -181,7 +176,7 @@ Y_UNIT_TEST(SecretOperations) { Y_UNIT_TEST(ShowCreateView) { TCases cases = { - {"use plato;show create view user;","USE plato;\n\nSHOW CREATE VIEW user;\n"}, + {"use plato;show create view user;", "USE plato;\n\nSHOW CREATE VIEW user;\n"}, }; TSetup setup; @@ -190,9 +185,9 @@ Y_UNIT_TEST(ShowCreateView) { Y_UNIT_TEST(Use) { TCases cases = { - {"use user;","USE user;\n"}, - {"use user:user;","USE user: user;\n"}, - {"use user:*;","USE user: *;\n"}, + {"use user;", "USE user;\n"}, + {"use user:user;", "USE user: user;\n"}, + {"use user:*;", "USE user: *;\n"}, }; TSetup setup; @@ -201,7 +196,7 @@ Y_UNIT_TEST(Use) { Y_UNIT_TEST(Commit) { TCases cases = { - {"commit;","COMMIT;\n"}, + {"commit;", "COMMIT;\n"}, }; TSetup setup; @@ -210,7 +205,7 @@ Y_UNIT_TEST(Commit) { Y_UNIT_TEST(Rollback) { TCases cases = { - {"rollback;","ROLLBACK;\n"}, + {"rollback;", "ROLLBACK;\n"}, }; TSetup setup; @@ -219,8 +214,8 @@ Y_UNIT_TEST(Rollback) { Y_UNIT_TEST(Export) { TCases cases = { - {"export $foo;","EXPORT\n\t$foo\n;\n"}, - {"export $foo, $bar;","EXPORT\n\t$foo,\n\t$bar\n;\n"}, + {"export $foo;", "EXPORT\n\t$foo\n;\n"}, + {"export $foo, $bar;", "EXPORT\n\t$foo,\n\t$bar\n;\n"}, }; TSetup setup; @@ -229,8 +224,8 @@ Y_UNIT_TEST(Export) { Y_UNIT_TEST(Import) { TCases cases = { - {"import user symbols $foo;","IMPORT user SYMBOLS $foo;\n"}, - {"import user symbols $foo,$bar;","IMPORT user SYMBOLS $foo, $bar;\n"}, + {"import user symbols $foo;", "IMPORT user SYMBOLS $foo;\n"}, + {"import user symbols $foo,$bar;", "IMPORT user SYMBOLS $foo, $bar;\n"}, }; TSetup setup; @@ -239,9 +234,9 @@ Y_UNIT_TEST(Import) { Y_UNIT_TEST(Values) { TCases cases = { - {"values (1);","VALUES\n\t(1)\n;\n"}, - {"values (1,2),(3,4);","VALUES\n\t(1, 2),\n\t(3, 4)\n;\n"}, - {"values ('a\nb');","VALUES\n\t('a\nb')\n;\n"}, + {"values (1);", "VALUES\n\t(1)\n;\n"}, + {"values (1,2),(3,4);", "VALUES\n\t(1, 2),\n\t(3, 4)\n;\n"}, + {"values ('a\nb');", "VALUES\n\t('a\nb')\n;\n"}, }; TSetup setup; @@ -250,9 +245,9 @@ Y_UNIT_TEST(Values) { Y_UNIT_TEST(Declare) { TCases cases = { - {"declare $foo as int32;","DECLARE $foo AS int32;\n"}, - {"declare $foo as bool ?","DECLARE $foo AS bool?;\n"}, - {"declare $foo as bool ? ?","DECLARE $foo AS bool??;\n"}, + {"declare $foo as int32;", "DECLARE $foo AS int32;\n"}, + {"declare $foo as bool ?", "DECLARE $foo AS bool?;\n"}, + {"declare $foo as bool ? ?", "DECLARE $foo AS bool??;\n"}, }; TSetup setup; @@ -262,19 +257,19 @@ Y_UNIT_TEST(Declare) { Y_UNIT_TEST(NamedNode) { TCases cases = { {"$x=1", - "$x = 1;\n"}, + "$x = 1;\n"}, {"$x,$y=(2,3)", - "$x, $y = (2, 3);\n"}, + "$x, $y = (2, 3);\n"}, {"$a = select 1 union all select 2", - "$a = (\n\tSELECT\n\t\t1\n\tUNION ALL\n\tSELECT\n\t\t2\n);\n"}, + "$a = (\n\tSELECT\n\t\t1\n\tUNION ALL\n\tSELECT\n\t\t2\n);\n"}, {"$a = select 1 from $as;", - "$a = (\n\tSELECT\n\t\t1\n\tFROM\n\t\t$as\n);\n"}, + "$a = (\n\tSELECT\n\t\t1\n\tFROM\n\t\t$as\n);\n"}, {"$a = select * from $t -- comment", - "$a = (\n\tSELECT\n\t\t*\n\tFROM\n\t\t$t -- comment\n);\n"}, + "$a = (\n\tSELECT\n\t\t*\n\tFROM\n\t\t$t -- comment\n);\n"}, {"-- comment\r\r\r$a=1;", - "-- comment\r\n$a = 1;\n"}, + "-- comment\r\n$a = 1;\n"}, {"$a=1;-- comment\n$b=2;/* comment */ /* comment */\n$c = 3;/* comment */ -- comment", - "$a = 1; -- comment\n$b = 2; /* comment */ /* comment */\n$c = 3; /* comment */ -- comment\n"}, + "$a = 1; -- comment\n$b = 2; /* comment */ /* comment */\n$c = 3; /* comment */ -- comment\n"}, }; TSetup setup; @@ -283,8 +278,8 @@ Y_UNIT_TEST(NamedNode) { Y_UNIT_TEST(DropTable) { TCases cases = { - {"drop table user","DROP TABLE user;\n"}, - {"drop table if exists user","DROP TABLE IF EXISTS user;\n"}, + {"drop table user", "DROP TABLE user;\n"}, + {"drop table if exists user", "DROP TABLE IF EXISTS user;\n"}, }; TSetup setup; @@ -293,76 +288,75 @@ Y_UNIT_TEST(DropTable) { Y_UNIT_TEST(CreateTable) { TCases cases = { - {"create table user(user int32)","CREATE TABLE user (\n\tuser int32\n);\n"}, - {"create table user(user int32,user bool ?)","CREATE TABLE user (\n\tuser int32,\n\tuser bool?\n);\n"}, - {"create table user(user int32) with (user=user)","CREATE TABLE user (\n\tuser int32\n)\nWITH (user = user);\n"}, - {"create table user(primary key (user))","CREATE TABLE user (\n\tPRIMARY KEY (user)\n);\n"}, - {"create table user(primary key (user,user))","CREATE TABLE user (\n\tPRIMARY KEY (user, user)\n);\n"}, - {"create table user(partition by (user))","CREATE TABLE user (\n\tPARTITION BY (user)\n);\n"}, - {"create table user(partition by (user,user))","CREATE TABLE user (\n\tPARTITION BY (user, user)\n);\n"}, - {"create table user(order by (user asc))","CREATE TABLE user (\n\tORDER BY (user ASC)\n);\n"}, - {"create table user(order by (user desc,user))","CREATE TABLE user (\n\tORDER BY (user DESC, user)\n);\n"}, + {"create table user(user int32)", "CREATE TABLE user (\n\tuser int32\n);\n"}, + {"create table user(user int32,user bool ?)", "CREATE TABLE user (\n\tuser int32,\n\tuser bool?\n);\n"}, + {"create table user(user int32) with (user=user)", "CREATE TABLE user (\n\tuser int32\n)\nWITH (user = user);\n"}, + {"create table user(primary key (user))", "CREATE TABLE user (\n\tPRIMARY KEY (user)\n);\n"}, + {"create table user(primary key (user,user))", "CREATE TABLE user (\n\tPRIMARY KEY (user, user)\n);\n"}, + {"create table user(partition by (user))", "CREATE TABLE user (\n\tPARTITION BY (user)\n);\n"}, + {"create table user(partition by (user,user))", "CREATE TABLE user (\n\tPARTITION BY (user, user)\n);\n"}, + {"create table user(order by (user asc))", "CREATE TABLE user (\n\tORDER BY (user ASC)\n);\n"}, + {"create table user(order by (user desc,user))", "CREATE TABLE user (\n\tORDER BY (user DESC, user)\n);\n"}, {"create table user(user int32) with (ttl=interval('P1D') on user as seconds)", - "CREATE TABLE user (\n\tuser int32\n)\nWITH (ttl = interval('P1D') ON user AS SECONDS);\n"}, + "CREATE TABLE user (\n\tuser int32\n)\nWITH (ttl = interval('P1D') ON user AS SECONDS);\n"}, {"create table user(user int32) with (ttl=interval('P1D') on user as MilliSeconds)", - "CREATE TABLE user (\n\tuser int32\n)\nWITH (ttl = interval('P1D') ON user AS MILLISECONDS);\n"}, + "CREATE TABLE user (\n\tuser int32\n)\nWITH (ttl = interval('P1D') ON user AS MILLISECONDS);\n"}, {"create table user(user int32) with (ttl=interval('P1D') on user as microSeconds)", - "CREATE TABLE user (\n\tuser int32\n)\nWITH (ttl = interval('P1D') ON user AS MICROSECONDS);\n"}, + "CREATE TABLE user (\n\tuser int32\n)\nWITH (ttl = interval('P1D') ON user AS MICROSECONDS);\n"}, {"create table user(user int32) with (ttl=interval('P1D') on user as nAnOsEcOnDs)", - "CREATE TABLE user (\n\tuser int32\n)\nWITH (ttl = interval('P1D') ON user AS NANOSECONDS);\n"}, + "CREATE TABLE user (\n\tuser int32\n)\nWITH (ttl = interval('P1D') ON user AS NANOSECONDS);\n"}, {"create table user(user int32) with (ttl=interval('P1D') delete on user as nAnOsEcOnDs)", - "CREATE TABLE user (\n\tuser int32\n)\nWITH (ttl = interval('P1D') DELETE ON user AS NANOSECONDS);\n"}, + "CREATE TABLE user (\n\tuser int32\n)\nWITH (ttl = interval('P1D') DELETE ON user AS NANOSECONDS);\n"}, {"create table user(user int32) with (ttl=interval('P1D')to external data source tier1 ,interval('P10D')delete on user as seconds)", - "CREATE TABLE user (\n" - "\tuser int32\n" - ")\n" - "WITH (ttl =\n" - "\tinterval('P1D') TO EXTERNAL DATA SOURCE tier1,\n" - "\tinterval('P10D') DELETE\n" - "ON user AS SECONDS);\n"}, + "CREATE TABLE user (\n" + "\tuser int32\n" + ")\n" + "WITH (ttl =\n" + "\tinterval('P1D') TO EXTERNAL DATA SOURCE tier1,\n" + "\tinterval('P10D') DELETE\n" + "ON user AS SECONDS);\n"}, {"create table user(index user global unique sync on (user,user) with (user=user,user=user))", - "CREATE TABLE user (\n\tINDEX user GLOBAL UNIQUE SYNC ON (user, user) WITH (user = user, user = user)\n);\n"}, + "CREATE TABLE user (\n\tINDEX user GLOBAL UNIQUE SYNC ON (user, user) WITH (user = user, user = user)\n);\n"}, {"create table user(index user global async on (user) with (user=user,))", - "CREATE TABLE user (\n\tINDEX user GLOBAL ASYNC ON (user) WITH (user = user,)\n);\n"}, + "CREATE TABLE user (\n\tINDEX user GLOBAL ASYNC ON (user) WITH (user = user,)\n);\n"}, {"create table user(index user local on (user) cover (user))", - "CREATE TABLE user (\n\tINDEX user LOCAL ON (user) COVER (user)\n);\n"}, + "CREATE TABLE user (\n\tINDEX user LOCAL ON (user) COVER (user)\n);\n"}, {"create table user(index user local on (user) cover (user,user))", - "CREATE TABLE user (\n\tINDEX user LOCAL ON (user) COVER (user, user)\n);\n"}, + "CREATE TABLE user (\n\tINDEX user LOCAL ON (user) COVER (user, user)\n);\n"}, {"create table user(index idx global using subtype on (col) cover (col) with (setting = foo, another_setting = bar));", - "CREATE TABLE user (\n\tINDEX idx GLOBAL USING subtype ON (col) COVER (col) WITH (setting = foo, another_setting = bar)\n);\n"}, + "CREATE TABLE user (\n\tINDEX idx GLOBAL USING subtype ON (col) COVER (col) WITH (setting = foo, another_setting = bar)\n);\n"}, {"create table user(family user (user='foo'))", - "CREATE TABLE user (\n\tFAMILY user (user = 'foo')\n);\n"}, + "CREATE TABLE user (\n\tFAMILY user (user = 'foo')\n);\n"}, {"create table user(family user (user='foo',user='bar'))", - "CREATE TABLE user (\n\tFAMILY user (user = 'foo', user = 'bar')\n);\n"}, + "CREATE TABLE user (\n\tFAMILY user (user = 'foo', user = 'bar')\n);\n"}, {"create table user(changefeed user with (user='foo'))", - "CREATE TABLE user (\n\tCHANGEFEED user WITH (user = 'foo')\n);\n"}, + "CREATE TABLE user (\n\tCHANGEFEED user WITH (user = 'foo')\n);\n"}, {"create table user(changefeed user with (user='foo',user='bar'))", - "CREATE TABLE user (\n\tCHANGEFEED user WITH (user = 'foo', user = 'bar')\n);\n"}, - {"create table user(user) AS SELECT 1","CREATE TABLE user (\n\tuser\n)\nAS\nSELECT\n\t1\n;\n"}, - {"create table user(user) AS VALUES (1), (2)","CREATE TABLE user (\n\tuser\n)\nAS\nVALUES\n\t(1),\n\t(2)\n;\n"}, + "CREATE TABLE user (\n\tCHANGEFEED user WITH (user = 'foo', user = 'bar')\n);\n"}, + {"create table user(user) AS SELECT 1", "CREATE TABLE user (\n\tuser\n)\nAS\nSELECT\n\t1\n;\n"}, + {"create table user(user) AS VALUES (1), (2)", "CREATE TABLE user (\n\tuser\n)\nAS\nVALUES\n\t(1),\n\t(2)\n;\n"}, {"create table user(foo int32, bar bool ?) inherits (s3:$cluster.xxx) partition by hash(a,b,hash) with (inherits=interval('PT1D') ON logical_time) tablestore tablestore", - "CREATE TABLE user (\n" - "\tfoo int32,\n" - "\tbar bool?\n" - ")\n" - "INHERITS (s3: $cluster.xxx)\n" - "PARTITION BY HASH (a, b, hash)\n" - "WITH (inherits = interval('PT1D') ON logical_time)\n" - "TABLESTORE tablestore;\n"}, + "CREATE TABLE user (\n" + "\tfoo int32,\n" + "\tbar bool?\n" + ")\n" + "INHERITS (s3: $cluster.xxx)\n" + "PARTITION BY HASH (a, b, hash)\n" + "WITH (inherits = interval('PT1D') ON logical_time)\n" + "TABLESTORE tablestore;\n"}, {"create table user(foo int32, bar bool ?) partition by hash(a,b,hash) with (tiering='some')", - "CREATE TABLE user (\n" - "\tfoo int32,\n" - "\tbar bool?\n" - ")\n" - "PARTITION BY HASH (a, b, hash)\n" - "WITH (tiering = 'some');\n"}, + "CREATE TABLE user (\n" + "\tfoo int32,\n" + "\tbar bool?\n" + ")\n" + "PARTITION BY HASH (a, b, hash)\n" + "WITH (tiering = 'some');\n"}, {"create table if not exists user(user int32)", "CREATE TABLE IF NOT EXISTS user (\n\tuser int32\n);\n"}, {"create temp table user(user int32)", "CREATE TEMP TABLE user (\n\tuser int32\n);\n"}, {"create temporary table user(user int32)", "CREATE TEMPORARY TABLE user (\n\tuser int32\n);\n"}, - {"create table user(user int32 (default 0, not null))","CREATE TABLE user (\n\tuser int32 (DEFAULT 0, NOT NULL)\n);\n"}, - {"create table user(user int32 (default 0, not null, family f))","CREATE TABLE user (\n\tuser int32 (DEFAULT 0, NOT NULL, FAMILY f)\n);\n"}, - {"create table user(user int32 (default 0, family f, not null))","CREATE TABLE user (\n\tuser int32 (DEFAULT 0, FAMILY f, NOT NULL)\n);\n"} - }; + {"create table user(user int32 (default 0, not null))", "CREATE TABLE user (\n\tuser int32 (DEFAULT 0, NOT NULL)\n);\n"}, + {"create table user(user int32 (default 0, not null, family f))", "CREATE TABLE user (\n\tuser int32 (DEFAULT 0, NOT NULL, FAMILY f)\n);\n"}, + {"create table user(user int32 (default 0, family f, not null))", "CREATE TABLE user (\n\tuser int32 (DEFAULT 0, FAMILY f, NOT NULL)\n);\n"}}; TSetup setup; setup.Run(cases); @@ -371,20 +365,19 @@ Y_UNIT_TEST(CreateTable) { Y_UNIT_TEST(ObjectOperations) { TCases cases = { {"alter oBject usEr (TYpe abcde) Set (a = b)", - "ALTER OBJECT usEr (TYPE abcde) SET (a = b);\n"}, + "ALTER OBJECT usEr (TYPE abcde) SET (a = b);\n"}, {"creAte oBject usEr (tYpe abcde) With (a = b)", - "CREATE OBJECT usEr (TYPE abcde) WITH (a = b);\n"}, - {"creAte oBject if not exIstS usEr (tYpe abcde) With (a = b)", - "CREATE OBJECT IF NOT EXISTS usEr (TYPE abcde) WITH (a = b);\n"}, + "CREATE OBJECT usEr (TYPE abcde) WITH (a = b);\n"}, + {"creAte oBject if not exIstS usEr (tYpe abcde) With (a = b)", + "CREATE OBJECT IF NOT EXISTS usEr (TYPE abcde) WITH (a = b);\n"}, {"creAte oBject usEr (tYpe abcde) With a = b", - "CREATE OBJECT usEr (TYPE abcde) WITH a = b;\n"}, + "CREATE OBJECT usEr (TYPE abcde) WITH a = b;\n"}, {"dRop oBject usEr (tYpe abcde) With (aeEE)", - "DROP OBJECT usEr (TYPE abcde) WITH (aeEE);\n"}, - {"dRop oBject If ExistS usEr (tYpe abcde) With (aeEE)", - "DROP OBJECT IF EXISTS usEr (TYPE abcde) WITH (aeEE);\n"}, + "DROP OBJECT usEr (TYPE abcde) WITH (aeEE);\n"}, + {"dRop oBject If ExistS usEr (tYpe abcde) With (aeEE)", + "DROP OBJECT IF EXISTS usEr (TYPE abcde) WITH (aeEE);\n"}, {"dRop oBject usEr (tYpe abcde) With aeEE", - "DROP OBJECT usEr (TYPE abcde) WITH aeEE;\n"} - }; + "DROP OBJECT usEr (TYPE abcde) WITH aeEE;\n"}}; TSetup setup; setup.Run(cases); @@ -393,10 +386,9 @@ Y_UNIT_TEST(ObjectOperations) { Y_UNIT_TEST(TableStoreOperations) { TCases cases = { {"alter tableStore uSer aDd column usEr int32", - "ALTER TABLESTORE uSer ADD COLUMN usEr int32;\n"}, - {"alter tableStore uSer drOp column usEr", - "ALTER TABLESTORE uSer DROP COLUMN usEr;\n"} - }; + "ALTER TABLESTORE uSer ADD COLUMN usEr int32;\n"}, + {"alter tableStore uSer drOp column usEr", + "ALTER TABLESTORE uSer DROP COLUMN usEr;\n"}}; TSetup setup; setup.Run(cases); @@ -405,21 +397,21 @@ Y_UNIT_TEST(TableStoreOperations) { Y_UNIT_TEST(ExternalDataSourceOperations) { TCases cases = { {"creAte exTernAl daTa SouRce usEr With (a = \"b\")", - "CREATE EXTERNAL DATA SOURCE usEr WITH (a = 'b');\n"}, + "CREATE EXTERNAL DATA SOURCE usEr WITH (a = 'b');\n"}, {"creAte exTernAl daTa SouRce if not exists usEr With (a = \"b\")", - "CREATE EXTERNAL DATA SOURCE IF NOT EXISTS usEr WITH (a = 'b');\n"}, + "CREATE EXTERNAL DATA SOURCE IF NOT EXISTS usEr WITH (a = 'b');\n"}, {"creAte oR rePlaCe exTernAl daTa SouRce usEr With (a = \"b\")", - "CREATE OR REPLACE EXTERNAL DATA SOURCE usEr WITH (a = 'b');\n"}, + "CREATE OR REPLACE EXTERNAL DATA SOURCE usEr WITH (a = 'b');\n"}, {"create external data source eds with (a=\"a\",b=\"b\",c = true)", - "CREATE EXTERNAL DATA SOURCE eds WITH (\n\ta = 'a',\n\tb = 'b',\n\tc = TRUE\n);\n"}, + "CREATE EXTERNAL DATA SOURCE eds WITH (\n\ta = 'a',\n\tb = 'b',\n\tc = TRUE\n);\n"}, {"alter external data source eds set a true, reset (b, c), set (x=y, z=false)", - "ALTER EXTERNAL DATA SOURCE eds\n\tSET a TRUE,\n\tRESET (b, c),\n\tSET (x = y, z = FALSE)\n;\n"}, + "ALTER EXTERNAL DATA SOURCE eds\n\tSET a TRUE,\n\tRESET (b, c),\n\tSET (x = y, z = FALSE)\n;\n"}, {"alter external data source eds reset (a), set (x=y)", - "ALTER EXTERNAL DATA SOURCE eds\n\tRESET (a),\n\tSET (x = y)\n;\n"}, + "ALTER EXTERNAL DATA SOURCE eds\n\tRESET (a),\n\tSET (x = y)\n;\n"}, {"dRop exTerNal Data SouRce usEr", - "DROP EXTERNAL DATA SOURCE usEr;\n"}, + "DROP EXTERNAL DATA SOURCE usEr;\n"}, {"dRop exTerNal Data SouRce if exists usEr", - "DROP EXTERNAL DATA SOURCE IF EXISTS usEr;\n"}, + "DROP EXTERNAL DATA SOURCE IF EXISTS usEr;\n"}, }; TSetup setup; @@ -429,13 +421,13 @@ Y_UNIT_TEST(ExternalDataSourceOperations) { Y_UNIT_TEST(AsyncReplication) { TCases cases = { {"create async replication user for table1 AS table2 with (user='foo')", - "CREATE ASYNC REPLICATION user FOR table1 AS table2 WITH (user = 'foo');\n"}, + "CREATE ASYNC REPLICATION user FOR table1 AS table2 WITH (user = 'foo');\n"}, {"alter async replication user set (user='foo')", - "ALTER ASYNC REPLICATION user SET (user = 'foo');\n"}, + "ALTER ASYNC REPLICATION user SET (user = 'foo');\n"}, {"drop async replication user", - "DROP ASYNC REPLICATION user;\n"}, + "DROP ASYNC REPLICATION user;\n"}, {"drop async replication user cascade", - "DROP ASYNC REPLICATION user CASCADE;\n"}, + "DROP ASYNC REPLICATION user CASCADE;\n"}, }; TSetup setup; @@ -445,17 +437,17 @@ Y_UNIT_TEST(AsyncReplication) { Y_UNIT_TEST(Transfer) { TCases cases = { {"alter transfer user set (user='foo')", - "ALTER TRANSFER user SET (user = 'foo');\n"}, + "ALTER TRANSFER user SET (user = 'foo');\n"}, {"drop transfer user", - "DROP TRANSFER user;\n"}, + "DROP TRANSFER user;\n"}, {"drop transfer user cascade", - "DROP TRANSFER user CASCADE;\n"}, + "DROP TRANSFER user CASCADE;\n"}, {"create transfer user from topic1 to table1 using ($x) -> { $y = cast($x as String); return $y ; }", - "CREATE TRANSFER user FROM topic1 TO table1 USING ($x) -> {\n $y = CAST($x AS String);\n RETURN $y;\n};\n"}, + "CREATE TRANSFER user FROM topic1 TO table1 USING ($x) -> {\n $y = CAST($x AS String);\n RETURN $y;\n};\n"}, {"create transfer user from topic1 to table1 using ($x) -> { $y = cast($x as String); return $y ; } with (user='foo')", - "CREATE TRANSFER user FROM topic1 TO table1 USING ($x) -> {\n $y = CAST($x AS String);\n RETURN $y;\n} WITH (user = 'foo');\n"}, + "CREATE TRANSFER user FROM topic1 TO table1 USING ($x) -> {\n $y = CAST($x AS String);\n RETURN $y;\n} WITH (user = 'foo');\n"}, {"create transfer user from topic1 to table1 using $xxx with (user='foo')", - "CREATE TRANSFER user FROM topic1 TO table1 USING $xxx WITH (user = 'foo');\n"}, + "CREATE TRANSFER user FROM topic1 TO table1 USING $xxx WITH (user = 'foo');\n"}, }; TSetup setup; @@ -465,19 +457,19 @@ Y_UNIT_TEST(Transfer) { Y_UNIT_TEST(ExternalTableOperations) { TCases cases = { {"creAte exTernAl TabLe usEr (a int) With (a = \"b\")", - "CREATE EXTERNAL TABLE usEr (\n\ta int\n)\nWITH (a = 'b');\n"}, + "CREATE EXTERNAL TABLE usEr (\n\ta int\n)\nWITH (a = 'b');\n"}, {"creAte oR rePlaCe exTernAl TabLe usEr (a int) With (a = \"b\")", - "CREATE OR REPLACE EXTERNAL TABLE usEr (\n\ta int\n)\nWITH (a = 'b');\n"}, + "CREATE OR REPLACE EXTERNAL TABLE usEr (\n\ta int\n)\nWITH (a = 'b');\n"}, {"creAte exTernAl TabLe iF NOt Exists usEr (a int) With (a = \"b\")", - "CREATE EXTERNAL TABLE IF NOT EXISTS usEr (\n\ta int\n)\nWITH (a = 'b');\n"}, + "CREATE EXTERNAL TABLE IF NOT EXISTS usEr (\n\ta int\n)\nWITH (a = 'b');\n"}, {"create external table user (a int) with (a=\"b\",c=\"d\")", - "CREATE EXTERNAL TABLE user (\n\ta int\n)\nWITH (\n\ta = 'b',\n\tc = 'd'\n);\n"}, + "CREATE EXTERNAL TABLE user (\n\ta int\n)\nWITH (\n\ta = 'b',\n\tc = 'd'\n);\n"}, {"alter external table user add column col1 int32, drop column col2, reset(prop), set (prop2 = 42, x=y), set a true", - "ALTER EXTERNAL TABLE user\n\tADD COLUMN col1 int32,\n\tDROP COLUMN col2,\n\tRESET (prop),\n\tSET (prop2 = 42, x = y),\n\tSET a TRUE\n;\n"}, + "ALTER EXTERNAL TABLE user\n\tADD COLUMN col1 int32,\n\tDROP COLUMN col2,\n\tRESET (prop),\n\tSET (prop2 = 42, x = y),\n\tSET a TRUE\n;\n"}, {"dRop exTerNal taBlE usEr", - "DROP EXTERNAL TABLE usEr;\n"}, + "DROP EXTERNAL TABLE usEr;\n"}, {"dRop exTerNal taBlE iF eXiStS usEr", - "DROP EXTERNAL TABLE IF EXISTS usEr;\n"}, + "DROP EXTERNAL TABLE IF EXISTS usEr;\n"}, }; TSetup setup; @@ -487,8 +479,7 @@ Y_UNIT_TEST(ExternalTableOperations) { Y_UNIT_TEST(TypeSelection) { TCases cases = { {"Select tYpe.* frOm Table tYpe", - "SELECT\n\ttYpe.*\nFROM\n\tTable tYpe\n;\n"} - }; + "SELECT\n\ttYpe.*\nFROM\n\tTable tYpe\n;\n"}}; TSetup setup; setup.Run(cases); @@ -497,77 +488,77 @@ Y_UNIT_TEST(TypeSelection) { Y_UNIT_TEST(AlterTable) { TCases cases = { {"alter table user add user int32", - "ALTER TABLE user\n\tADD user int32\n;\n"}, + "ALTER TABLE user\n\tADD user int32\n;\n"}, {"alter table user add user int32, add user bool ?", - "ALTER TABLE user\n\tADD user int32,\n\tADD user bool?\n;\n"}, + "ALTER TABLE user\n\tADD user int32,\n\tADD user bool?\n;\n"}, {"alter table user add column user int32", - "ALTER TABLE user\n\tADD COLUMN user int32\n;\n"}, + "ALTER TABLE user\n\tADD COLUMN user int32\n;\n"}, {"alter table user drop user", - "ALTER TABLE user\n\tDROP user\n;\n"}, + "ALTER TABLE user\n\tDROP user\n;\n"}, {"alter table user drop column user", - "ALTER TABLE user\n\tDROP COLUMN user\n;\n"}, + "ALTER TABLE user\n\tDROP COLUMN user\n;\n"}, {"alter table user alter column user set family user", - "ALTER TABLE user\n\tALTER COLUMN user SET FAMILY user\n;\n"}, + "ALTER TABLE user\n\tALTER COLUMN user SET FAMILY user\n;\n"}, {"alter table t alter column c drop not null", - "ALTER TABLE t\n\tALTER COLUMN c DROP NOT NULL\n;\n"}, + "ALTER TABLE t\n\tALTER COLUMN c DROP NOT NULL\n;\n"}, {"alter table t alter column c set not null", - "ALTER TABLE t\n\tALTER COLUMN c SET NOT NULL\n;\n"}, + "ALTER TABLE t\n\tALTER COLUMN c SET NOT NULL\n;\n"}, {"alter table user add family user(user='foo')", - "ALTER TABLE user\n\tADD FAMILY user (user = 'foo')\n;\n"}, + "ALTER TABLE user\n\tADD FAMILY user (user = 'foo')\n;\n"}, {"alter table user alter family user set user 'foo'", - "ALTER TABLE user\n\tALTER FAMILY user SET user 'foo'\n;\n"}, + "ALTER TABLE user\n\tALTER FAMILY user SET user 'foo'\n;\n"}, {"alter table user set user user", - "ALTER TABLE user\n\tSET user user\n;\n"}, + "ALTER TABLE user\n\tSET user user\n;\n"}, {"alter table user set (user=user)", - "ALTER TABLE user\n\tSET (user = user)\n;\n"}, + "ALTER TABLE user\n\tSET (user = user)\n;\n"}, {"alter table user set (user=user,user=user)", - "ALTER TABLE user\n\tSET (user = user, user = user)\n;\n"}, + "ALTER TABLE user\n\tSET (user = user, user = user)\n;\n"}, {"alter table user reset(user)", - "ALTER TABLE user\n\tRESET (user)\n;\n"}, + "ALTER TABLE user\n\tRESET (user)\n;\n"}, {"alter table user reset(user, user)", - "ALTER TABLE user\n\tRESET (user, user)\n;\n"}, + "ALTER TABLE user\n\tRESET (user, user)\n;\n"}, {"alter table user add index user local on (user)", - "ALTER TABLE user\n\tADD INDEX user LOCAL ON (user)\n;\n"}, + "ALTER TABLE user\n\tADD INDEX user LOCAL ON (user)\n;\n"}, {"alter table user alter index idx set setting 'foo'", - "ALTER TABLE user\n\tALTER INDEX idx SET setting 'foo'\n;\n"}, + "ALTER TABLE user\n\tALTER INDEX idx SET setting 'foo'\n;\n"}, {"alter table user alter index idx set (setting = 'foo', another_setting = 'bar')", - "ALTER TABLE user\n\tALTER INDEX idx SET (setting = 'foo', another_setting = 'bar')\n;\n"}, + "ALTER TABLE user\n\tALTER INDEX idx SET (setting = 'foo', another_setting = 'bar')\n;\n"}, {"alter table user alter index idx reset (setting, another_setting)", - "ALTER TABLE user\n\tALTER INDEX idx RESET (setting, another_setting)\n;\n"}, + "ALTER TABLE user\n\tALTER INDEX idx RESET (setting, another_setting)\n;\n"}, {"alter table user add index idx global using subtype on (col) cover (col) with (setting = foo, another_setting = 'bar');", - "ALTER TABLE user\n\tADD INDEX idx GLOBAL USING subtype ON (col) COVER (col) WITH (setting = foo, another_setting = 'bar')\n;\n"}, + "ALTER TABLE user\n\tADD INDEX idx GLOBAL USING subtype ON (col) COVER (col) WITH (setting = foo, another_setting = 'bar')\n;\n"}, {"alter table user drop index user", - "ALTER TABLE user\n\tDROP INDEX user\n;\n"}, + "ALTER TABLE user\n\tDROP INDEX user\n;\n"}, {"alter table user rename to user", - "ALTER TABLE user\n\tRENAME TO user\n;\n"}, + "ALTER TABLE user\n\tRENAME TO user\n;\n"}, {"alter table user add changefeed user with (user = 'foo')", - "ALTER TABLE user\n\tADD CHANGEFEED user WITH (user = 'foo')\n;\n"}, + "ALTER TABLE user\n\tADD CHANGEFEED user WITH (user = 'foo')\n;\n"}, {"alter table user alter changefeed user disable", - "ALTER TABLE user\n\tALTER CHANGEFEED user DISABLE\n;\n"}, + "ALTER TABLE user\n\tALTER CHANGEFEED user DISABLE\n;\n"}, {"alter table user alter changefeed user set(user='foo')", - "ALTER TABLE user\n\tALTER CHANGEFEED user SET (user = 'foo')\n;\n"}, + "ALTER TABLE user\n\tALTER CHANGEFEED user SET (user = 'foo')\n;\n"}, {"alter table user drop changefeed user", - "ALTER TABLE user\n\tDROP CHANGEFEED user\n;\n"}, + "ALTER TABLE user\n\tDROP CHANGEFEED user\n;\n"}, {"alter table user add changefeed user with (initial_scan = tRUe)", - "ALTER TABLE user\n\tADD CHANGEFEED user WITH (initial_scan = TRUE)\n;\n"}, + "ALTER TABLE user\n\tADD CHANGEFEED user WITH (initial_scan = TRUE)\n;\n"}, {"alter table user add changefeed user with (initial_scan = FaLsE)", - "ALTER TABLE user\n\tADD CHANGEFEED user WITH (initial_scan = FALSE)\n;\n"}, + "ALTER TABLE user\n\tADD CHANGEFEED user WITH (initial_scan = FALSE)\n;\n"}, {"alter table user add changefeed user with (retention_period = Interval(\"P1D\"))", - "ALTER TABLE user\n\tADD CHANGEFEED user WITH (retention_period = Interval('P1D'))\n;\n"}, + "ALTER TABLE user\n\tADD CHANGEFEED user WITH (retention_period = Interval('P1D'))\n;\n"}, {"alter table user add changefeed user with (virtual_timestamps = TruE)", - "ALTER TABLE user\n\tADD CHANGEFEED user WITH (virtual_timestamps = TRUE)\n;\n"}, + "ALTER TABLE user\n\tADD CHANGEFEED user WITH (virtual_timestamps = TRUE)\n;\n"}, {"alter table user add changefeed user with (virtual_timestamps = fAlSe)", - "ALTER TABLE user\n\tADD CHANGEFEED user WITH (virtual_timestamps = FALSE)\n;\n"}, + "ALTER TABLE user\n\tADD CHANGEFEED user WITH (virtual_timestamps = FALSE)\n;\n"}, {"alter table user add changefeed user with (barriers_interval = Interval(\"PT1S\"))", - "ALTER TABLE user\n\tADD CHANGEFEED user WITH (barriers_interval = Interval('PT1S'))\n;\n"}, + "ALTER TABLE user\n\tADD CHANGEFEED user WITH (barriers_interval = Interval('PT1S'))\n;\n"}, {"alter table user add changefeed user with (schema_changes = TruE)", - "ALTER TABLE user\n\tADD CHANGEFEED user WITH (schema_changes = TRUE)\n;\n"}, + "ALTER TABLE user\n\tADD CHANGEFEED user WITH (schema_changes = TRUE)\n;\n"}, {"alter table user add changefeed user with (schema_changes = fAlSe)", - "ALTER TABLE user\n\tADD CHANGEFEED user WITH (schema_changes = FALSE)\n;\n"}, + "ALTER TABLE user\n\tADD CHANGEFEED user WITH (schema_changes = FALSE)\n;\n"}, {"alter table user add changefeed user with (topic_min_active_partitions = 1)", - "ALTER TABLE user\n\tADD CHANGEFEED user WITH (topic_min_active_partitions = 1)\n;\n"}, + "ALTER TABLE user\n\tADD CHANGEFEED user WITH (topic_min_active_partitions = 1)\n;\n"}, {"alter table user add changefeed user with (topic_auto_partitioning = 'ENABLED', topic_min_active_partitions = 1, topic_max_active_partitions = 7)", - "ALTER TABLE user\n\tADD CHANGEFEED user WITH (topic_auto_partitioning = 'ENABLED', topic_min_active_partitions = 1, topic_max_active_partitions = 7)\n;\n"}, + "ALTER TABLE user\n\tADD CHANGEFEED user WITH (topic_auto_partitioning = 'ENABLED', topic_min_active_partitions = 1, topic_max_active_partitions = 7)\n;\n"}, }; TSetup setup; @@ -577,15 +568,15 @@ Y_UNIT_TEST(AlterTable) { Y_UNIT_TEST(CreateTopic) { TCases cases = { {"create topic topic1", - "CREATE TOPIC topic1;\n"}, + "CREATE TOPIC topic1;\n"}, {"create topic topic1 (consumer c1)", - "CREATE TOPIC topic1 (\n\tCONSUMER c1\n);\n"}, + "CREATE TOPIC topic1 (\n\tCONSUMER c1\n);\n"}, {"create topic topic1 (consumer c1, consumer c2 with (important = True))", - "CREATE TOPIC topic1 (\n\tCONSUMER c1,\n\tCONSUMER c2 WITH (important = TRUE)\n);\n"}, + "CREATE TOPIC topic1 (\n\tCONSUMER c1,\n\tCONSUMER c2 WITH (important = TRUE)\n);\n"}, {"create topic topic1 (consumer c1) with (partition_count_limit = 5)", - "CREATE TOPIC topic1 (\n\tCONSUMER c1\n) WITH (\n\tpartition_count_limit = 5\n);\n"}, + "CREATE TOPIC topic1 (\n\tCONSUMER c1\n) WITH (\n\tpartition_count_limit = 5\n);\n"}, {"create topic topic1 (consumer c1) with (availability_period=Interval('PT9H'))", - "CREATE TOPIC topic1 (\n\tCONSUMER c1\n) WITH (\n\tavailability_period = Interval('PT9H')\n);\n"}, + "CREATE TOPIC topic1 (\n\tCONSUMER c1\n) WITH (\n\tavailability_period = Interval('PT9H')\n);\n"}, }; TSetup setup; @@ -595,15 +586,15 @@ Y_UNIT_TEST(CreateTopic) { Y_UNIT_TEST(AlterTopic) { TCases cases = { {"alter topic topic1 alter consumer c1 set (important = false)", - "ALTER TOPIC topic1\n\tALTER CONSUMER c1 SET (important = FALSE)\n;\n"}, + "ALTER TOPIC topic1\n\tALTER CONSUMER c1 SET (important = FALSE)\n;\n"}, {"alter topic topic1 alter consumer c1 set (important = false), alter consumer c2 reset (read_from)", - "ALTER TOPIC topic1\n\tALTER CONSUMER c1 SET (important = FALSE),\n\tALTER CONSUMER c2 RESET (read_from)\n;\n"}, + "ALTER TOPIC topic1\n\tALTER CONSUMER c1 SET (important = FALSE),\n\tALTER CONSUMER c2 RESET (read_from)\n;\n"}, {"alter topic topic1 add consumer c1, drop consumer c2", - "ALTER TOPIC topic1\n\tADD CONSUMER c1,\n\tDROP CONSUMER c2\n;\n"}, + "ALTER TOPIC topic1\n\tADD CONSUMER c1,\n\tDROP CONSUMER c2\n;\n"}, {"alter topic topic1 set (supported_codecs = 'RAW'), RESET (retention_period)", - "ALTER TOPIC topic1\n\tSET (supported_codecs = 'RAW'),\n\tRESET (retention_period)\n;\n"}, + "ALTER TOPIC topic1\n\tSET (supported_codecs = 'RAW'),\n\tRESET (retention_period)\n;\n"}, {"alter topic topic1 alter consumer c1 set (availability_period=Interval('PT9H')), alter consumer c2 reset (availability_period)", - "ALTER TOPIC topic1\n\tALTER CONSUMER c1 SET (availability_period = Interval('PT9H')),\n\tALTER CONSUMER c2 RESET (availability_period)\n;\n"}, + "ALTER TOPIC topic1\n\tALTER CONSUMER c1 SET (availability_period = Interval('PT9H')),\n\tALTER CONSUMER c2 RESET (availability_period)\n;\n"}, }; TSetup setup; @@ -613,7 +604,7 @@ Y_UNIT_TEST(AlterTopic) { Y_UNIT_TEST(DropTopic) { TCases cases = { {"drop topic topic1", - "DROP TOPIC topic1;\n"}, + "DROP TOPIC topic1;\n"}, }; TSetup setup; @@ -623,11 +614,11 @@ Y_UNIT_TEST(DropTopic) { Y_UNIT_TEST(TopicExistsStatement) { TCases cases = { {"drop topic if exists topic1", - "DROP TOPIC IF EXISTS topic1;\n"}, + "DROP TOPIC IF EXISTS topic1;\n"}, {"create topic if not exists topic1 with (partition_count_limit = 5)", - "CREATE TOPIC IF NOT EXISTS topic1 WITH (\n\tpartition_count_limit = 5\n);\n"}, + "CREATE TOPIC IF NOT EXISTS topic1 WITH (\n\tpartition_count_limit = 5\n);\n"}, {"alter topic if exists topic1 alter consumer c1 set (important = false)", - "ALTER TOPIC IF EXISTS topic1\n\tALTER CONSUMER c1 SET (important = FALSE)\n;\n"}, + "ALTER TOPIC IF EXISTS topic1\n\tALTER CONSUMER c1 SET (important = FALSE)\n;\n"}, }; TSetup setup; @@ -637,9 +628,9 @@ Y_UNIT_TEST(TopicExistsStatement) { Y_UNIT_TEST(Do) { TCases cases = { {"do $a(1,2,3)", - "DO\n\t$a(1, 2, 3)\n;\n"}, + "DO\n\t$a(1, 2, 3)\n;\n"}, {"do begin values(1); end do;", - "DO BEGIN\n\tVALUES\n\t\t(1)\n\t;\nEND DO;\n"}, + "DO BEGIN\n\tVALUES\n\t\t(1)\n\t;\nEND DO;\n"}, }; TSetup setup; @@ -649,46 +640,46 @@ Y_UNIT_TEST(Do) { Y_UNIT_TEST(DefineActionOrSubquery) { TCases cases = { {"define action $a() as " - "define action $b() as " - "values(1); " - "end define; " - "define subquery $c() as " - "select 1; " - "end define; " - "do $b(); " - "process $c(); " - "end define", - "DEFINE ACTION $a() AS\n\tDEFINE ACTION $b() AS\n\t\t" - "VALUES\n\t\t\t(1)\n\t\t;\n\tEND DEFINE;\n\n\t" - "DEFINE SUBQUERY $c() AS\n\t\tSELECT\n\t\t\t1\n\t\t;\n\t" - "END DEFINE;\n\tDO\n\t\t$b()\n\t;\n\n\tPROCESS $c();\nEND DEFINE;\n"}, + "define action $b() as " + "values(1); " + "end define; " + "define subquery $c() as " + "select 1; " + "end define; " + "do $b(); " + "process $c(); " + "end define", + "DEFINE ACTION $a() AS\n\tDEFINE ACTION $b() AS\n\t\t" + "VALUES\n\t\t\t(1)\n\t\t;\n\tEND DEFINE;\n\n\t" + "DEFINE SUBQUERY $c() AS\n\t\tSELECT\n\t\t\t1\n\t\t;\n\t" + "END DEFINE;\n\tDO\n\t\t$b()\n\t;\n\n\tPROCESS $c();\nEND DEFINE;\n"}, {"define action $foo($bar) as;" - "$a = 10;; " - "$b = 20;;; " - "$c = $a + $b " - "end define", - "DEFINE ACTION $foo($bar) AS\n\t" - "$a = 10;\n\t" - "$b = 20;\n\t" - "$c = $a + $b;\n" - "END DEFINE;\n"}, + "$a = 10;; " + "$b = 20;;; " + "$c = $a + $b " + "end define", + "DEFINE ACTION $foo($bar) AS\n\t" + "$a = 10;\n\t" + "$b = 20;\n\t" + "$c = $a + $b;\n" + "END DEFINE;\n"}, {"define subquery $s() as;" - "select * from $t1 " - "union all select * from $t2 " - "end define", - "DEFINE SUBQUERY $s() AS\n\t" - "SELECT\n\t\t*\n\tFROM\n\t\t$t1\n\t" - "UNION ALL\n\t" - "SELECT\n\t\t*\n\tFROM\n\t\t$t2\n\t;\n" - "END DEFINE;\n"}, + "select * from $t1 " + "union all select * from $t2 " + "end define", + "DEFINE SUBQUERY $s() AS\n\t" + "SELECT\n\t\t*\n\tFROM\n\t\t$t1\n\t" + "UNION ALL\n\t" + "SELECT\n\t\t*\n\tFROM\n\t\t$t2\n\t;\n" + "END DEFINE;\n"}, {"define subquery $s() as $t = select * from $a end define", - "DEFINE SUBQUERY $s() AS\n\t" - "$t = (\n\t\tSELECT\n\t\t\t*\n\t\tFROM\n\t\t\t$a\n\t);\n" - "END DEFINE;\n"}, + "DEFINE SUBQUERY $s() AS\n\t" + "$t = (\n\t\tSELECT\n\t\t\t*\n\t\tFROM\n\t\t\t$a\n\t);\n" + "END DEFINE;\n"}, {"define subquery $s() as; $t = select * from $a; end define", - "DEFINE SUBQUERY $s() AS\n\t" - "$t = (\n\t\tSELECT\n\t\t\t*\n\t\tFROM\n\t\t\t$a\n\t);\n" - "END DEFINE;\n"}, + "DEFINE SUBQUERY $s() AS\n\t" + "$t = (\n\t\tSELECT\n\t\t\t*\n\t\tFROM\n\t\t\t$a\n\t);\n" + "END DEFINE;\n"}, }; TSetup setup; @@ -698,21 +689,21 @@ Y_UNIT_TEST(DefineActionOrSubquery) { Y_UNIT_TEST(If) { TCases cases = { {"evaluate if 1=1 do $a()", - "EVALUATE IF 1 == 1 DO\n\t$a()\n;\n"}, + "EVALUATE IF 1 == 1 DO\n\t$a()\n;\n"}, {"evaluate if 1=1 do $a() else do $b()", - "EVALUATE IF 1 == 1 DO\n\t$a()\nELSE DO\n\t$b()\n;\n"}, + "EVALUATE IF 1 == 1 DO\n\t$a()\nELSE DO\n\t$b()\n;\n"}, {"evaluate if 1=1 do begin select 1; end do", - "EVALUATE IF 1 == 1 DO BEGIN\n\tSELECT\n\t\t1\n\t;\nEND DO;\n"}, + "EVALUATE IF 1 == 1 DO BEGIN\n\tSELECT\n\t\t1\n\t;\nEND DO;\n"}, {"evaluate if 1=1 do begin select 1; end do else do begin select 2; end do", - "EVALUATE IF 1 == 1 DO BEGIN\n\tSELECT\n\t\t1\n\t;\nEND DO " - "ELSE DO BEGIN\n\tSELECT\n\t\t2\n\t;\nEND DO;\n"}, + "EVALUATE IF 1 == 1 DO BEGIN\n\tSELECT\n\t\t1\n\t;\nEND DO " + "ELSE DO BEGIN\n\tSELECT\n\t\t2\n\t;\nEND DO;\n"}, {"evaluate if 1=1 do begin; select 1 end do else do begin select 2;; select 3 end do", - "EVALUATE IF 1 == 1 DO BEGIN\n\tSELECT\n\t\t1\n\t;\nEND DO ELSE DO BEGIN\n\t" - "SELECT\n\t\t2\n\t;\n\n\tSELECT\n\t\t3\n\t;\nEND DO;\n"}, + "EVALUATE IF 1 == 1 DO BEGIN\n\tSELECT\n\t\t1\n\t;\nEND DO ELSE DO BEGIN\n\t" + "SELECT\n\t\t2\n\t;\n\n\tSELECT\n\t\t3\n\t;\nEND DO;\n"}, {"evaluate if 1=1 do begin (select 1) end do", - "EVALUATE IF 1 == 1 DO BEGIN\n\t(\n\t\tSELECT\n\t\t\t1\n\t);\nEND DO;\n"}, + "EVALUATE IF 1 == 1 DO BEGIN\n\t(\n\t\tSELECT\n\t\t\t1\n\t);\nEND DO;\n"}, {"evaluate if 1=1 do begin $a = select * from $begin; $end = 1; end do", - "EVALUATE IF 1 == 1 DO BEGIN\n\t$a = (\n\t\tSELECT\n\t\t\t*\n\t\tFROM\n\t\t\t$begin\n\t);\n\t$end = 1;\nEND DO;\n"}, + "EVALUATE IF 1 == 1 DO BEGIN\n\t$a = (\n\t\tSELECT\n\t\t\t*\n\t\tFROM\n\t\t\t$begin\n\t);\n\t$end = 1;\nEND DO;\n"}, }; TSetup setup; @@ -722,21 +713,21 @@ Y_UNIT_TEST(If) { Y_UNIT_TEST(For) { TCases cases = { {"evaluate for $x in [] do $a($x)", - "EVALUATE FOR $x IN [] DO\n\t$a($x)\n;\n"}, + "EVALUATE FOR $x IN [] DO\n\t$a($x)\n;\n"}, {"evaluate for $x in [] do $a($x) else do $b()", - "EVALUATE FOR $x IN [] DO\n\t$a($x)\nELSE DO\n\t$b()\n;\n"}, + "EVALUATE FOR $x IN [] DO\n\t$a($x)\nELSE DO\n\t$b()\n;\n"}, {"evaluate for $x in [] do begin select $x; end do", - "EVALUATE FOR $x IN [] DO BEGIN\n\tSELECT\n\t\t$x\n\t;\nEND DO;\n"}, + "EVALUATE FOR $x IN [] DO BEGIN\n\tSELECT\n\t\t$x\n\t;\nEND DO;\n"}, {"evaluate for $x in [] do begin select $x; end do else do begin select 2; end do", - "EVALUATE FOR $x IN [] DO BEGIN\n\tSELECT\n\t\t$x\n\t;\nEND DO ELSE DO BEGIN\n\tSELECT\n\t\t2\n\t;\nEND DO;\n"}, + "EVALUATE FOR $x IN [] DO BEGIN\n\tSELECT\n\t\t$x\n\t;\nEND DO ELSE DO BEGIN\n\tSELECT\n\t\t2\n\t;\nEND DO;\n"}, {"evaluate parallel for $x in [] do $a($x)", - "EVALUATE PARALLEL FOR $x IN [] DO\n\t$a($x)\n;\n"}, + "EVALUATE PARALLEL FOR $x IN [] DO\n\t$a($x)\n;\n"}, {"evaluate for $x in [] do begin; select $x;; select $y end do", - "EVALUATE FOR $x IN [] DO BEGIN\n\tSELECT\n\t\t$x\n\t;\n\n\tSELECT\n\t\t$y\n\t;\nEND DO;\n"}, + "EVALUATE FOR $x IN [] DO BEGIN\n\tSELECT\n\t\t$x\n\t;\n\n\tSELECT\n\t\t$y\n\t;\nEND DO;\n"}, {"evaluate for $x in [] do begin (select 1) end do", - "EVALUATE FOR $x IN [] DO BEGIN\n\t(\n\t\tSELECT\n\t\t\t1\n\t);\nEND DO;\n"}, + "EVALUATE FOR $x IN [] DO BEGIN\n\t(\n\t\tSELECT\n\t\t\t1\n\t);\nEND DO;\n"}, {"evaluate for $x in [] do begin $a = select * from $begin; $end = 1; end do", - "EVALUATE FOR $x IN [] DO BEGIN\n\t$a = (\n\t\tSELECT\n\t\t\t*\n\t\tFROM\n\t\t\t$begin\n\t);\n\t$end = 1;\nEND DO;\n"}, + "EVALUATE FOR $x IN [] DO BEGIN\n\t$a = (\n\t\tSELECT\n\t\t\t*\n\t\tFROM\n\t\t\t$begin\n\t);\n\t$end = 1;\nEND DO;\n"}, }; TSetup setup; @@ -746,29 +737,29 @@ Y_UNIT_TEST(For) { Y_UNIT_TEST(Update) { TCases cases = { {"update user on default values", - "UPDATE user\nON DEFAULT VALUES;\n"}, + "UPDATE user\nON DEFAULT VALUES;\n"}, {"update user on values (1),(2)", - "UPDATE user\nON\nVALUES\n\t(1),\n\t(2)\n;\n"}, + "UPDATE user\nON\nVALUES\n\t(1),\n\t(2)\n;\n"}, {"update user on select 1 as x, 2 as y", - "UPDATE user\nON\nSELECT\n\t1 AS x,\n\t2 AS y\n;\n"}, + "UPDATE user\nON\nSELECT\n\t1 AS x,\n\t2 AS y\n;\n"}, {"update user on (x) values (1),(2),(3)", - "UPDATE user\nON (\n\tx\n)\nVALUES\n\t(1),\n\t(2),\n\t(3)\n;\n"}, + "UPDATE user\nON (\n\tx\n)\nVALUES\n\t(1),\n\t(2),\n\t(3)\n;\n"}, {"update user on (x,y) values (1,2),(2,3),(3,4)", - "UPDATE user\nON (\n\tx,\n\ty\n)\nVALUES\n\t(1, 2),\n\t(2, 3),\n\t(3, 4)\n;\n"}, + "UPDATE user\nON (\n\tx,\n\ty\n)\nVALUES\n\t(1, 2),\n\t(2, 3),\n\t(3, 4)\n;\n"}, {"update user on (x) select 1", - "UPDATE user\nON (\n\tx\n)\nSELECT\n\t1\n;\n"}, + "UPDATE user\nON (\n\tx\n)\nSELECT\n\t1\n;\n"}, {"update user on (x,y) select 1,2", - "UPDATE user\nON (\n\tx,\n\ty\n)\nSELECT\n\t1,\n\t2\n;\n"}, + "UPDATE user\nON (\n\tx,\n\ty\n)\nSELECT\n\t1,\n\t2\n;\n"}, {"update user set x=1", - "UPDATE user\nSET\n\tx = 1\n;\n"}, + "UPDATE user\nSET\n\tx = 1\n;\n"}, {"update user set (x)=(1)", - "UPDATE user\nSET\n(\n\tx\n) = (\n\t1\n);\n"}, + "UPDATE user\nSET\n(\n\tx\n) = (\n\t1\n);\n"}, {"update user set (x,y)=(1,2)", - "UPDATE user\nSET\n(\n\tx,\n\ty\n) = (\n\t1,\n\t2\n);\n"}, + "UPDATE user\nSET\n(\n\tx,\n\ty\n) = (\n\t1,\n\t2\n);\n"}, {"update user set (x,y)=(select 1,2)", - "UPDATE user\nSET\n(\n\tx,\n\ty\n) = (\n\tSELECT\n\t\t1,\n\t\t2\n);\n"}, + "UPDATE user\nSET\n(\n\tx,\n\ty\n) = (\n\tSELECT\n\t\t1,\n\t\t2\n);\n"}, {"update user set x=1,y=2 where z=3", - "UPDATE user\nSET\n\tx = 1,\n\ty = 2\nWHERE z == 3;\n"}, + "UPDATE user\nSET\n\tx = 1,\n\ty = 2\nWHERE z == 3;\n"}, }; TSetup setup; @@ -778,15 +769,15 @@ Y_UNIT_TEST(Update) { Y_UNIT_TEST(Delete) { TCases cases = { {"delete from user", - "DELETE FROM user;\n"}, + "DELETE FROM user;\n"}, {"delete from user where 1=1", - "DELETE FROM user\nWHERE 1 == 1;\n"}, + "DELETE FROM user\nWHERE 1 == 1;\n"}, {"delete from user on select 1 as x, 2 as y", - "DELETE FROM user\nON\nSELECT\n\t1 AS x,\n\t2 AS y\n;\n"}, + "DELETE FROM user\nON\nSELECT\n\t1 AS x,\n\t2 AS y\n;\n"}, {"delete from user on (x) values (1)", - "DELETE FROM user\nON (\n\tx\n)\nVALUES\n\t(1)\n;\n"}, + "DELETE FROM user\nON (\n\tx\n)\nVALUES\n\t(1)\n;\n"}, {"delete from user on (x,y) values (1,2), (3,4)", - "DELETE FROM user\nON (\n\tx,\n\ty\n)\nVALUES\n\t(1, 2),\n\t(3, 4)\n;\n"}, + "DELETE FROM user\nON (\n\tx,\n\ty\n)\nVALUES\n\t(1, 2),\n\t(3, 4)\n;\n"}, }; TSetup setup; @@ -796,39 +787,39 @@ Y_UNIT_TEST(Delete) { Y_UNIT_TEST(Into) { TCases cases = { {"insert into user select 1 as x", - "INSERT INTO user\nSELECT\n\t1 AS x\n;\n"}, + "INSERT INTO user\nSELECT\n\t1 AS x\n;\n"}, {"insert or abort into user select 1 as x", - "INSERT OR ABORT INTO user\nSELECT\n\t1 AS x\n;\n"}, + "INSERT OR ABORT INTO user\nSELECT\n\t1 AS x\n;\n"}, {"insert or revert into user select 1 as x", - "INSERT OR REVERT INTO user\nSELECT\n\t1 AS x\n;\n"}, + "INSERT OR REVERT INTO user\nSELECT\n\t1 AS x\n;\n"}, {"insert or ignore into user select 1 as x", - "INSERT OR IGNORE INTO user\nSELECT\n\t1 AS x\n;\n"}, + "INSERT OR IGNORE INTO user\nSELECT\n\t1 AS x\n;\n"}, {"upsert into user select 1 as x", - "UPSERT INTO user\nSELECT\n\t1 AS x\n;\n"}, + "UPSERT INTO user\nSELECT\n\t1 AS x\n;\n"}, {"replace into user select 1 as x", - "REPLACE INTO user\nSELECT\n\t1 AS x\n;\n"}, + "REPLACE INTO user\nSELECT\n\t1 AS x\n;\n"}, {"insert into user(x) values (1)", - "INSERT INTO user (\n\tx\n)\nVALUES\n\t(1)\n;\n"}, + "INSERT INTO user (\n\tx\n)\nVALUES\n\t(1)\n;\n"}, {"insert into user(x,y) values (1,2)", - "INSERT INTO user (\n\tx,\n\ty\n)\nVALUES\n\t(1, 2)\n;\n"}, + "INSERT INTO user (\n\tx,\n\ty\n)\nVALUES\n\t(1, 2)\n;\n"}, {"insert into plato.user select 1 as x", - "INSERT INTO plato.user\nSELECT\n\t1 AS x\n;\n"}, + "INSERT INTO plato.user\nSELECT\n\t1 AS x\n;\n"}, {"insert into @user select 1 as x", - "INSERT INTO @user\nSELECT\n\t1 AS x\n;\n"}, + "INSERT INTO @user\nSELECT\n\t1 AS x\n;\n"}, {"insert into $user select 1 as x", - "INSERT INTO $user\nSELECT\n\t1 AS x\n;\n"}, + "INSERT INTO $user\nSELECT\n\t1 AS x\n;\n"}, {"insert into @$user select 1 as x", - "INSERT INTO @$user\nSELECT\n\t1 AS x\n;\n"}, + "INSERT INTO @$user\nSELECT\n\t1 AS x\n;\n"}, {"upsert into user erase by (x,y) values (1)", - "UPSERT INTO user\n\tERASE BY (\n\t\tx,\n\t\ty\n\t)\nVALUES\n\t(1)\n;\n"}, + "UPSERT INTO user\n\tERASE BY (\n\t\tx,\n\t\ty\n\t)\nVALUES\n\t(1)\n;\n"}, {"insert into user with truncate select 1 as x", - "INSERT INTO user WITH truncate\nSELECT\n\t1 AS x\n;\n"}, + "INSERT INTO user WITH truncate\nSELECT\n\t1 AS x\n;\n"}, {"insert into user with (truncate,inferscheme='1') select 1 as x", - "INSERT INTO user WITH (\n\ttruncate,\n\tinferscheme = '1'\n)\nSELECT\n\t1 AS x\n;\n"}, + "INSERT INTO user WITH (\n\ttruncate,\n\tinferscheme = '1'\n)\nSELECT\n\t1 AS x\n;\n"}, {"insert into user with schema Struct<user:int32> select 1 as user", - "INSERT INTO user WITH SCHEMA Struct<user: int32>\nSELECT\n\t1 AS user\n;\n"}, + "INSERT INTO user WITH SCHEMA Struct<user: int32>\nSELECT\n\t1 AS user\n;\n"}, {"insert into user with schema (int32 as user) select 1 as user", - "INSERT INTO user WITH SCHEMA (int32 AS user)\nSELECT\n\t1 AS user\n;\n"}, + "INSERT INTO user WITH SCHEMA (int32 AS user)\nSELECT\n\t1 AS user\n;\n"}, }; TSetup setup; @@ -838,21 +829,21 @@ Y_UNIT_TEST(Into) { Y_UNIT_TEST(Process) { TCases cases = { {"process user", - "PROCESS user;\n"}, + "PROCESS user;\n"}, {"process user using $f() as user", - "PROCESS user\nUSING $f() AS user;\n"}, + "PROCESS user\nUSING $f() AS user;\n"}, {"process user,user using $f()", - "PROCESS user, user\nUSING $f();\n"}, + "PROCESS user, user\nUSING $f();\n"}, {"process user using $f() where 1=1 having 1=1 assume order by user", - "PROCESS user\nUSING $f()\nWHERE\n\t1 == 1\nHAVING\n\t1 == 1\nASSUME ORDER BY\n\tuser\n;\n"}, + "PROCESS user\nUSING $f()\nWHERE\n\t1 == 1\nHAVING\n\t1 == 1\nASSUME ORDER BY\n\tuser\n;\n"}, {"process user using $f() union all process user using $f()", - "PROCESS user\nUSING $f()\nUNION ALL\nPROCESS user\nUSING $f();\n"}, + "PROCESS user\nUSING $f()\nUNION ALL\nPROCESS user\nUSING $f();\n"}, {"process user using $f() with foo=bar", - "PROCESS user\nUSING $f()\nWITH foo = bar;\n"}, + "PROCESS user\nUSING $f()\nWITH foo = bar;\n"}, {"discard process user using $f()", - "DISCARD PROCESS user\nUSING $f();\n"}, + "DISCARD PROCESS user\nUSING $f();\n"}, {"process user using $f() into result user", - "PROCESS user\nUSING $f()\nINTO RESULT user;\n"}, + "PROCESS user\nUSING $f()\nINTO RESULT user;\n"}, }; TSetup setup; @@ -862,25 +853,25 @@ Y_UNIT_TEST(Process) { Y_UNIT_TEST(Reduce) { TCases cases = { {"reduce user on user using $f()", - "REDUCE user\nON\n\tuser\nUSING $f();\n"}, + "REDUCE user\nON\n\tuser\nUSING $f();\n"}, {"reduce user on user, using $f()", - "REDUCE user\nON\n\tuser,\nUSING $f();\n"}, + "REDUCE user\nON\n\tuser,\nUSING $f();\n"}, {"discard reduce user on user using $f();", - "DISCARD REDUCE user\nON\n\tuser\nUSING $f();\n"}, + "DISCARD REDUCE user\nON\n\tuser\nUSING $f();\n"}, {"reduce user on user using $f() into result user", - "REDUCE user\nON\n\tuser\nUSING $f()\nINTO RESULT user;\n"}, + "REDUCE user\nON\n\tuser\nUSING $f()\nINTO RESULT user;\n"}, {"reduce user on user using all $f()", - "REDUCE user\nON\n\tuser\nUSING ALL $f();\n"}, + "REDUCE user\nON\n\tuser\nUSING ALL $f();\n"}, {"reduce user on user using $f() as user", - "REDUCE user\nON\n\tuser\nUSING $f() AS user;\n"}, + "REDUCE user\nON\n\tuser\nUSING $f() AS user;\n"}, {"reduce user,user on user using $f()", - "REDUCE user, user\nON\n\tuser\nUSING $f();\n"}, + "REDUCE user, user\nON\n\tuser\nUSING $f();\n"}, {"reduce user on user,user using $f()", - "REDUCE user\nON\n\tuser,\n\tuser\nUSING $f();\n"}, + "REDUCE user\nON\n\tuser,\n\tuser\nUSING $f();\n"}, {"reduce user on user using $f() where 1=1 having 1=1 assume order by user", - "REDUCE user\nON\n\tuser\nUSING $f()\nWHERE\n\t1 == 1\nHAVING\n\t1 == 1\nASSUME ORDER BY\n\tuser\n;\n"}, + "REDUCE user\nON\n\tuser\nUSING $f()\nWHERE\n\t1 == 1\nHAVING\n\t1 == 1\nASSUME ORDER BY\n\tuser\n;\n"}, {"reduce user presort user,user on user using $f();", - "REDUCE user\nPRESORT\n\tuser,\n\tuser\nON\n\tuser\nUSING $f();\n"}, + "REDUCE user\nPRESORT\n\tuser,\n\tuser\nON\n\tuser\nUSING $f();\n"}, }; TSetup setup; @@ -890,115 +881,115 @@ Y_UNIT_TEST(Reduce) { Y_UNIT_TEST(Select) { TCases cases = { {"select 1", - "SELECT\n\t1\n;\n"}, + "SELECT\n\t1\n;\n"}, {"select 1,", - "SELECT\n\t1,\n;\n"}, + "SELECT\n\t1,\n;\n"}, {"select 1 as x", - "SELECT\n\t1 AS x\n;\n"}, + "SELECT\n\t1 AS x\n;\n"}, {"select *", - "SELECT\n\t*\n;\n"}, + "SELECT\n\t*\n;\n"}, {"select a.*", - "SELECT\n\ta.*\n;\n"}, + "SELECT\n\ta.*\n;\n"}, {"select * without a", - "SELECT\n\t*\nWITHOUT\n\ta\n;\n"}, + "SELECT\n\t*\nWITHOUT\n\ta\n;\n"}, {"select * without a,b", - "SELECT\n\t*\nWITHOUT\n\ta,\n\tb\n;\n"}, + "SELECT\n\t*\nWITHOUT\n\ta,\n\tb\n;\n"}, {"select * without a,", - "SELECT\n\t*\nWITHOUT\n\ta,\n;\n"}, + "SELECT\n\t*\nWITHOUT\n\ta,\n;\n"}, {"select * without if exists a", - "SELECT\n\t*\nWITHOUT IF EXISTS\n\ta\n;\n"}, + "SELECT\n\t*\nWITHOUT IF EXISTS\n\ta\n;\n"}, {"select 1 from user", - "SELECT\n\t1\nFROM\n\tuser\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\n;\n"}, {"select 1 from plato.user", - "SELECT\n\t1\nFROM\n\tplato.user\n;\n"}, + "SELECT\n\t1\nFROM\n\tplato.user\n;\n"}, {"select 1 from $user", - "SELECT\n\t1\nFROM\n\t$user\n;\n"}, + "SELECT\n\t1\nFROM\n\t$user\n;\n"}, {"select 1 from @user", - "SELECT\n\t1\nFROM\n\t@user\n;\n"}, + "SELECT\n\t1\nFROM\n\t@user\n;\n"}, {"select 1 from @$user", - "SELECT\n\t1\nFROM\n\t@$user\n;\n"}, + "SELECT\n\t1\nFROM\n\t@$user\n;\n"}, {"select 1 from user view user", - "SELECT\n\t1\nFROM\n\tuser VIEW user\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser VIEW user\n;\n"}, {"select 1 from user as user", - "SELECT\n\t1\nFROM\n\tuser AS user\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser AS user\n;\n"}, {"select 1 from user as user(user)", - "SELECT\n\t1\nFROM\n\tuser AS user (\n\t\tuser\n\t)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser AS user (\n\t\tuser\n\t)\n;\n"}, {"select 1 from user as user(user, user)", - "SELECT\n\t1\nFROM\n\tuser AS user (\n\t\tuser,\n\t\tuser\n\t)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser AS user (\n\t\tuser,\n\t\tuser\n\t)\n;\n"}, {"select 1 from user with user=user", - "SELECT\n\t1\nFROM\n\tuser WITH user = user\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser WITH user = user\n;\n"}, {"select 1 from user with (user=user, user=user)", - "SELECT\n\t1\nFROM\n\tuser WITH (\n\t\tuser = user,\n\t\tuser = user\n\t)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser WITH (\n\t\tuser = user,\n\t\tuser = user\n\t)\n;\n"}, {"select 1 from user sample 0.1", - "SELECT\n\t1\nFROM\n\tuser\n\tSAMPLE 0.1\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\n\tSAMPLE 0.1\n;\n"}, {"select 1 from user tablesample system(0.1)", - "SELECT\n\t1\nFROM\n\tuser\n\tTABLESAMPLE SYSTEM (0.1)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\n\tTABLESAMPLE SYSTEM (0.1)\n;\n"}, {"select 1 from user tablesample bernoulli(0.1) repeatable(10)", - "SELECT\n\t1\nFROM\n\tuser\n\tTABLESAMPLE BERNOULLI (0.1) REPEATABLE (10)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\n\tTABLESAMPLE BERNOULLI (0.1) REPEATABLE (10)\n;\n"}, {"select 1 from user flatten columns", - "SELECT\n\t1\nFROM\n\tuser\n\tFLATTEN COLUMNS\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\n\tFLATTEN COLUMNS\n;\n"}, {"select 1 from user flatten list by user", - "SELECT\n\t1\nFROM\n\tuser\n\tFLATTEN LIST BY user\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\n\tFLATTEN LIST BY user\n;\n"}, {"select 1 from user flatten list by (user,user)", - "SELECT\n\t1\nFROM\n\tuser\n\tFLATTEN LIST BY (\n\t\tuser,\n\t\tuser\n\t)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\n\tFLATTEN LIST BY (\n\t\tuser,\n\t\tuser\n\t)\n;\n"}, {"select 1 from $user(1,2)", - "SELECT\n\t1\nFROM\n\t$user(1, 2)\n;\n"}, + "SELECT\n\t1\nFROM\n\t$user(1, 2)\n;\n"}, {"select 1 from $user(1,2) view user", - "SELECT\n\t1\nFROM\n\t$user(1, 2) VIEW user\n;\n"}, + "SELECT\n\t1\nFROM\n\t$user(1, 2) VIEW user\n;\n"}, {"select 1 from range('a','b')", - "SELECT\n\t1\nFROM\n\trange('a', 'b')\n;\n"}, + "SELECT\n\t1\nFROM\n\trange('a', 'b')\n;\n"}, {"from user select 1", - "FROM\n\tuser\nSELECT\n\t1\n;\n"}, + "FROM\n\tuser\nSELECT\n\t1\n;\n"}, {"select * from user as a join user as b on a.x=b.y", - "SELECT\n\t*\nFROM\n\tuser AS a\nJOIN\n\tuser AS b\nON\n\ta.x == b.y\n;\n"}, + "SELECT\n\t*\nFROM\n\tuser AS a\nJOIN\n\tuser AS b\nON\n\ta.x == b.y\n;\n"}, {"select * from user as a join user as b using(x)", - "SELECT\n\t*\nFROM\n\tuser AS a\nJOIN\n\tuser AS b\nUSING (x);\n"}, + "SELECT\n\t*\nFROM\n\tuser AS a\nJOIN\n\tuser AS b\nUSING (x);\n"}, {"select * from any user as a full join user as b on a.x=b.y", - "SELECT\n\t*\nFROM ANY\n\tuser AS a\nFULL JOIN\n\tuser AS b\nON\n\ta.x == b.y\n;\n"}, + "SELECT\n\t*\nFROM ANY\n\tuser AS a\nFULL JOIN\n\tuser AS b\nON\n\ta.x == b.y\n;\n"}, {"select * from user as a left join any user as b on a.x=b.y", - "SELECT\n\t*\nFROM\n\tuser AS a\nLEFT JOIN ANY\n\tuser AS b\nON\n\ta.x == b.y\n;\n"}, + "SELECT\n\t*\nFROM\n\tuser AS a\nLEFT JOIN ANY\n\tuser AS b\nON\n\ta.x == b.y\n;\n"}, {"select * from any user as a right join any user as b on a.x=b.y", - "SELECT\n\t*\nFROM ANY\n\tuser AS a\nRIGHT JOIN ANY\n\tuser AS b\nON\n\ta.x == b.y\n;\n"}, + "SELECT\n\t*\nFROM ANY\n\tuser AS a\nRIGHT JOIN ANY\n\tuser AS b\nON\n\ta.x == b.y\n;\n"}, {"select * from user as a cross join user as b", - "SELECT\n\t*\nFROM\n\tuser AS a\nCROSS JOIN\n\tuser AS b\n;\n"}, + "SELECT\n\t*\nFROM\n\tuser AS a\nCROSS JOIN\n\tuser AS b\n;\n"}, {"select 1 from user where key = 1", - "SELECT\n\t1\nFROM\n\tuser\nWHERE\n\tkey == 1\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nWHERE\n\tkey == 1\n;\n"}, {"select 1 from user having count(*) = 1", - "SELECT\n\t1\nFROM\n\tuser\nHAVING\n\tcount(*) == 1\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nHAVING\n\tcount(*) == 1\n;\n"}, {"select 1 from user group by key", - "SELECT\n\t1\nFROM\n\tuser\nGROUP BY\n\tkey\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nGROUP BY\n\tkey\n;\n"}, {"select 1 from user group compact by key, value as v", - "SELECT\n\t1\nFROM\n\tuser\nGROUP COMPACT BY\n\tkey,\n\tvalue AS v\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nGROUP COMPACT BY\n\tkey,\n\tvalue AS v\n;\n"}, {"select 1 from user group by key with combine", - "SELECT\n\t1\nFROM\n\tuser\nGROUP BY\n\tkey\n\tWITH combine\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nGROUP BY\n\tkey\n\tWITH combine\n;\n"}, {"select 1 from user order by key asc", - "SELECT\n\t1\nFROM\n\tuser\nORDER BY\n\tkey ASC\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nORDER BY\n\tkey ASC\n;\n"}, {"select 1 from user order by key, value desc", - "SELECT\n\t1\nFROM\n\tuser\nORDER BY\n\tkey,\n\tvalue DESC\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nORDER BY\n\tkey,\n\tvalue DESC\n;\n"}, {"select 1 from user assume order by key", - "SELECT\n\t1\nFROM\n\tuser\nASSUME ORDER BY\n\tkey\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nASSUME ORDER BY\n\tkey\n;\n"}, {"select 1 from user window w1 as (), w2 as ()", - "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (),\n\tw2 AS ()\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (),\n\tw2 AS ()\n;\n"}, {"select 1 from user window w1 as (user)", - "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tuser\n\t)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tuser\n\t)\n;\n"}, {"select 1 from user window w1 as (partition by user)", - "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tPARTITION BY\n\t\t\tuser\n\t)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tPARTITION BY\n\t\t\tuser\n\t)\n;\n"}, {"select 1 from user window w1 as (partition by user, user)", - "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tPARTITION BY\n\t\t\tuser,\n\t\t\tuser\n\t)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tPARTITION BY\n\t\t\tuser,\n\t\t\tuser\n\t)\n;\n"}, {"select 1 from user window w1 as (order by user asc)", - "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tORDER BY\n\t\t\tuser ASC\n\t)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tORDER BY\n\t\t\tuser ASC\n\t)\n;\n"}, {"select 1 from user window w1 as (order by user, user desc)", - "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tORDER BY\n\t\t\tuser,\n\t\t\tuser DESC\n\t)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tORDER BY\n\t\t\tuser,\n\t\t\tuser DESC\n\t)\n;\n"}, {"select 1 from user window w1 as (rows between 1 preceding and 1 following)", - "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING\n\t)\n;\n"}, + "SELECT\n\t1\nFROM\n\tuser\nWINDOW\n\tw1 AS (\n\t\tROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING\n\t)\n;\n"}, {"select 1 limit 10", - "SELECT\n\t1\nLIMIT 10;\n"}, + "SELECT\n\t1\nLIMIT 10;\n"}, {"select 1 limit 10 offset 5", - "SELECT\n\t1\nLIMIT 10 OFFSET 5;\n"}, + "SELECT\n\t1\nLIMIT 10 OFFSET 5;\n"}, {"select 1 union all select 2", - "SELECT\n\t1\nUNION ALL\nSELECT\n\t2\n;\n" }, + "SELECT\n\t1\nUNION ALL\nSELECT\n\t2\n;\n"}, {"select * from $user where key == 1 -- comment", - "SELECT\n\t*\nFROM\n\t$user\nWHERE\n\tkey == 1 -- comment\n;\n"}, + "SELECT\n\t*\nFROM\n\t$user\nWHERE\n\tkey == 1 -- comment\n;\n"}, }; TSetup setup; @@ -1008,10 +999,10 @@ Y_UNIT_TEST(Select) { Y_UNIT_TEST(CompositeTypesAndQuestions) { TCases cases = { {"declare $_x AS list<int32>??;declare $_y AS int32 ? ? ;select 1<>2, 1??2," - "formattype(list<int32>), formattype(resource<user>),formattype(tuple<>), formattype(tuple< >), formattype(int32 ? ? )", - "DECLARE $_x AS list<int32>??;\nDECLARE $_y AS int32??;\n\nSELECT\n\t1 != 2,\n\t1 ?? 2,\n\tformattype(list<int32>)," - "\n\tformattype(resource<user>),\n\tformattype(tuple<>),\n\tformattype(tuple< >),\n\tformattype(int32??" ")\n;\n" - }, + "formattype(list<int32>), formattype(resource<user>),formattype(tuple<>), formattype(tuple< >), formattype(int32 ? ? )", + "DECLARE $_x AS list<int32>??;\nDECLARE $_y AS int32??;\n\nSELECT\n\t1 != 2,\n\t1 ?? 2,\n\tformattype(list<int32>)," + "\n\tformattype(resource<user>),\n\tformattype(tuple<>),\n\tformattype(tuple< >),\n\tformattype(int32??" + ")\n;\n"}, }; TSetup setup; @@ -1021,11 +1012,11 @@ Y_UNIT_TEST(CompositeTypesAndQuestions) { Y_UNIT_TEST(Lambda) { TCases cases = { {"$f=($a,$b)->{$x=$a+$b;return $a*$x};$g=($a,$b?)->($a+$b??0);select $f(10,4),$g(1,2);", - "$f = ($a, $b) -> {\n\t$x = $a + $b;\n\tRETURN $a * $x;\n};\n\n" - "$g = ($a, $b?) -> ($a + $b ?? 0);\n\n" - "SELECT\n\t$f(10, 4),\n\t$g(1, 2)\n;\n"}, + "$f = ($a, $b) -> {\n\t$x = $a + $b;\n\tRETURN $a * $x;\n};\n\n" + "$g = ($a, $b?) -> ($a + $b ?? 0);\n\n" + "SELECT\n\t$f(10, 4),\n\t$g(1, 2)\n;\n"}, {"$f=($arg)->{;$a=10;;$b=20;;;RETURN $a+$b}", - "$f = ($arg) -> {\n\t$a = 10;\n\t$b = 20;\n\tRETURN $a + $b;\n};\n"}, + "$f = ($arg) -> {\n\t$a = 10;\n\t$b = 20;\n\tRETURN $a + $b;\n};\n"}, }; TSetup setup; @@ -1035,17 +1026,17 @@ Y_UNIT_TEST(Lambda) { Y_UNIT_TEST(NestedSelect) { TCases cases = { {"$x=select 1", - "$x = (\n\tSELECT\n\t\t1\n);\n"}, + "$x = (\n\tSELECT\n\t\t1\n);\n"}, {"$x=(select 1)", - "$x = (\n\tSELECT\n\t\t1\n);\n"}, + "$x = (\n\tSELECT\n\t\t1\n);\n"}, {"$x=((select 1))", - "$x = (\n\t(\n\t\tSELECT\n\t\t\t1\n\t)\n);\n"}, + "$x = (\n\t(\n\t\tSELECT\n\t\t\t1\n\t)\n);\n"}, {"select 1 in (select 1)", - "SELECT\n\t1 IN (\n\t\tSELECT\n\t\t\t1\n\t)\n;\n"}, + "SELECT\n\t1 IN (\n\t\tSELECT\n\t\t\t1\n\t)\n;\n"}, {"select 1 in ((select 1))", - "SELECT\n\t1 IN (\n\t\t(\n\t\t\tSELECT\n\t\t\t\t1\n\t\t)\n\t)\n;\n"}, + "SELECT\n\t1 IN (\n\t\t(\n\t\t\tSELECT\n\t\t\t\t1\n\t\t)\n\t)\n;\n"}, {"select 1 in (\nselect 1)", - "SELECT\n\t1 IN (\n\t\tSELECT\n\t\t\t1\n\t)\n;\n"}, + "SELECT\n\t1 IN (\n\t\tSELECT\n\t\t\t1\n\t)\n;\n"}, }; TSetup setup; @@ -1054,8 +1045,8 @@ Y_UNIT_TEST(NestedSelect) { Y_UNIT_TEST(Cast) { TCases cases = { - {"select cast(1 as string)","SELECT\n\tCAST(1 AS string)\n;\n"}, - {"select bitcast(1 as int32)","SELECT\n\tBITCAST(1 AS int32)\n;\n"}, + {"select cast(1 as string)", "SELECT\n\tCAST(1 AS string)\n;\n"}, + {"select bitcast(1 as int32)", "SELECT\n\tBITCAST(1 AS int32)\n;\n"}, }; TSetup setup; @@ -1064,9 +1055,9 @@ Y_UNIT_TEST(Cast) { Y_UNIT_TEST(StructLiteral) { TCases cases = { - {"select <||>","SELECT\n\t<||>\n;\n"}, - {"select <|a:1|>","SELECT\n\t<|a: 1|>\n;\n"}, - {"select <|a:1,b:2|>","SELECT\n\t<|a: 1, b: 2|>\n;\n"}, + {"select <||>", "SELECT\n\t<||>\n;\n"}, + {"select <|a:1|>", "SELECT\n\t<|a: 1|>\n;\n"}, + {"select <|a:1,b:2|>", "SELECT\n\t<|a: 1, b: 2|>\n;\n"}, }; TSetup setup; @@ -1076,13 +1067,13 @@ Y_UNIT_TEST(StructLiteral) { Y_UNIT_TEST(TableHints) { TCases cases = { {"select * from plato.T with schema(foo int32, bar list<string>) where key is not null", - "SELECT\n\t*\nFROM\n\tplato.T WITH SCHEMA (foo int32, bar list<string>)\nWHERE\n\tkey IS NOT NULL\n;\n"}, + "SELECT\n\t*\nFROM\n\tplato.T WITH SCHEMA (foo int32, bar list<string>)\nWHERE\n\tkey IS NOT NULL\n;\n"}, {"select * from plato.T with schema struct<foo:integer, Bar:list<string?>> where key<0", - "SELECT\n\t*\nFROM\n\tplato.T WITH SCHEMA struct<foo: integer, Bar: list<string?>>\nWHERE\n\tkey < 0\n;\n"}, + "SELECT\n\t*\nFROM\n\tplato.T WITH SCHEMA struct<foo: integer, Bar: list<string?>>\nWHERE\n\tkey < 0\n;\n"}, {"select * from plato.T with (foo=bar, x=$y, a=(a, b, c), u='aaa', schema (foo int32, bar list<string>))", - "SELECT\n\t*\nFROM\n\tplato.T WITH (\n\t\tfoo = bar,\n\t\tx = $y,\n\t\ta = (a, b, c),\n\t\tu = 'aaa',\n\t\tSCHEMA (foo int32, bar list<string>)\n\t)\n;\n"}, + "SELECT\n\t*\nFROM\n\tplato.T WITH (\n\t\tfoo = bar,\n\t\tx = $y,\n\t\ta = (a, b, c),\n\t\tu = 'aaa',\n\t\tSCHEMA (foo int32, bar list<string>)\n\t)\n;\n"}, {"select * from plato.T with schema struct<\nfoo:int32,\nbar:double\n> as a", - "SELECT\n\t*\nFROM\n\tplato.T WITH SCHEMA struct<\n\t\tfoo: int32,\n\t\tbar: double\n\t> AS a\n;\n"}, + "SELECT\n\t*\nFROM\n\tplato.T WITH SCHEMA struct<\n\t\tfoo: int32,\n\t\tbar: double\n\t> AS a\n;\n"}, }; TSetup setup; @@ -1092,7 +1083,7 @@ Y_UNIT_TEST(TableHints) { Y_UNIT_TEST(BoolAsVariableName) { TCases cases = { {"$ False = True; select $ False;", - "$False = TRUE;\n\nSELECT\n\t$False\n;\n"}, + "$False = TRUE;\n\nSELECT\n\t$False\n;\n"}, }; TSetup setup; @@ -1102,8 +1093,8 @@ Y_UNIT_TEST(BoolAsVariableName) { Y_UNIT_TEST(WithSchemaEquals) { TCases cases = { {"select * from plato.T with (format= csv_with_names, schema=(year int32 Null, month String, day String not null, a Utf8, b Uint16));", - "SELECT\n\t*\nFROM\n\tplato.T WITH (\n\t\tformat = csv_with_names,\n\t\tSCHEMA = (year int32 NULL, month String, day String NOT NULL, a Utf8, b Uint16)\n\t)\n;\n"}, - }; + "SELECT\n\t*\nFROM\n\tplato.T WITH (\n\t\tformat = csv_with_names,\n\t\tSCHEMA = (year int32 NULL, month String, day String NOT NULL, a Utf8, b Uint16)\n\t)\n;\n"}, + }; TSetup setup; setup.Run(cases); @@ -1112,7 +1103,7 @@ Y_UNIT_TEST(WithSchemaEquals) { Y_UNIT_TEST(SquareBrackets) { TCases cases = { {"select a[0]", - "SELECT\n\ta[0]\n;\n"}, + "SELECT\n\ta[0]\n;\n"}, }; TSetup setup; @@ -1122,23 +1113,23 @@ Y_UNIT_TEST(SquareBrackets) { Y_UNIT_TEST(MultiLineList) { TCases cases = { {"select [\n]", - "SELECT\n\t[\n\t]\n;\n"}, + "SELECT\n\t[\n\t]\n;\n"}, {"select [1\n]", - "SELECT\n\t[\n\t\t1\n\t]\n;\n"}, + "SELECT\n\t[\n\t\t1\n\t]\n;\n"}, {"select [\n1]", - "SELECT\n\t[\n\t\t1\n\t]\n;\n"}, + "SELECT\n\t[\n\t\t1\n\t]\n;\n"}, {"select [1,\n]", - "SELECT\n\t[\n\t\t1,\n\t]\n;\n"}, + "SELECT\n\t[\n\t\t1,\n\t]\n;\n"}, {"select [1\n,]", - "SELECT\n\t[\n\t\t1,\n\t]\n;\n"}, + "SELECT\n\t[\n\t\t1,\n\t]\n;\n"}, {"select [\n1,]", - "SELECT\n\t[\n\t\t1,\n\t]\n;\n"}, + "SELECT\n\t[\n\t\t1,\n\t]\n;\n"}, {"select [1,2,\n3,4]", - "SELECT\n\t[\n\t\t1, 2,\n\t\t3, 4\n\t]\n;\n"}, + "SELECT\n\t[\n\t\t1, 2,\n\t\t3, 4\n\t]\n;\n"}, {"select [1,2,\n3,4,]", - "SELECT\n\t[\n\t\t1, 2,\n\t\t3, 4,\n\t]\n;\n"}, + "SELECT\n\t[\n\t\t1, 2,\n\t\t3, 4,\n\t]\n;\n"}, {"select [1,2\n,3,\n4\n,5]", - "SELECT\n\t[\n\t\t1, 2,\n\t\t3,\n\t\t4,\n\t\t5\n\t]\n;\n"}, + "SELECT\n\t[\n\t\t1, 2,\n\t\t3,\n\t\t4,\n\t\t5\n\t]\n;\n"}, }; TSetup setup; @@ -1148,17 +1139,17 @@ Y_UNIT_TEST(MultiLineList) { Y_UNIT_TEST(MultiLineTuple) { TCases cases = { {"select (\n)", - "SELECT\n\t(\n\t)\n;\n"}, + "SELECT\n\t(\n\t)\n;\n"}, {"select (1,\n)", - "SELECT\n\t(\n\t\t1,\n\t)\n;\n"}, + "SELECT\n\t(\n\t\t1,\n\t)\n;\n"}, {"select (1\n,)", - "SELECT\n\t(\n\t\t1,\n\t)\n;\n"}, + "SELECT\n\t(\n\t\t1,\n\t)\n;\n"}, {"select (\n1,)", - "SELECT\n\t(\n\t\t1,\n\t)\n;\n"}, + "SELECT\n\t(\n\t\t1,\n\t)\n;\n"}, {"select (1,2,\n3,4)", - "SELECT\n\t(\n\t\t1, 2,\n\t\t3, 4\n\t)\n;\n"}, + "SELECT\n\t(\n\t\t1, 2,\n\t\t3, 4\n\t)\n;\n"}, {"select (1,2,\n3,4,)", - "SELECT\n\t(\n\t\t1, 2,\n\t\t3, 4,\n\t)\n;\n"}, + "SELECT\n\t(\n\t\t1, 2,\n\t\t3, 4,\n\t)\n;\n"}, }; TSetup setup; @@ -1168,21 +1159,21 @@ Y_UNIT_TEST(MultiLineTuple) { Y_UNIT_TEST(MultiLineSet) { TCases cases = { {"select {\n}", - "SELECT\n\t{\n\t}\n;\n"}, + "SELECT\n\t{\n\t}\n;\n"}, {"select {1\n}", - "SELECT\n\t{\n\t\t1\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t1\n\t}\n;\n"}, {"select {\n1}", - "SELECT\n\t{\n\t\t1\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t1\n\t}\n;\n"}, {"select {1,\n}", - "SELECT\n\t{\n\t\t1,\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t1,\n\t}\n;\n"}, {"select {1\n,}", - "SELECT\n\t{\n\t\t1,\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t1,\n\t}\n;\n"}, {"select {\n1,}", - "SELECT\n\t{\n\t\t1,\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t1,\n\t}\n;\n"}, {"select {1,2,\n3,4}", - "SELECT\n\t{\n\t\t1, 2,\n\t\t3, 4\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t1, 2,\n\t\t3, 4\n\t}\n;\n"}, {"select {1,2,\n3,4,}", - "SELECT\n\t{\n\t\t1, 2,\n\t\t3, 4,\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t1, 2,\n\t\t3, 4,\n\t}\n;\n"}, }; TSetup setup; @@ -1192,19 +1183,19 @@ Y_UNIT_TEST(MultiLineSet) { Y_UNIT_TEST(MultiLineDict) { TCases cases = { {"select {0:1\n}", - "SELECT\n\t{\n\t\t0: 1\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t0: 1\n\t}\n;\n"}, {"select {\n0:1}", - "SELECT\n\t{\n\t\t0: 1\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t0: 1\n\t}\n;\n"}, {"select {0:1,\n}", - "SELECT\n\t{\n\t\t0: 1,\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t0: 1,\n\t}\n;\n"}, {"select {0:1\n,}", - "SELECT\n\t{\n\t\t0: 1,\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t0: 1,\n\t}\n;\n"}, {"select {\n0:1,}", - "SELECT\n\t{\n\t\t0: 1,\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t0: 1,\n\t}\n;\n"}, {"select {10:1,20:2,\n30:3,40:4}", - "SELECT\n\t{\n\t\t10: 1, 20: 2,\n\t\t30: 3, 40: 4\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t10: 1, 20: 2,\n\t\t30: 3, 40: 4\n\t}\n;\n"}, {"select {10:1,20:2,\n30:3,40:4,}", - "SELECT\n\t{\n\t\t10: 1, 20: 2,\n\t\t30: 3, 40: 4,\n\t}\n;\n"}, + "SELECT\n\t{\n\t\t10: 1, 20: 2,\n\t\t30: 3, 40: 4,\n\t}\n;\n"}, }; TSetup setup; @@ -1214,21 +1205,21 @@ Y_UNIT_TEST(MultiLineDict) { Y_UNIT_TEST(MultiLineFuncCall) { TCases cases = { {"select f(\n)", - "SELECT\n\tf(\n\t)\n;\n"}, + "SELECT\n\tf(\n\t)\n;\n"}, {"select f(1\n)", - "SELECT\n\tf(\n\t\t1\n\t)\n;\n"}, + "SELECT\n\tf(\n\t\t1\n\t)\n;\n"}, {"select f(\n1)", - "SELECT\n\tf(\n\t\t1\n\t)\n;\n"}, + "SELECT\n\tf(\n\t\t1\n\t)\n;\n"}, {"select f(1,\n)", - "SELECT\n\tf(\n\t\t1,\n\t)\n;\n"}, + "SELECT\n\tf(\n\t\t1,\n\t)\n;\n"}, {"select f(1\n,)", - "SELECT\n\tf(\n\t\t1,\n\t)\n;\n"}, + "SELECT\n\tf(\n\t\t1,\n\t)\n;\n"}, {"select f(\n1,)", - "SELECT\n\tf(\n\t\t1,\n\t)\n;\n"}, + "SELECT\n\tf(\n\t\t1,\n\t)\n;\n"}, {"select f(1,2,\n3,4)", - "SELECT\n\tf(\n\t\t1, 2,\n\t\t3, 4\n\t)\n;\n"}, + "SELECT\n\tf(\n\t\t1, 2,\n\t\t3, 4\n\t)\n;\n"}, {"select f(1,2,\n3,4,)", - "SELECT\n\tf(\n\t\t1, 2,\n\t\t3, 4,\n\t)\n;\n"}, + "SELECT\n\tf(\n\t\t1, 2,\n\t\t3, 4,\n\t)\n;\n"}, }; TSetup setup; @@ -1238,21 +1229,21 @@ Y_UNIT_TEST(MultiLineFuncCall) { Y_UNIT_TEST(MultiLineStruct) { TCases cases = { {"select <|\n|>", - "SELECT\n\t<|\n\t|>\n;\n"}, + "SELECT\n\t<|\n\t|>\n;\n"}, {"select <|a:1\n|>", - "SELECT\n\t<|\n\t\ta: 1\n\t|>\n;\n"}, + "SELECT\n\t<|\n\t\ta: 1\n\t|>\n;\n"}, {"select <|\na:1|>", - "SELECT\n\t<|\n\t\ta: 1\n\t|>\n;\n"}, + "SELECT\n\t<|\n\t\ta: 1\n\t|>\n;\n"}, {"select <|a:1,\n|>", - "SELECT\n\t<|\n\t\ta: 1,\n\t|>\n;\n"}, + "SELECT\n\t<|\n\t\ta: 1,\n\t|>\n;\n"}, {"select <|a:1\n,|>", - "SELECT\n\t<|\n\t\ta: 1,\n\t|>\n;\n"}, + "SELECT\n\t<|\n\t\ta: 1,\n\t|>\n;\n"}, {"select <|\na:1,|>", - "SELECT\n\t<|\n\t\ta: 1,\n\t|>\n;\n"}, + "SELECT\n\t<|\n\t\ta: 1,\n\t|>\n;\n"}, {"select <|a:1,b:2,\nc:3,d:4|>", - "SELECT\n\t<|\n\t\ta: 1, b: 2,\n\t\tc: 3, d: 4\n\t|>\n;\n"}, + "SELECT\n\t<|\n\t\ta: 1, b: 2,\n\t\tc: 3, d: 4\n\t|>\n;\n"}, {"select <|a:1,b:2,\nc:3,d:4,|>", - "SELECT\n\t<|\n\t\ta: 1, b: 2,\n\t\tc: 3, d: 4,\n\t|>\n;\n"}, + "SELECT\n\t<|\n\t\ta: 1, b: 2,\n\t\tc: 3, d: 4,\n\t|>\n;\n"}, }; TSetup setup; @@ -1262,9 +1253,9 @@ Y_UNIT_TEST(MultiLineStruct) { Y_UNIT_TEST(MultiLineListType) { TCases cases = { {"select list<int32\n>", - "SELECT\n\tlist<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\tlist<\n\t\tint32\n\t>\n;\n"}, {"select list<\nint32>", - "SELECT\n\tlist<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\tlist<\n\t\tint32\n\t>\n;\n"}, }; TSetup setup; @@ -1274,9 +1265,9 @@ Y_UNIT_TEST(MultiLineListType) { Y_UNIT_TEST(MultiLineOptionalType) { TCases cases = { {"select optional<int32\n>", - "SELECT\n\toptional<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\toptional<\n\t\tint32\n\t>\n;\n"}, {"select optional<\nint32>", - "SELECT\n\toptional<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\toptional<\n\t\tint32\n\t>\n;\n"}, }; TSetup setup; @@ -1286,9 +1277,9 @@ Y_UNIT_TEST(MultiLineOptionalType) { Y_UNIT_TEST(MultiLineStreamType) { TCases cases = { {"select stream<int32\n>", - "SELECT\n\tstream<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\tstream<\n\t\tint32\n\t>\n;\n"}, {"select stream<\nint32>", - "SELECT\n\tstream<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\tstream<\n\t\tint32\n\t>\n;\n"}, }; TSetup setup; @@ -1298,9 +1289,9 @@ Y_UNIT_TEST(MultiLineStreamType) { Y_UNIT_TEST(MultiLineFlowType) { TCases cases = { {"select flow<int32\n>", - "SELECT\n\tflow<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\tflow<\n\t\tint32\n\t>\n;\n"}, {"select flow<\nint32>", - "SELECT\n\tflow<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\tflow<\n\t\tint32\n\t>\n;\n"}, }; TSetup setup; @@ -1310,9 +1301,9 @@ Y_UNIT_TEST(MultiLineFlowType) { Y_UNIT_TEST(MultiLineSetType) { TCases cases = { {"select set<int32\n>", - "SELECT\n\tset<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\tset<\n\t\tint32\n\t>\n;\n"}, {"select set<\nint32>", - "SELECT\n\tset<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\tset<\n\t\tint32\n\t>\n;\n"}, }; TSetup setup; @@ -1322,21 +1313,21 @@ Y_UNIT_TEST(MultiLineSetType) { Y_UNIT_TEST(MultiLineTupleType) { TCases cases = { {"select tuple<\n>", - "SELECT\n\ttuple<\n\t\t \n\t>\n;\n"}, + "SELECT\n\ttuple<\n\t\t \n\t>\n;\n"}, {"select tuple<int32\n>", - "SELECT\n\ttuple<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\ttuple<\n\t\tint32\n\t>\n;\n"}, {"select tuple<\nint32>", - "SELECT\n\ttuple<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\ttuple<\n\t\tint32\n\t>\n;\n"}, {"select tuple<int32,\n>", - "SELECT\n\ttuple<\n\t\tint32,\n\t>\n;\n"}, + "SELECT\n\ttuple<\n\t\tint32,\n\t>\n;\n"}, {"select tuple<int32\n,>", - "SELECT\n\ttuple<\n\t\tint32,\n\t>\n;\n"}, + "SELECT\n\ttuple<\n\t\tint32,\n\t>\n;\n"}, {"select tuple<\nint32,>", - "SELECT\n\ttuple<\n\t\tint32,\n\t>\n;\n"}, + "SELECT\n\ttuple<\n\t\tint32,\n\t>\n;\n"}, {"select tuple<\nint32,string,\ndouble,bool>", - "SELECT\n\ttuple<\n\t\tint32, string,\n\t\tdouble, bool\n\t>\n;\n"}, + "SELECT\n\ttuple<\n\t\tint32, string,\n\t\tdouble, bool\n\t>\n;\n"}, {"select tuple<\nint32,string,\ndouble,bool,>", - "SELECT\n\ttuple<\n\t\tint32, string,\n\t\tdouble, bool,\n\t>\n;\n"}, + "SELECT\n\ttuple<\n\t\tint32, string,\n\t\tdouble, bool,\n\t>\n;\n"}, }; TSetup setup; @@ -1346,21 +1337,21 @@ Y_UNIT_TEST(MultiLineTupleType) { Y_UNIT_TEST(MultiLineStructType) { TCases cases = { {"select struct<\n>", - "SELECT\n\tstruct<\n\t\t \n\t>\n;\n"}, + "SELECT\n\tstruct<\n\t\t \n\t>\n;\n"}, {"select struct<a:int32\n>", - "SELECT\n\tstruct<\n\t\ta: int32\n\t>\n;\n"}, + "SELECT\n\tstruct<\n\t\ta: int32\n\t>\n;\n"}, {"select struct<\na:int32>", - "SELECT\n\tstruct<\n\t\ta: int32\n\t>\n;\n"}, + "SELECT\n\tstruct<\n\t\ta: int32\n\t>\n;\n"}, {"select struct<a:int32,\n>", - "SELECT\n\tstruct<\n\t\ta: int32,\n\t>\n;\n"}, + "SELECT\n\tstruct<\n\t\ta: int32,\n\t>\n;\n"}, {"select struct<a:int32\n,>", - "SELECT\n\tstruct<\n\t\ta: int32,\n\t>\n;\n"}, + "SELECT\n\tstruct<\n\t\ta: int32,\n\t>\n;\n"}, {"select struct<\na:int32,>", - "SELECT\n\tstruct<\n\t\ta: int32,\n\t>\n;\n"}, + "SELECT\n\tstruct<\n\t\ta: int32,\n\t>\n;\n"}, {"select struct<\na:int32,b:string,\nc:double,d:bool>", - "SELECT\n\tstruct<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool\n\t>\n;\n"}, + "SELECT\n\tstruct<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool\n\t>\n;\n"}, {"select struct<\na:int32,b:string,\nc:double,d:bool,>", - "SELECT\n\tstruct<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool,\n\t>\n;\n"}, + "SELECT\n\tstruct<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool,\n\t>\n;\n"}, }; TSetup setup; @@ -1370,19 +1361,19 @@ Y_UNIT_TEST(MultiLineStructType) { Y_UNIT_TEST(MultiLineVariantOverTupleType) { TCases cases = { {"select variant<int32\n>", - "SELECT\n\tvariant<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\tint32\n\t>\n;\n"}, {"select variant<\nint32>", - "SELECT\n\tvariant<\n\t\tint32\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\tint32\n\t>\n;\n"}, {"select variant<int32,\n>", - "SELECT\n\tvariant<\n\t\tint32,\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\tint32,\n\t>\n;\n"}, {"select variant<int32\n,>", - "SELECT\n\tvariant<\n\t\tint32,\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\tint32,\n\t>\n;\n"}, {"select variant<\nint32,>", - "SELECT\n\tvariant<\n\t\tint32,\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\tint32,\n\t>\n;\n"}, {"select variant<\nint32,string,\ndouble,bool>", - "SELECT\n\tvariant<\n\t\tint32, string,\n\t\tdouble, bool\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\tint32, string,\n\t\tdouble, bool\n\t>\n;\n"}, {"select variant<\nint32,string,\ndouble,bool,>", - "SELECT\n\tvariant<\n\t\tint32, string,\n\t\tdouble, bool,\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\tint32, string,\n\t\tdouble, bool,\n\t>\n;\n"}, }; TSetup setup; @@ -1392,19 +1383,19 @@ Y_UNIT_TEST(MultiLineVariantOverTupleType) { Y_UNIT_TEST(MultiLineVariantOverStructType) { TCases cases = { {"select variant<a:int32\n>", - "SELECT\n\tvariant<\n\t\ta: int32\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\ta: int32\n\t>\n;\n"}, {"select variant<\na:int32>", - "SELECT\n\tvariant<\n\t\ta: int32\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\ta: int32\n\t>\n;\n"}, {"select variant<a:int32,\n>", - "SELECT\n\tvariant<\n\t\ta: int32,\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\ta: int32,\n\t>\n;\n"}, {"select variant<a:int32\n,>", - "SELECT\n\tvariant<\n\t\ta: int32,\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\ta: int32,\n\t>\n;\n"}, {"select variant<\na:int32,>", - "SELECT\n\tvariant<\n\t\ta: int32,\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\ta: int32,\n\t>\n;\n"}, {"select variant<\na:int32,b:string,\nc:double,d:bool>", - "SELECT\n\tvariant<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool\n\t>\n;\n"}, {"select variant<\na:int32,b:string,\nc:double,d:bool,>", - "SELECT\n\tvariant<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool,\n\t>\n;\n"}, + "SELECT\n\tvariant<\n\t\ta: int32, b: string,\n\t\tc: double, d: bool,\n\t>\n;\n"}, }; TSetup setup; @@ -1414,19 +1405,19 @@ Y_UNIT_TEST(MultiLineVariantOverStructType) { Y_UNIT_TEST(MultiLineEnum) { TCases cases = { {"select enum<a\n>", - "SELECT\n\tenum<\n\t\ta\n\t>\n;\n"}, + "SELECT\n\tenum<\n\t\ta\n\t>\n;\n"}, {"select enum<\na>", - "SELECT\n\tenum<\n\t\ta\n\t>\n;\n"}, + "SELECT\n\tenum<\n\t\ta\n\t>\n;\n"}, {"select enum<a,\n>", - "SELECT\n\tenum<\n\t\ta,\n\t>\n;\n"}, + "SELECT\n\tenum<\n\t\ta,\n\t>\n;\n"}, {"select enum<a\n,>", - "SELECT\n\tenum<\n\t\ta,\n\t>\n;\n"}, + "SELECT\n\tenum<\n\t\ta,\n\t>\n;\n"}, {"select enum<\na,>", - "SELECT\n\tenum<\n\t\ta,\n\t>\n;\n"}, + "SELECT\n\tenum<\n\t\ta,\n\t>\n;\n"}, {"select enum<\na,b,\nc,d>", - "SELECT\n\tenum<\n\t\ta, b,\n\t\tc, d\n\t>\n;\n"}, + "SELECT\n\tenum<\n\t\ta, b,\n\t\tc, d\n\t>\n;\n"}, {"select enum<\na,b,\nc,d,>", - "SELECT\n\tenum<\n\t\ta, b,\n\t\tc, d,\n\t>\n;\n"}, + "SELECT\n\tenum<\n\t\ta, b,\n\t\tc, d,\n\t>\n;\n"}, }; TSetup setup; @@ -1436,9 +1427,9 @@ Y_UNIT_TEST(MultiLineEnum) { Y_UNIT_TEST(MultiLineResourceType) { TCases cases = { {"select resource<foo\n>", - "SELECT\n\tresource<\n\t\tfoo\n\t>\n;\n"}, + "SELECT\n\tresource<\n\t\tfoo\n\t>\n;\n"}, {"select resource<\nfoo>", - "SELECT\n\tresource<\n\t\tfoo\n\t>\n;\n"}, + "SELECT\n\tresource<\n\t\tfoo\n\t>\n;\n"}, }; TSetup setup; @@ -1448,13 +1439,13 @@ Y_UNIT_TEST(MultiLineResourceType) { Y_UNIT_TEST(MultiLineTaggedType) { TCases cases = { {"select tagged<int32,foo\n>", - "SELECT\n\ttagged<\n\t\tint32, foo\n\t>\n;\n"}, + "SELECT\n\ttagged<\n\t\tint32, foo\n\t>\n;\n"}, {"select tagged<int32,\nfoo>", - "SELECT\n\ttagged<\n\t\tint32,\n\t\tfoo\n\t>\n;\n"}, + "SELECT\n\ttagged<\n\t\tint32,\n\t\tfoo\n\t>\n;\n"}, {"select tagged<int32\n,foo>", - "SELECT\n\ttagged<\n\t\tint32,\n\t\tfoo\n\t>\n;\n"}, + "SELECT\n\ttagged<\n\t\tint32,\n\t\tfoo\n\t>\n;\n"}, {"select tagged<\nint32,foo>", - "SELECT\n\ttagged<\n\t\tint32, foo\n\t>\n;\n"}, + "SELECT\n\ttagged<\n\t\tint32, foo\n\t>\n;\n"}, }; TSetup setup; @@ -1464,13 +1455,13 @@ Y_UNIT_TEST(MultiLineTaggedType) { Y_UNIT_TEST(MultiLineDictType) { TCases cases = { {"select dict<int32,string\n>", - "SELECT\n\tdict<\n\t\tint32, string\n\t>\n;\n"}, + "SELECT\n\tdict<\n\t\tint32, string\n\t>\n;\n"}, {"select dict<int32,\nstring>", - "SELECT\n\tdict<\n\t\tint32,\n\t\tstring\n\t>\n;\n"}, + "SELECT\n\tdict<\n\t\tint32,\n\t\tstring\n\t>\n;\n"}, {"select dict<int32\n,string>", - "SELECT\n\tdict<\n\t\tint32,\n\t\tstring\n\t>\n;\n"}, + "SELECT\n\tdict<\n\t\tint32,\n\t\tstring\n\t>\n;\n"}, {"select dict<\nint32,string>", - "SELECT\n\tdict<\n\t\tint32, string\n\t>\n;\n"}, + "SELECT\n\tdict<\n\t\tint32, string\n\t>\n;\n"}, }; TSetup setup; @@ -1480,15 +1471,15 @@ Y_UNIT_TEST(MultiLineDictType) { Y_UNIT_TEST(MultiLineCallableType) { TCases cases = { {"select callable<()->int32\n>", - "SELECT\n\tcallable<\n\t\t() -> int32\n\t>\n;\n"}, + "SELECT\n\tcallable<\n\t\t() -> int32\n\t>\n;\n"}, {"select callable<\n()->int32>", - "SELECT\n\tcallable<\n\t\t() -> int32\n\t>\n;\n"}, + "SELECT\n\tcallable<\n\t\t() -> int32\n\t>\n;\n"}, {"select callable<\n(int32)->int32>", - "SELECT\n\tcallable<\n\t\t(int32) -> int32\n\t>\n;\n"}, + "SELECT\n\tcallable<\n\t\t(int32) -> int32\n\t>\n;\n"}, {"select callable<\n(int32,\ndouble)->int32>", - "SELECT\n\tcallable<\n\t\t(\n\t\t\tint32,\n\t\t\tdouble\n\t\t) -> int32\n\t>\n;\n"}, + "SELECT\n\tcallable<\n\t\t(\n\t\t\tint32,\n\t\t\tdouble\n\t\t) -> int32\n\t>\n;\n"}, {"select callable<\n(int32\n,double)->int32>", - "SELECT\n\tcallable<\n\t\t(\n\t\t\tint32,\n\t\t\tdouble\n\t\t) -> int32\n\t>\n;\n"}, + "SELECT\n\tcallable<\n\t\t(\n\t\t\tint32,\n\t\t\tdouble\n\t\t) -> int32\n\t>\n;\n"}, }; TSetup setup; @@ -1498,7 +1489,7 @@ Y_UNIT_TEST(MultiLineCallableType) { Y_UNIT_TEST(UnaryOp) { TCases cases = { {"select -x,+x,~x,-1,-1.0,+1,+1.0,~1u", - "SELECT\n\t-x,\n\t+x,\n\t~x,\n\t-1,\n\t-1.0,\n\t+1,\n\t+1.0,\n\t~1u\n;\n"}, + "SELECT\n\t-x,\n\t+x,\n\t~x,\n\t-1,\n\t-1.0,\n\t+1,\n\t+1.0,\n\t~1u\n;\n"}, }; TSetup setup; @@ -1521,7 +1512,7 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A, B as B ); )", -R"(PRAGMA FeatureR010 = 'prototype'; + R"(PRAGMA FeatureR010 = 'prototype'; USE plato; @@ -1549,8 +1540,7 @@ FROM B AS B ) ; -)" - }}; +)"}}; TSetup setup; setup.Run(cases); } @@ -1558,9 +1548,9 @@ FROM Y_UNIT_TEST(CreateTableTrailingComma) { TCases cases = { {"CREATE TABLE tableName (Key Uint32, PRIMARY KEY (Key),);", - "CREATE TABLE tableName (\n\tKey Uint32,\n\tPRIMARY KEY (Key),\n);\n"}, + "CREATE TABLE tableName (\n\tKey Uint32,\n\tPRIMARY KEY (Key),\n);\n"}, {"CREATE TABLE tableName (Key Uint32,);", - "CREATE TABLE tableName (\n\tKey Uint32,\n);\n"}, + "CREATE TABLE tableName (\n\tKey Uint32,\n);\n"}, }; TSetup setup; setup.Run(cases); @@ -1569,11 +1559,11 @@ Y_UNIT_TEST(CreateTableTrailingComma) { Y_UNIT_TEST(Union) { TCases cases = { {"select 1 union all select 2 union select 3 union all select 4 union select 5", - "SELECT\n\t1\nUNION ALL\nSELECT\n\t2\nUNION\nSELECT\n\t3\nUNION ALL\nSELECT\n\t4\nUNION\nSELECT\n\t5\n;\n"}, + "SELECT\n\t1\nUNION ALL\nSELECT\n\t2\nUNION\nSELECT\n\t3\nUNION ALL\nSELECT\n\t4\nUNION\nSELECT\n\t5\n;\n"}, {"select 1 union all (select 2)", - "SELECT\n\t1\nUNION ALL\n(\n\tSELECT\n\t\t2\n);\n"}, + "SELECT\n\t1\nUNION ALL\n(\n\tSELECT\n\t\t2\n);\n"}, {"select 1 union distinct select 2 union select 3 union distinct select 4 union select 5", - "SELECT\n\t1\nUNION DISTINCT\nSELECT\n\t2\nUNION\nSELECT\n\t3\nUNION DISTINCT\nSELECT\n\t4\nUNION\nSELECT\n\t5\n;\n"}, + "SELECT\n\t1\nUNION DISTINCT\nSELECT\n\t2\nUNION\nSELECT\n\t3\nUNION DISTINCT\nSELECT\n\t4\nUNION\nSELECT\n\t5\n;\n"}, }; TSetup setup; @@ -1583,11 +1573,11 @@ Y_UNIT_TEST(Union) { Y_UNIT_TEST(Intersect) { TCases cases = { {"select 1 intersect all select 2 intersect select 3 intersect all select 4 intersect select 5", - "SELECT\n\t1\nINTERSECT ALL\nSELECT\n\t2\nINTERSECT\nSELECT\n\t3\nINTERSECT ALL\nSELECT\n\t4\nINTERSECT\nSELECT\n\t5\n;\n"}, + "SELECT\n\t1\nINTERSECT ALL\nSELECT\n\t2\nINTERSECT\nSELECT\n\t3\nINTERSECT ALL\nSELECT\n\t4\nINTERSECT\nSELECT\n\t5\n;\n"}, {"select 1 intersect all (select 2)", - "SELECT\n\t1\nINTERSECT ALL\n(\n\tSELECT\n\t\t2\n);\n"}, + "SELECT\n\t1\nINTERSECT ALL\n(\n\tSELECT\n\t\t2\n);\n"}, {"select 1 intersect distinct select 2 intersect select 3 intersect distinct select 4 intersect select 5", - "SELECT\n\t1\nINTERSECT DISTINCT\nSELECT\n\t2\nINTERSECT\nSELECT\n\t3\nINTERSECT DISTINCT\nSELECT\n\t4\nINTERSECT\nSELECT\n\t5\n;\n"}, + "SELECT\n\t1\nINTERSECT DISTINCT\nSELECT\n\t2\nINTERSECT\nSELECT\n\t3\nINTERSECT DISTINCT\nSELECT\n\t4\nINTERSECT\nSELECT\n\t5\n;\n"}, }; TSetup setup; @@ -1597,11 +1587,11 @@ Y_UNIT_TEST(Intersect) { Y_UNIT_TEST(Except) { TCases cases = { {"select 1 except all select 2 except select 3 except all select 4 except select 5", - "SELECT\n\t1\nEXCEPT ALL\nSELECT\n\t2\nEXCEPT\nSELECT\n\t3\nEXCEPT ALL\nSELECT\n\t4\nEXCEPT\nSELECT\n\t5\n;\n"}, + "SELECT\n\t1\nEXCEPT ALL\nSELECT\n\t2\nEXCEPT\nSELECT\n\t3\nEXCEPT ALL\nSELECT\n\t4\nEXCEPT\nSELECT\n\t5\n;\n"}, {"select 1 except all (select 2)", - "SELECT\n\t1\nEXCEPT ALL\n(\n\tSELECT\n\t\t2\n);\n"}, + "SELECT\n\t1\nEXCEPT ALL\n(\n\tSELECT\n\t\t2\n);\n"}, {"select 1 except distinct select 2 except select 3 except distinct select 4 except select 5", - "SELECT\n\t1\nEXCEPT DISTINCT\nSELECT\n\t2\nEXCEPT\nSELECT\n\t3\nEXCEPT DISTINCT\nSELECT\n\t4\nEXCEPT\nSELECT\n\t5\n;\n"}, + "SELECT\n\t1\nEXCEPT DISTINCT\nSELECT\n\t2\nEXCEPT\nSELECT\n\t3\nEXCEPT DISTINCT\nSELECT\n\t4\nEXCEPT\nSELECT\n\t5\n;\n"}, }; TSetup setup; @@ -1623,7 +1613,7 @@ Y_UNIT_TEST(UnionIntersectExcept) { Y_UNIT_TEST(Comment) { TCases cases = { {"/*\nmulti\nline\ncomment\n*/\npragma foo = \"true\";\npragma bar = \"1\"", - "/*\nmulti\nline\ncomment\n*/\nPRAGMA foo = 'true';\nPRAGMA bar = '1';\n"}, + "/*\nmulti\nline\ncomment\n*/\nPRAGMA foo = 'true';\nPRAGMA bar = '1';\n"}, }; TSetup setup; @@ -1633,15 +1623,15 @@ Y_UNIT_TEST(Comment) { Y_UNIT_TEST(CommentAfterLastSelect) { TCases cases = { {"SELECT 1--comment\n", - "SELECT\n\t1 --comment\n;\n"}, + "SELECT\n\t1 --comment\n;\n"}, {"SELECT 1\n\n--comment\n", - "SELECT\n\t1\n\n--comment\n;\n"}, + "SELECT\n\t1\n\n--comment\n;\n"}, {"SELECT 1\n\n--comment", - "SELECT\n\t1\n\n--comment\n;\n"}, + "SELECT\n\t1\n\n--comment\n;\n"}, {"SELECT * FROM Input /* comment */\n\n\n", - "SELECT\n\t*\nFROM\n\tInput /* comment */\n;\n"}, + "SELECT\n\t*\nFROM\n\tInput /* comment */\n;\n"}, {"SELECT * FROM Input\n\n\n\n/* comment */\n\n\n", - "SELECT\n\t*\nFROM\n\tInput\n\n/* comment */;\n"}, + "SELECT\n\t*\nFROM\n\tInput\n\n/* comment */;\n"}, }; TSetup setup; @@ -1651,11 +1641,11 @@ Y_UNIT_TEST(CommentAfterLastSelect) { Y_UNIT_TEST(WindowFunctionInsideExpr) { TCases cases = { {"SELECT CAST(ROW_NUMBER() OVER () AS String) AS x,\nFROM Input;", - "SELECT\n\tCAST(ROW_NUMBER() OVER () AS String) AS x,\nFROM\n\tInput\n;\n"}, + "SELECT\n\tCAST(ROW_NUMBER() OVER () AS String) AS x,\nFROM\n\tInput\n;\n"}, {"SELECT CAST(ROW_NUMBER() OVER (PARTITION BY key) AS String) AS x,\nFROM Input;", - "SELECT\n\tCAST(\n\t\tROW_NUMBER() OVER (\n\t\t\tPARTITION BY\n\t\t\t\tkey\n\t\t) AS String\n\t) AS x,\nFROM\n\tInput\n;\n"}, + "SELECT\n\tCAST(\n\t\tROW_NUMBER() OVER (\n\t\t\tPARTITION BY\n\t\t\t\tkey\n\t\t) AS String\n\t) AS x,\nFROM\n\tInput\n;\n"}, {"SELECT CAST(ROW_NUMBER() OVER (users) AS String) AS x,\nFROM Input;", - "SELECT\n\tCAST(\n\t\tROW_NUMBER() OVER (\n\t\t\tusers\n\t\t) AS String\n\t) AS x,\nFROM\n\tInput\n;\n"}, + "SELECT\n\tCAST(\n\t\tROW_NUMBER() OVER (\n\t\t\tusers\n\t\t) AS String\n\t) AS x,\nFROM\n\tInput\n;\n"}, }; TSetup setup; @@ -1665,9 +1655,9 @@ Y_UNIT_TEST(WindowFunctionInsideExpr) { Y_UNIT_TEST(ExistsExpr) { TCases cases = { {"SELECT EXISTS (SELECT 1);", - "SELECT\n\tEXISTS (\n\t\tSELECT\n\t\t\t1\n\t)\n;\n"}, + "SELECT\n\tEXISTS (\n\t\tSELECT\n\t\t\t1\n\t)\n;\n"}, {"SELECT CAST(EXISTS(SELECT 1) AS Int) AS x,\nFROM Input;", - "SELECT\n\tCAST(\n\t\tEXISTS (\n\t\t\tSELECT\n\t\t\t\t1\n\t\t) AS Int\n\t) AS x,\nFROM\n\tInput\n;\n"}, + "SELECT\n\tCAST(\n\t\tEXISTS (\n\t\t\tSELECT\n\t\t\t\t1\n\t\t) AS Int\n\t) AS x,\nFROM\n\tInput\n;\n"}, }; TSetup setup; @@ -1677,7 +1667,7 @@ Y_UNIT_TEST(ExistsExpr) { Y_UNIT_TEST(LambdaInsideExpr) { TCases cases = { {"SELECT ListMap(AsList(1,2),($x)->{return $x+1});", - "SELECT\n\tListMap(\n\t\tAsList(1, 2), ($x) -> {\n\t\t\tRETURN $x + 1;\n\t\t}\n\t)\n;\n"}, + "SELECT\n\tListMap(\n\t\tAsList(1, 2), ($x) -> {\n\t\t\tRETURN $x + 1;\n\t\t}\n\t)\n;\n"}, }; TSetup setup; @@ -1687,11 +1677,11 @@ Y_UNIT_TEST(LambdaInsideExpr) { Y_UNIT_TEST(CaseExpr) { TCases cases = { {"SELECT CASE WHEN 1 == 2 THEN 3 WHEN 4 == 5 THEN 6 WHEN 7 == 8 THEN 9 ELSE 10 END;", - "SELECT\n\tCASE\n\t\tWHEN 1 == 2 THEN 3\n\t\tWHEN 4 == 5 THEN 6\n\t\tWHEN 7 == 8 THEN 9\n\t\tELSE 10\n\tEND\n;\n"}, + "SELECT\n\tCASE\n\t\tWHEN 1 == 2 THEN 3\n\t\tWHEN 4 == 5 THEN 6\n\t\tWHEN 7 == 8 THEN 9\n\t\tELSE 10\n\tEND\n;\n"}, {"SELECT CAST(CASE WHEN 1 == 2 THEN 3 WHEN 4 == 5 THEN 6 ELSE 10 END AS String);", - "SELECT\n\tCAST(\n\t\tCASE\n\t\t\tWHEN 1 == 2 THEN 3\n\t\t\tWHEN 4 == 5 THEN 6\n\t\t\tELSE 10\n\t\tEND AS String\n\t)\n;\n"}, + "SELECT\n\tCAST(\n\t\tCASE\n\t\t\tWHEN 1 == 2 THEN 3\n\t\t\tWHEN 4 == 5 THEN 6\n\t\t\tELSE 10\n\t\tEND AS String\n\t)\n;\n"}, {"SELECT CASE x WHEN 1 THEN 2 WHEN 3 THEN 4 WHEN 5 THEN 6 ELSE 10 END;", - "SELECT\n\tCASE x\n\t\tWHEN 1 THEN 2\n\t\tWHEN 3 THEN 4\n\t\tWHEN 5 THEN 6\n\t\tELSE 10\n\tEND\n;\n"}, + "SELECT\n\tCASE x\n\t\tWHEN 1 THEN 2\n\t\tWHEN 3 THEN 4\n\t\tWHEN 5 THEN 6\n\t\tELSE 10\n\tEND\n;\n"}, }; TSetup setup; @@ -1701,13 +1691,13 @@ Y_UNIT_TEST(CaseExpr) { Y_UNIT_TEST(MultiTokenOperations) { TCases cases = { {"$x = 1 >>| 2;", - "$x = 1 >>| 2;\n"}, + "$x = 1 >>| 2;\n"}, {"$x = 1 >> 2;", - "$x = 1 >> 2;\n"}, + "$x = 1 >> 2;\n"}, {"$x = 1 ?? 2;", - "$x = 1 ?? 2;\n"}, + "$x = 1 ?? 2;\n"}, {"$x = 1 > /*comment*/ > /*comment*/ | 2;", - "$x = 1 > /*comment*/> /*comment*/| 2;\n"}, + "$x = 1 > /*comment*/> /*comment*/| 2;\n"}, }; TSetup setup; @@ -1717,37 +1707,37 @@ Y_UNIT_TEST(MultiTokenOperations) { Y_UNIT_TEST(OperatorNewlines) { TCases cases = { {"$x = TRUE\nOR\nFALSE;", - "$x = TRUE\n\tOR\n\tFALSE;\n"}, + "$x = TRUE\n\tOR\n\tFALSE;\n"}, {"$x = TRUE OR\nFALSE;", - "$x = TRUE\n\tOR FALSE;\n"}, + "$x = TRUE\n\tOR FALSE;\n"}, {"$x = TRUE\nOR FALSE;", - "$x = TRUE\n\tOR FALSE;\n"}, + "$x = TRUE\n\tOR FALSE;\n"}, {"$x = 1+\n2*\n3;", - "$x = 1\n\t+ 2\n\t* 3;\n"}, + "$x = 1\n\t+ 2\n\t* 3;\n"}, {"$x = 1\n+\n2\n*3\n*5\n+\n4;", - "$x = 1\n\t+\n\t2\n\t* 3\n\t* 5\n\t+\n\t4;\n"}, + "$x = 1\n\t+\n\t2\n\t* 3\n\t* 5\n\t+\n\t4;\n"}, {"$x = 1\n+2+3+4\n+5+6+7+\n\n8+9+10;", - "$x = 1\n\t+ 2 + 3 + 4\n\t+ 5 + 6 + 7\n\t+ 8 + 9 + 10;\n"}, + "$x = 1\n\t+ 2 + 3 + 4\n\t+ 5 + 6 + 7\n\t+ 8 + 9 + 10;\n"}, {"$x = TRUE\nAND\nTRUE OR\nFALSE\nAND TRUE\nOR FALSE\nAND TRUE\nOR FALSE;", - "$x = TRUE\n\tAND\n\tTRUE\n\tOR FALSE\n\tAND TRUE\n\tOR FALSE\n\tAND TRUE\n\tOR FALSE;\n"}, + "$x = TRUE\n\tAND\n\tTRUE\n\tOR FALSE\n\tAND TRUE\n\tOR FALSE\n\tAND TRUE\n\tOR FALSE;\n"}, {"$x = 1 -- comment\n+ 2;", - "$x = 1 -- comment\n\t+ 2;\n"}, + "$x = 1 -- comment\n\t+ 2;\n"}, {"$x = 1 -- comment\n+ -- comment\n2;", - "$x = 1 -- comment\n\t+ -- comment\n\t2;\n"}, + "$x = 1 -- comment\n\t+ -- comment\n\t2;\n"}, {"$x = 1 + -- comment\n2;", - "$x = 1\n\t+ -- comment\n\t2;\n"}, + "$x = 1\n\t+ -- comment\n\t2;\n"}, {"$x = 1\n>\n>\n|\n2;", - "$x = 1\n\t>>|\n\t2;\n"}, + "$x = 1\n\t>>|\n\t2;\n"}, {"$x = 1\n?? 2 ??\n3\n??\n4 +\n5\n*\n6 +\n7 ??\n8;", - "$x = 1 ??\n\t2 ??\n\t3\n\t??\n\t4\n\t+ 5\n\t*\n\t6\n\t+ 7 ??\n\t8;\n"}, + "$x = 1 ??\n\t2 ??\n\t3\n\t??\n\t4\n\t+ 5\n\t*\n\t6\n\t+ 7 ??\n\t8;\n"}, {"select 1 ??\n2 ?? 3,\n4;", - "SELECT\n\t1 ??\n\t\t2 ?? 3,\n\t4\n;\n"}, + "SELECT\n\t1 ??\n\t\t2 ?? 3,\n\t4\n;\n"}, {"select 1\n?? 2 ?? 3,\n4;", - "SELECT\n\t1 ??\n\t\t2 ?? 3,\n\t4\n;\n"}, + "SELECT\n\t1 ??\n\t\t2 ?? 3,\n\t4\n;\n"}, {"select 1\n?? 2 ??\n3 ?? 4,\n5;", - "SELECT\n\t1 ??\n\t\t2 ??\n\t\t3 ?? 4,\n\t5\n;\n"}, + "SELECT\n\t1 ??\n\t\t2 ??\n\t\t3 ?? 4,\n\t5\n;\n"}, {"select 1\n?? 2 ?? 3 ??\n4 ?? 5,\n6;", - "SELECT\n\t1 ??\n\t\t2 ?? 3 ??\n\t\t4 ?? 5,\n\t6\n;\n"}, + "SELECT\n\t1 ??\n\t\t2 ?? 3 ??\n\t\t4 ?? 5,\n\t6\n;\n"}, }; TSetup setup; @@ -1757,29 +1747,29 @@ Y_UNIT_TEST(OperatorNewlines) { Y_UNIT_TEST(ObfuscateSelect) { TCases cases = { {"select 1;", - "SELECT\n\t0\n;\n"}, + "SELECT\n\t0\n;\n"}, {"select true;", - "SELECT\n\tFALSE\n;\n"}, + "SELECT\n\tFALSE\n;\n"}, {"select 'foo';", - "SELECT\n\t'str'\n;\n"}, + "SELECT\n\t'str'\n;\n"}, {"select 3.0;", - "SELECT\n\t0.0\n;\n"}, + "SELECT\n\t0.0\n;\n"}, {"select col;", - "SELECT\n\tid\n;\n"}, + "SELECT\n\tid\n;\n"}, {"select * from tab;", - "SELECT\n\t*\nFROM\n\tid\n;\n"}, + "SELECT\n\t*\nFROM\n\tid\n;\n"}, {"select cast(col as int32);", - "SELECT\n\tCAST(id AS int32)\n;\n"}, + "SELECT\n\tCAST(id AS int32)\n;\n"}, {"select func(col);", - "SELECT\n\tfunc(id)\n;\n"}, + "SELECT\n\tfunc(id)\n;\n"}, {"select mod::func(col);", - "SELECT\n\tmod::func(id)\n;\n"}, + "SELECT\n\tmod::func(id)\n;\n"}, {"declare $a as int32;", - "DECLARE $id AS int32;\n"}, + "DECLARE $id AS int32;\n"}, {"select * from `logs/of/bob` where pwd='foo';", - "SELECT\n\t*\nFROM\n\tid\nWHERE\n\tid == 'str'\n;\n"}, + "SELECT\n\t*\nFROM\n\tid\nWHERE\n\tid == 'str'\n;\n"}, {"select $f();", - "SELECT\n\t$id()\n;\n"}, + "SELECT\n\t$id()\n;\n"}, }; TSetup setup; @@ -1789,15 +1779,15 @@ Y_UNIT_TEST(ObfuscateSelect) { Y_UNIT_TEST(ObfuscatePragma) { TCases cases = { {"pragma a=1", - "PRAGMA id = 0;\n"}, + "PRAGMA id = 0;\n"}, {"pragma a='foo';", - "PRAGMA id = 'str';\n"}, + "PRAGMA id = 'str';\n"}, {"pragma a=true;", - "PRAGMA id = FALSE;\n"}, + "PRAGMA id = FALSE;\n"}, {"pragma a=$foo;", - "PRAGMA id = $id;\n"}, + "PRAGMA id = $id;\n"}, {"pragma a=foo;", - "PRAGMA id = id;\n"}, + "PRAGMA id = id;\n"}, }; TSetup setup; @@ -1805,31 +1795,22 @@ Y_UNIT_TEST(ObfuscatePragma) { } Y_UNIT_TEST(CreateView) { - TCases cases = {{ - "creAte vIEw TheView As SELect 1", - "CREATE VIEW TheView AS\nSELECT\n\t1\n;\n" - }, { - "creAte vIEw If Not ExIsTs TheView As SELect 1", - "CREATE VIEW IF NOT EXISTS TheView AS\nSELECT\n\t1\n;\n" - }, { - "creAte vIEw TheView wiTh (option = tRuE) As SELect 1", - "CREATE VIEW TheView WITH (option = TRUE) AS\nSELECT\n\t1\n;\n" - } - }; + TCases cases = {{"creAte vIEw TheView As SELect 1", + "CREATE VIEW TheView AS\nSELECT\n\t1\n;\n"}, + {"creAte vIEw If Not ExIsTs TheView As SELect 1", + "CREATE VIEW IF NOT EXISTS TheView AS\nSELECT\n\t1\n;\n"}, + {"creAte vIEw TheView wiTh (option = tRuE) As SELect 1", + "CREATE VIEW TheView WITH (option = TRUE) AS\nSELECT\n\t1\n;\n"}}; TSetup setup; setup.Run(cases); } Y_UNIT_TEST(DropView) { - TCases cases = {{ - "dRop viEW theVIEW", - "DROP VIEW theVIEW;\n" - }, { - "dRop viEW iF EXistS theVIEW", - "DROP VIEW IF EXISTS theVIEW;\n" - } - }; + TCases cases = {{"dRop viEW theVIEW", + "DROP VIEW theVIEW;\n"}, + {"dRop viEW iF EXistS theVIEW", + "DROP VIEW IF EXISTS theVIEW;\n"}}; TSetup setup; setup.Run(cases); @@ -1838,15 +1819,15 @@ Y_UNIT_TEST(DropView) { Y_UNIT_TEST(ResourcePoolOperations) { TCases cases = { {"creAte reSourCe poOl naMe With (a = \"b\")", - "CREATE RESOURCE POOL naMe WITH (a = 'b');\n"}, + "CREATE RESOURCE POOL naMe WITH (a = 'b');\n"}, {"create resource pool eds with (a=\"a\",b=\"b\",c = true)", - "CREATE RESOURCE POOL eds WITH (\n\ta = 'a',\n\tb = 'b',\n\tc = TRUE\n);\n"}, + "CREATE RESOURCE POOL eds WITH (\n\ta = 'a',\n\tb = 'b',\n\tc = TRUE\n);\n"}, {"alTer reSOurcE poOl naMe resEt (b, c), seT (x=y, z=false)", - "ALTER RESOURCE POOL naMe\n\tRESET (b, c),\n\tSET (x = y, z = FALSE)\n;\n"}, + "ALTER RESOURCE POOL naMe\n\tRESET (b, c),\n\tSET (x = y, z = FALSE)\n;\n"}, {"alter resource pool eds reset (a), set (x=y)", - "ALTER RESOURCE POOL eds\n\tRESET (a),\n\tSET (x = y)\n;\n"}, + "ALTER RESOURCE POOL eds\n\tRESET (a),\n\tSET (x = y)\n;\n"}, {"dRop reSourCe poOl naMe", - "DROP RESOURCE POOL naMe;\n"}, + "DROP RESOURCE POOL naMe;\n"}, }; TSetup setup; @@ -1856,21 +1837,21 @@ Y_UNIT_TEST(ResourcePoolOperations) { Y_UNIT_TEST(BackupCollectionOperations) { TCases cases = { {"creAte BackuP colLection `-naMe` wIth (a = \"b\")", - "CREATE BACKUP COLLECTION `-naMe` WITH (a = 'b');\n"}, + "CREATE BACKUP COLLECTION `-naMe` WITH (a = 'b');\n"}, {"creAte BackuP colLection `-naMe` DATabase wIth (a = 'b')", - "CREATE BACKUP COLLECTION `-naMe` DATABASE WITH (a = 'b');\n"}, + "CREATE BACKUP COLLECTION `-naMe` DATABASE WITH (a = 'b');\n"}, {"creAte BackuP colLection `-naMe` ( tabLe `tbl1` , TablE `tbl2`) wIth (a = \"b\")", - "CREATE BACKUP COLLECTION `-naMe` (TABLE `tbl1`, TABLE `tbl2`) WITH (a = 'b');\n"}, + "CREATE BACKUP COLLECTION `-naMe` (TABLE `tbl1`, TABLE `tbl2`) WITH (a = 'b');\n"}, {"alTer bACKuP coLLECTION naMe resEt (b, c), seT (x=y, z=false)", - "ALTER BACKUP COLLECTION naMe\n\tRESET (b, c),\n\tSET (x = y, z = FALSE)\n;\n"}, + "ALTER BACKUP COLLECTION naMe\n\tRESET (b, c),\n\tSET (x = y, z = FALSE)\n;\n"}, {"alTer bACKuP coLLECTION naMe aDD DATAbase", - "ALTER BACKUP COLLECTION naMe\n\tADD DATABASE\n;\n"}, + "ALTER BACKUP COLLECTION naMe\n\tADD DATABASE\n;\n"}, {"alTer bACKuP coLLECTION naMe DRoP \n\n DaTAbase", - "ALTER BACKUP COLLECTION naMe\n\tDROP DATABASE\n;\n"}, + "ALTER BACKUP COLLECTION naMe\n\tDROP DATABASE\n;\n"}, {"alTer bACKuP coLLECTION naMe add \n\n tablE\n\tsometable,drOp TABle `other`", - "ALTER BACKUP COLLECTION naMe\n\tADD TABLE sometable,\n\tDROP TABLE `other`\n;\n"}, + "ALTER BACKUP COLLECTION naMe\n\tADD TABLE sometable,\n\tDROP TABLE `other`\n;\n"}, {"DROP backup collectiOn `/some/path`", - "DROP BACKUP COLLECTION `/some/path`;\n"}, + "DROP BACKUP COLLECTION `/some/path`;\n"}, }; TSetup setup; @@ -1880,10 +1861,9 @@ Y_UNIT_TEST(BackupCollectionOperations) { Y_UNIT_TEST(Analyze) { TCases cases = { {"analyze table (col1, col2, col3)", - "ANALYZE table (col1, col2, col3);\n"}, + "ANALYZE table (col1, col2, col3);\n"}, {"analyze table", - "ANALYZE table;\n"} - }; + "ANALYZE table;\n"}}; TSetup setup; setup.Run(cases); @@ -1892,15 +1872,15 @@ Y_UNIT_TEST(Analyze) { Y_UNIT_TEST(ResourcePoolClassifierOperations) { TCases cases = { {"creAte reSourCe poOl ClaSsiFIer naMe With (a = \"b\")", - "CREATE RESOURCE POOL CLASSIFIER naMe WITH (a = 'b');\n"}, + "CREATE RESOURCE POOL CLASSIFIER naMe WITH (a = 'b');\n"}, {"create resource pool classifier eds with (a=\"a\",b=\"b\",c = true)", - "CREATE RESOURCE POOL CLASSIFIER eds WITH (\n\ta = 'a',\n\tb = 'b',\n\tc = TRUE\n);\n"}, + "CREATE RESOURCE POOL CLASSIFIER eds WITH (\n\ta = 'a',\n\tb = 'b',\n\tc = TRUE\n);\n"}, {"alTer reSOurcE poOl ClaSsiFIer naMe resEt (b, c), seT (x=y, z=false)", - "ALTER RESOURCE POOL CLASSIFIER naMe\n\tRESET (b, c),\n\tSET (x = y, z = FALSE)\n;\n"}, + "ALTER RESOURCE POOL CLASSIFIER naMe\n\tRESET (b, c),\n\tSET (x = y, z = FALSE)\n;\n"}, {"alter resource pool classifier eds reset (a), set (x=y)", - "ALTER RESOURCE POOL CLASSIFIER eds\n\tRESET (a),\n\tSET (x = y)\n;\n"}, + "ALTER RESOURCE POOL CLASSIFIER eds\n\tRESET (a),\n\tSET (x = y)\n;\n"}, {"dRop reSourCe poOl ClaSsiFIer naMe", - "DROP RESOURCE POOL CLASSIFIER naMe;\n"}, + "DROP RESOURCE POOL CLASSIFIER naMe;\n"}, }; TSetup setup; @@ -1910,7 +1890,7 @@ Y_UNIT_TEST(ResourcePoolClassifierOperations) { Y_UNIT_TEST(Backup) { TCases cases = { {"\tBaCKup\n\n TestCollection incremENTAl", - "BACKUP TestCollection INCREMENTAL;\n"}, + "BACKUP TestCollection INCREMENTAL;\n"}, }; TSetup setup; @@ -1920,7 +1900,7 @@ Y_UNIT_TEST(Backup) { Y_UNIT_TEST(Restore) { TCases cases = { {"resToRe\n\n\n TestCollection aT\n \t \n '2024-06-16_20-14-02'", - "RESTORE TestCollection AT '2024-06-16_20-14-02';\n"}, + "RESTORE TestCollection AT '2024-06-16_20-14-02';\n"}, }; TSetup setup; @@ -1930,7 +1910,7 @@ Y_UNIT_TEST(Restore) { Y_UNIT_TEST(AnsiLexer) { TCases cases = { {"select 'a', \"a\" from (select 1 as \"a\")", - "SELECT\n\t'a',\n\t\"a\"\nFROM (\n\tSELECT\n\t\t1 AS \"a\"\n);\n"}, + "SELECT\n\t'a',\n\t\"a\"\nFROM (\n\tSELECT\n\t\t1 AS \"a\"\n);\n"}, }; TSetup setup(/* ansiLexer = */ true); @@ -1940,11 +1920,11 @@ Y_UNIT_TEST(AnsiLexer) { Y_UNIT_TEST(ValueConstructor) { TCases cases = { {"select Enum('a', Enum<'a','b'>)", - "SELECT\n\tEnum('a', Enum<'a', 'b'>)\n;\n"}, + "SELECT\n\tEnum('a', Enum<'a', 'b'>)\n;\n"}, {"select Variant(true, '0', Variant<bool>)", - "SELECT\n\tVariant(TRUE, '0', Variant<bool>)\n;\n"}, + "SELECT\n\tVariant(TRUE, '0', Variant<bool>)\n;\n"}, {"select Callable(Callable<(Int32)->Int32>,($x)->($x))(0)", - "SELECT\n\tCallable(Callable<(Int32) -> Int32>, ($x) -> ($x))(0)\n;\n"}, + "SELECT\n\tCallable(Callable<(Int32) -> Int32>, ($x) -> ($x))(0)\n;\n"}, }; TSetup setup; @@ -1952,54 +1932,38 @@ Y_UNIT_TEST(ValueConstructor) { } Y_UNIT_TEST(CreateStreamingQuery) { - TCases cases = {{ - "creAte sTReaMing qUErY TheQuery As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", - "CREATE STREAMING QUERY TheQuery AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n" - }, { - "creAte sTReaMing qUErY If Not ExIsTs TheQuery As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", - "CREATE STREAMING QUERY IF NOT EXISTS TheQuery AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n" - }, { - "creAte oR ReplAce sTReaMing qUErY TheQuery As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", - "CREATE OR REPLACE STREAMING QUERY TheQuery AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n" - }, { - "creAte sTReaMing qUErY TheQuery wiTh (option = tRuE) As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", - "CREATE STREAMING QUERY TheQuery WITH (\n\toption = TRUE\n) AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n" - } - }; + TCases cases = {{"creAte sTReaMing qUErY TheQuery As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", + "CREATE STREAMING QUERY TheQuery AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n"}, + {"creAte sTReaMing qUErY If Not ExIsTs TheQuery As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", + "CREATE STREAMING QUERY IF NOT EXISTS TheQuery AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n"}, + {"creAte oR ReplAce sTReaMing qUErY TheQuery As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", + "CREATE OR REPLACE STREAMING QUERY TheQuery AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n"}, + {"creAte sTReaMing qUErY TheQuery wiTh (option = tRuE) As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", + "CREATE STREAMING QUERY TheQuery WITH (\n\toption = TRUE\n) AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n"}}; TSetup setup; setup.Run(cases); } Y_UNIT_TEST(AlterStreamingQuery) { - TCases cases = {{ - "aLTer sTReaMing qUErY TheQuery As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", - "ALTER STREAMING QUERY TheQuery AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n" - }, { - "aLTer sTReaMing qUErY If ExIsTs TheQuery As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", - "ALTER STREAMING QUERY IF EXISTS TheQuery AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n" - }, { - "aLTer sTReaMing qUErY TheQuery sEt (option = tRuE)", - "ALTER STREAMING QUERY TheQuery SET (\n\toption = TRUE\n);\n" - }, { - "aLTer sTReaMing qUErY TheQuery sEt (option = tRuE) As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", - "ALTER STREAMING QUERY TheQuery SET (\n\toption = TRUE\n) AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n" - } - }; + TCases cases = {{"aLTer sTReaMing qUErY TheQuery As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", + "ALTER STREAMING QUERY TheQuery AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n"}, + {"aLTer sTReaMing qUErY If ExIsTs TheQuery As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", + "ALTER STREAMING QUERY IF EXISTS TheQuery AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n"}, + {"aLTer sTReaMing qUErY TheQuery sEt (option = tRuE)", + "ALTER STREAMING QUERY TheQuery SET (\n\toption = TRUE\n);\n"}, + {"aLTer sTReaMing qUErY TheQuery sEt (option = tRuE) As dO BeGin ;;\n\nInSeRT iNTo TheTable SELect 1;; eNd Do", + "ALTER STREAMING QUERY TheQuery SET (\n\toption = TRUE\n) AS DO BEGIN\nINSERT INTO TheTable\nSELECT\n\t1\n;\nEND DO;\n"}}; TSetup setup; setup.Run(cases); } Y_UNIT_TEST(DropStreamingQuery) { - TCases cases = {{ - "dRop sTReaMing qUErY TheQuery", - "DROP STREAMING QUERY TheQuery;\n" - } , { - "dRop sTReaMing qUErY If ExIsTs TheQuery", - "DROP STREAMING QUERY IF EXISTS TheQuery;\n" - } - }; + TCases cases = {{"dRop sTReaMing qUErY TheQuery", + "DROP STREAMING QUERY TheQuery;\n"}, + {"dRop sTReaMing qUErY If ExIsTs TheQuery", + "DROP STREAMING QUERY IF EXISTS TheQuery;\n"}}; TSetup setup; setup.Run(cases); @@ -2044,7 +2008,7 @@ END DEFINE; } Y_UNIT_TEST(InlineSubquery) { - TString input = R"sql( + TString input = R"sql( SELECT (SELECT 1); SELECT (SELECT * FROM t WHERE p); SELECT * FROM t WHERE x > (SELECT 1); diff --git a/yql/essentials/sql/v1/format/sql_format_ut_antlr4.cpp b/yql/essentials/sql/v1/format/sql_format_ut_antlr4.cpp index 9e5be312a7f..adf95b48508 100644 --- a/yql/essentials/sql/v1/format/sql_format_ut_antlr4.cpp +++ b/yql/essentials/sql/v1/format/sql_format_ut_antlr4.cpp @@ -7,7 +7,6 @@ #include <yql/essentials/sql/v1/proto_parser/antlr4/proto_parser.h> #include <yql/essentials/sql/v1/proto_parser/antlr4_ansi/proto_parser.h> - #include <google/protobuf/arena.h> #include <util/string/subst.h> #include <util/string/join.h> @@ -65,8 +64,8 @@ struct TSetup { NSQLFormat::ISqlFormatter::TPtr Formatter; }; -} +} // namespace Y_UNIT_TEST_SUITE(CheckSqlFormatter) { - #include "sql_format_ut.h" -} +#include "sql_format_ut.h" +} // Y_UNIT_TEST_SUITE(CheckSqlFormatter) diff --git a/yql/essentials/sql/v1/format/ya.make b/yql/essentials/sql/v1/format/ya.make index a6d5ec0537c..0ee8aed6a85 100644 --- a/yql/essentials/sql/v1/format/ya.make +++ b/yql/essentials/sql/v1/format/ya.make @@ -1,5 +1,6 @@ LIBRARY() +ENABLE(YQL_STYLE_CPP) SRCS( sql_format.cpp diff --git a/yql/essentials/sql/v1/insert.cpp b/yql/essentials/sql/v1/insert.cpp index 42bddd74ca0..85e199ac63d 100644 --- a/yql/essentials/sql/v1/insert.cpp +++ b/yql/essentials/sql/v1/insert.cpp @@ -54,7 +54,7 @@ public: std::pair<TNodePtr, bool> BuildAggregation(const TString& label, TContext& ctx) override { Y_UNUSED(label); Y_UNUSED(ctx); - return { nullptr, true }; + return {nullptr, true}; } protected: @@ -68,14 +68,15 @@ public: : TModifySourceBase(pos, columnsHint) , OperationHumanName_(operationHumanName) , Values_(values) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { if (ColumnsHint_.size() != Values_.size()) { ctx.Error(Pos_) << "VALUES have " << Values_.size() << " columns, " << OperationHumanName_ << " expects: " << ColumnsHint_.size(); return false; } - for (auto& value: Values_) { + for (auto& value : Values_) { if (!value->Init(ctx, src)) { return false; } @@ -102,6 +103,7 @@ public: TNodePtr DoClone() const final { return new TUpdateByValues(Pos_, OperationHumanName_, ColumnsHint_, CloneContainer(Values_)); } + private: TString OperationHumanName_; @@ -122,7 +124,7 @@ public: bool DoInit(TContext& ctx, ISource* src) override { Y_UNUSED(src); bool hasError = false; - for (const auto& row: Values_) { + for (const auto& row : Values_) { if (ColumnsHint_.empty()) { ctx.Error(Pos_) << OperationHumanName_ << " ... VALUES requires specification of table columns"; hasError = true; @@ -133,7 +135,7 @@ public: hasError = true; continue; } - for (auto& value: row) { + for (auto& value : row) { if (!value->Init(ctx, FakeSource_.Get())) { hasError = true; continue; @@ -146,10 +148,10 @@ public: TNodePtr Build(TContext& ctx) override { Y_UNUSED(ctx); auto tuple = Y(); - for (const auto& row: Values_) { + for (const auto& row : Values_) { auto rowValues = Y("AsStruct"); // ordered struct auto column = ColumnsHint_.begin(); - for (auto value: row) { + for (auto value : row) { rowValues = L(rowValues, Q(Y(BuildQuotedAtom(Pos_, *column), value))); ++column; } @@ -161,7 +163,7 @@ public: TNodePtr DoClone() const final { TVector<TVector<TNodePtr>> clonedValues; clonedValues.reserve(Values_.size()); - for (auto cur: Values_) { + for (auto cur : Values_) { clonedValues.push_back(CloneContainer(cur)); } return new TModifyByValues(Pos_, OperationHumanName_, ColumnsHint_, clonedValues); @@ -179,7 +181,8 @@ public: : TModifySourceBase(pos, columnsHint) , OperationHumanName_(operationHumanName) , Source_(std::move(source)) - {} + { + } void GetInputTables(TTableList& tableList) const override { if (Source_) { @@ -221,8 +224,8 @@ public: } if (mismatchFound) { if (!ctx.Warning(Pos_, TIssuesIds::YQL_SOURCE_SELECT_COLUMN_MISMATCH, [&](auto& out) { - out << str.Str(); - })) { + out << str.Str(); + })) { return false; } } @@ -236,7 +239,7 @@ public: return input; } auto columns = Y(); - for (auto column: ColumnsHint_) { + for (auto column : ColumnsHint_) { columns = L(columns, BuildQuotedAtom(Pos_, column)); } const auto sourceColumns = Source_->GetColumns(); @@ -248,10 +251,9 @@ public: YQL_ENSURE(sourceColumns->List.size() == ColumnsHint_.size()); auto srcColumn = Source_->GetColumns()->List.begin(); auto structObj = Y("AsStruct"); // ordered struct - for (auto column: ColumnsHint_) { + for (auto column : ColumnsHint_) { structObj = L(structObj, Q(Y(BuildQuotedAtom(Pos_, column), - Y("Member", "row", BuildQuotedAtom(Pos_, *srcColumn)) - ))); + Y("Member", "row", BuildQuotedAtom(Pos_, *srcColumn))))); ++srcColumn; } return Y("AssumeColumnOrder", Y("OrderedMap", input, BuildLambda(Pos_, Y("row"), structObj)), Q(columns)); @@ -285,7 +287,7 @@ TSourcePtr BuildUpdateValues(TPosition pos, const TVector<TString>& columnsHint, class TWriteColumnsNode: public TAstListNode { public: TWriteColumnsNode(TPosition pos, TScopedStatePtr scoped, - const TTableRef& table, EWriteColumnMode mode, TSourcePtr values = nullptr, TNodePtr options = nullptr) + const TTableRef& table, EWriteColumnMode mode, TSourcePtr values = nullptr, TNodePtr options = nullptr) : TAstListNode(pos) , Scoped_(scoped) , Table_(table) @@ -433,7 +435,6 @@ TNodePtr BuildBatchDelete(TPosition pos, TScopedStatePtr scoped, const TTableRef return writeNode; } - class TEraseColumnsNode: public TAstListNode { public: TEraseColumnsNode(TPosition pos, const TVector<TString>& columns) @@ -447,7 +448,7 @@ public: Y_UNUSED(src); TNodePtr columnList = Y(); - for (const auto& column: Columns_) { + for (const auto& column : Columns_) { columnList->Add(Q(column)); } @@ -464,7 +465,6 @@ private: TVector<TString> Columns_; }; - TNodePtr BuildEraseColumns(TPosition pos, const TVector<TString>& columns) { return new TEraseColumnsNode(pos, columns); } diff --git a/yql/essentials/sql/v1/join.cpp b/yql/essentials/sql/v1/join.cpp index cec0d6293e8..df9842eeec2 100644 --- a/yql/essentials/sql/v1/join.cpp +++ b/yql/essentials/sql/v1/join.cpp @@ -16,7 +16,7 @@ namespace NSQLTranslationV1 { TString NormalizeJoinOp(const TString& joinOp) { TVector<TString> joinOpsParts; Split(joinOp, " ", joinOpsParts); - for (auto&x : joinOpsParts) { + for (auto& x : joinOpsParts) { x.to_title(); } @@ -36,7 +36,8 @@ struct TJoinDescr { explicit TJoinDescr(const TString& op) : Op(op) - {} + { + } }; class TJoinBase: public IJoin { @@ -50,7 +51,7 @@ public: } void AllColumns() override { - for (auto& source: Sources_) { + for (auto& source : Sources_) { source->AllColumns(); } } @@ -61,7 +62,7 @@ public: return true; } if (const auto sourceName = *column.GetSourceName()) { - for (auto& source: Sources_) { + for (auto& source : Sources_) { if (sourceName == source->GetLabel()) { srcByName = source.Get(); break; @@ -84,7 +85,7 @@ public: if (srcByName) { srcByName->AllColumns(); } else { - for (auto& source: Sources_) { + for (auto& source : Sources_) { source->AllColumns(); } } @@ -105,7 +106,7 @@ public: TIntrusivePtr<TColumnNode> tryColumn = static_cast<TColumnNode*>(column.Clone().Get()); tryColumn->SetAsNotReliable(); TString lastAcceptedColumnSource; - for (auto& source: Sources_) { + for (auto& source : Sources_) { if (source->AddColumn(ctx, *tryColumn)) { ++acceptedColumns; lastAcceptedColumnSource = source->GetLabel(); @@ -115,7 +116,7 @@ public: TStringBuilder sb; const auto& fullColumnName = FullColumnName(column); sb << "Column " << fullColumnName << " is not fit to any source"; - for (auto& source: Sources_) { + for (auto& source : Sources_) { if (const auto mistype = source->FindColumnMistype(fullColumnName)) { sb << ". Did you mean " << mistype.GetRef() << "?"; break; @@ -136,7 +137,7 @@ public: } void GetInputTables(TTableList& tableList) const override { - for (auto& src: Sources_) { + for (auto& src : Sources_) { src->GetInputTables(tableList); } ISource::GetInputTables(tableList); @@ -146,8 +147,8 @@ public: const size_t n = JoinOps_.size(); TString what(Sources_[n]->GetLabel()); static const TSet<TString> noRightSourceJoinOps = {"LeftOnly", "LeftSemi"}; - for (size_t nn = n; nn > 0 && noRightSourceJoinOps.contains(JoinOps_[nn-1]); --nn) { - what = Sources_[nn-1]->GetLabel(); + for (size_t nn = n; nn > 0 && noRightSourceJoinOps.contains(JoinOps_[nn - 1]); --nn) { + what = Sources_[nn - 1]->GetLabel(); } const TString with(Sources_[n + 1]->GetLabel()); @@ -168,7 +169,7 @@ public: } TPosition pos(ctx.Pos()); TNodePtr expr; - for (auto& name: names) { + for (auto& name : names) { auto lhs = BuildColumn(Pos_, name, what); auto rhs = BuildColumn(Pos_, name, with); if (!lhs || !rhs) { @@ -197,7 +198,7 @@ public: } bool IsStream() const override { - return AnyOf(Sources_, [] (const TSourcePtr& s) { return s->IsStream(); }); + return AnyOf(Sources_, [](const TSourcePtr& s) { return s->IsStream(); }); } protected: @@ -225,13 +226,13 @@ protected: ui32 idx = 0; THashMap<TString, ui32> sources; - for (auto& source: Sources_) { + for (auto& source : Sources_) { auto label = source->GetLabel(); if (!label) { ctx.Error(source->GetPos()) << "JOIN: missing correlation name for source"; return false; } - sources.insert({ source->GetLabel(), idx }); + sources.insert({source->GetLabel(), idx}); ++idx; } if (sources.size() != Sources_.size()) { @@ -268,18 +269,15 @@ protected: rightArg = pos; rightSource = sourceNamePtr; rightSourceIdx = it->second; - } - else if (it->second > joinIdx + 1) { + } else if (it->second > joinIdx + 1) { ctx.Error(expr->GetPos()) << "JOIN: can not use source: " << sourceName << " in equality predicate, it is out of current join scope"; return false; - } - else { + } else { leftArg = pos; leftSource = sourceNamePtr; leftSourceIdx = it->second; } - } - else { + } else { ctx.Error(expr->GetPos()) << "JOIN: unknown corellation name: " << sourceName; return false; } @@ -299,8 +297,7 @@ protected: leftArg = pos; leftSourceIdx = x.second; joinedSources.insert(x.first); - } - else if (x.second = joinIdx + 1) { + } else if (x.second = joinIdx + 1) { rightArg = pos; rightSourceIdx = x.second; joinedSources.insert(x.first); @@ -345,8 +342,8 @@ protected: JoinDescrs_.push_back(std::move(newDescr)); } - JoinDescrs_.back().Keys.push_back({ { leftSourceIdx, op ? op->GetArgs()[leftArg] : nullptr}, - { rightSourceIdx, op ? op->GetArgs()[rightArg] : nullptr } }); + JoinDescrs_.back().Keys.push_back({{leftSourceIdx, op ? op->GetArgs()[leftArg] : nullptr}, + {rightSourceIdx, op ? op->GetArgs()[rightArg] : nullptr}}); KeysInitializing_ = false; return true; } @@ -371,10 +368,10 @@ protected: if (IsColumnDone_) { return; } - YQL_ENSURE(JoinOps_.size()+1 == Sources_.size()); + YQL_ENSURE(JoinOps_.size() + 1 == Sources_.size()); bool excludeNextSource = false; decltype(JoinOps_)::const_iterator opIter = JoinOps_.begin(); - for (auto& src: Sources_) { + for (auto& src : Sources_) { if (excludeNextSource) { excludeNextSource = false; if (opIter != JoinOps_.end()) { @@ -406,7 +403,7 @@ protected: }; bool TJoinBase::DoInit(TContext& ctx, ISource* initSrc) { - for (auto& source: Sources_) { + for (auto& source : Sources_) { if (!source->Init(ctx, initSrc)) { return false; } @@ -425,7 +422,7 @@ bool TJoinBase::DoInit(TContext& ctx, ISource* initSrc) { YQL_ENSURE(JoinOps_.size() == JoinLinkSettings_.size()); const TSet<TString> allowedJoinOps = {"Inner", "Left", "Right", "Full", "LeftOnly", "RightOnly", "Exclusion", "LeftSemi", "RightSemi", "Cross"}; - for (auto& opName: JoinOps_) { + for (auto& opName : JoinOps_) { if (!allowedJoinOps.contains(opName)) { ctx.Error(Pos_) << "Invalid join op: " << opName; return false; @@ -433,7 +430,7 @@ bool TJoinBase::DoInit(TContext& ctx, ISource* initSrc) { } ui32 idx = 0; - for (auto expr: JoinExprs_) { + for (auto expr : JoinExprs_) { if (expr) { TDeque<TNodePtr> conjQueue; conjQueue.push_back(expr); @@ -457,7 +454,7 @@ bool TJoinBase::DoInit(TContext& ctx, ISource* initSrc) { } TSet<ui32> joinedSources; - for (auto& descr: JoinDescrs_) { + for (auto& descr : JoinDescrs_) { for (auto& key : descr.Keys) { joinedSources.insert(key.first.Source); joinedSources.insert(key.second.Source); @@ -484,7 +481,7 @@ public: TNodePtr Build(TContext& ctx) override { TMap<std::pair<TString, TString>, TNodePtr> extraColumns; TNodePtr joinTree; - for (auto& descr: JoinDescrs_) { + for (auto& descr : JoinDescrs_) { auto leftBranch = joinTree; bool leftAny = false; if (!leftBranch) { @@ -503,7 +500,7 @@ public: linkOptions = L(linkOptions, Q(Y(Q("forceSortedMerge")))); } else if (TJoinLinkSettings::EStrategy::StreamLookup == descr.LinkSettings.Strategy) { auto streamlookup = Y(Q("forceStreamLookup")); - for (auto&& option: descr.LinkSettings.Values) { + for (auto&& option : descr.LinkSettings.Values) { streamlookup = L(streamlookup, Q(option)); } linkOptions = L(linkOptions, Q(streamlookup)); @@ -529,8 +526,7 @@ public: BuildQuotedAtom(Pos_, Sources_[descr.Keys[0].second.Source]->GetLabel()), leftKeys, rightKeys, - Q(linkOptions) - )); + Q(linkOptions))); } TNodePtr equiJoin(Y("EquiJoin")); @@ -544,9 +540,7 @@ public: const bool useOrderedForSource = ctx.UseUnordered(*source); ordered = ordered || useOrderedForSource; if (source->IsFlattenByColumns() || source->IsFlattenColumns()) { - auto flatten = source->IsFlattenByColumns() ? - source->BuildFlattenByColumns("row") : - source->BuildFlattenColumns("row"); + auto flatten = source->IsFlattenByColumns() ? source->BuildFlattenByColumns("row") : source->BuildFlattenColumns("row"); if (!flatten) { return nullptr; @@ -566,7 +560,7 @@ public: sourceNode = Y("block", Q(L(block, Y("return", "flatten")))); } TNodePtr extraMembers; - for (auto it = extraColumns.lower_bound({ source->GetLabel(), "" }); it != extraColumns.end(); ++it) { + for (auto it = extraColumns.lower_bound({source->GetLabel(), ""}); it != extraColumns.end(); ++it) { if (it->first.first != source->GetLabel()) { break; } @@ -575,8 +569,7 @@ public: } extraMembers = L( extraMembers, - Y("let", "row", Y("AddMember", "row", BuildQuotedAtom(it->second->GetPos(), it->first.second), it->second)) - ); + Y("let", "row", Y("AddMember", "row", BuildQuotedAtom(it->second->GetPos(), it->first.second), it->second))); } if (extraMembers) { sourceNode = Y(useOrderedForSource ? "OrderedMap" : "Map", sourceNode, BuildLambda(Pos_, Y("row"), extraMembers, "row")); @@ -585,18 +578,17 @@ public: equiJoin = L(equiJoin, Q(Y(sourceNode, BuildQuotedAtom(source->GetPos(), source->GetLabel())))); } TNodePtr removeMembers; - for(auto it: extraColumns) { + for (auto it : extraColumns) { if (!removeMembers) { removeMembers = Y(); } removeMembers = L( removeMembers, - Y("let", "row", Y("ForceRemoveMember", "row", BuildQuotedAtom(Pos_, DotJoin(it.first.first, it.first.second)))) - ); + Y("let", "row", Y("ForceRemoveMember", "row", BuildQuotedAtom(Pos_, DotJoin(it.first.first, it.first.second))))); } auto options = Y(); if (StrictJoinKeyTypes_) { - options = L(options, Q(Y(Q("strict_keys")))); + options = L(options, Q(Y(Q("strict_keys")))); } equiJoin = L(equiJoin, joinTree, Q(options)); if (removeMembers) { @@ -611,7 +603,7 @@ public: TVector<TString> GetJoinLabels() const override { TVector<TString> labels; - for (auto& source: Sources_) { + for (auto& source : Sources_) { const auto label = source->GetLabel(); YQL_ENSURE(label); labels.push_back(label); @@ -621,7 +613,7 @@ public: TPtr DoClone() const final { TVector<TSourcePtr> clonedSources; - for (auto& cur: Sources_) { + for (auto& cur : Sources_) { clonedSources.push_back(cur->CloneSource()); } auto newSource = MakeIntrusive<TEquiJoin>(Pos_, std::move(clonedSources), TVector<bool>(AnyFlags_), StrictJoinKeyTypes_); @@ -636,11 +628,10 @@ private: TContext& ctx, TMap<std::pair<TString, TString>, TNodePtr>& extraColumns, const TVector<std::pair<TJoinDescr::TFullColumn, TJoinDescr::TFullColumn>>& keys, - bool left - ) { + bool left) { Y_UNUSED(ctx); auto res = Y(); - for (auto& it: keys) { + for (auto& it : keys) { auto tableName = Sources_[left ? it.first.Source : it.second.Source]->GetLabel(); TString columnName; auto column = left ? it.first.Column : it.second.Column; @@ -654,7 +645,7 @@ private: TStringStream str; str << "_equijoin_column_" << extraColumns.size(); columnName = str.Str(); - extraColumns.insert({ std::make_pair(tableName, columnName), column }); + extraColumns.insert({std::make_pair(tableName, columnName), column}); } res = L(res, BuildQuotedAtom(Pos_, tableName)); diff --git a/yql/essentials/sql/v1/lexer/antlr3/lexer.cpp b/yql/essentials/sql/v1/lexer/antlr3/lexer.cpp index e2d23d1503d..a0d9b577022 100644 --- a/yql/essentials/sql/v1/lexer/antlr3/lexer.cpp +++ b/yql/essentials/sql/v1/lexer/antlr3/lexer.cpp @@ -5,8 +5,8 @@ #include <yql/essentials/parser/proto_ast/antlr3/proto_ast_antlr3.h> namespace NALPDefault { -extern ANTLR_UINT8 *SQLv1ParserTokenNames[]; -} +extern ANTLR_UINT8* SQLv1ParserTokenNames[]; +} // namespace NALPDefault namespace NSQLTranslationV1 { @@ -31,10 +31,10 @@ public: } }; -} +} // namespace NSQLTranslation::TLexerFactoryPtr MakeAntlr3LexerFactory() { return MakeIntrusive<TFactory>(); } -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/antlr3/lexer.h b/yql/essentials/sql/v1/lexer/antlr3/lexer.h index 0c4fd35d0f6..7d3bd550688 100644 --- a/yql/essentials/sql/v1/lexer/antlr3/lexer.h +++ b/yql/essentials/sql/v1/lexer/antlr3/lexer.h @@ -5,4 +5,4 @@ namespace NSQLTranslationV1 { NSQLTranslation::TLexerFactoryPtr MakeAntlr3LexerFactory(); -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/antlr3_ansi/lexer.cpp b/yql/essentials/sql/v1/lexer/antlr3_ansi/lexer.cpp index 5b5c459f701..c7ee91a6260 100644 --- a/yql/essentials/sql/v1/lexer/antlr3_ansi/lexer.cpp +++ b/yql/essentials/sql/v1/lexer/antlr3_ansi/lexer.cpp @@ -5,8 +5,8 @@ #include <yql/essentials/parser/proto_ast/antlr3/proto_ast_antlr3.h> namespace NALPAnsi { -extern ANTLR_UINT8 *SQLv1ParserTokenNames[]; -} +extern ANTLR_UINT8* SQLv1ParserTokenNames[]; +} // namespace NALPAnsi namespace NSQLTranslationV1 { @@ -31,10 +31,10 @@ public: } }; -} +} // namespace NSQLTranslation::TLexerFactoryPtr MakeAntlr3AnsiLexerFactory() { return MakeIntrusive<TFactory>(); } -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/antlr3_ansi/lexer.h b/yql/essentials/sql/v1/lexer/antlr3_ansi/lexer.h index c2347d82332..7871fbff4cb 100644 --- a/yql/essentials/sql/v1/lexer/antlr3_ansi/lexer.h +++ b/yql/essentials/sql/v1/lexer/antlr3_ansi/lexer.h @@ -5,4 +5,4 @@ namespace NSQLTranslationV1 { NSQLTranslation::TLexerFactoryPtr MakeAntlr3AnsiLexerFactory(); -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/antlr4/lexer.cpp b/yql/essentials/sql/v1/lexer/antlr4/lexer.cpp index e3f63c4b65a..e5f8509f66e 100644 --- a/yql/essentials/sql/v1/lexer/antlr4/lexer.cpp +++ b/yql/essentials/sql/v1/lexer/antlr4/lexer.cpp @@ -29,10 +29,10 @@ public: } }; -} +} // namespace NSQLTranslation::TLexerFactoryPtr MakeAntlr4LexerFactory() { return MakeIntrusive<TFactory>(); } -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/antlr4/lexer.h b/yql/essentials/sql/v1/lexer/antlr4/lexer.h index 89d598d018e..9039bbc1ebf 100644 --- a/yql/essentials/sql/v1/lexer/antlr4/lexer.h +++ b/yql/essentials/sql/v1/lexer/antlr4/lexer.h @@ -5,4 +5,4 @@ namespace NSQLTranslationV1 { NSQLTranslation::TLexerFactoryPtr MakeAntlr4LexerFactory(); -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/antlr4_ansi/lexer.cpp b/yql/essentials/sql/v1/lexer/antlr4_ansi/lexer.cpp index ca5842ae984..706ad833ad3 100644 --- a/yql/essentials/sql/v1/lexer/antlr4_ansi/lexer.cpp +++ b/yql/essentials/sql/v1/lexer/antlr4_ansi/lexer.cpp @@ -27,10 +27,10 @@ public: } }; -} +} // namespace NSQLTranslation::TLexerFactoryPtr MakeAntlr4AnsiLexerFactory() { return MakeIntrusive<TFactory>(); } -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/antlr4_ansi/lexer.h b/yql/essentials/sql/v1/lexer/antlr4_ansi/lexer.h index 4aed14ef017..99ad7401dd2 100644 --- a/yql/essentials/sql/v1/lexer/antlr4_ansi/lexer.h +++ b/yql/essentials/sql/v1/lexer/antlr4_ansi/lexer.h @@ -5,4 +5,4 @@ namespace NSQLTranslationV1 { NSQLTranslation::TLexerFactoryPtr MakeAntlr4AnsiLexerFactory(); -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/antlr4_pure/lexer.cpp b/yql/essentials/sql/v1/lexer/antlr4_pure/lexer.cpp index d1cfb228eda..2a870395c31 100644 --- a/yql/essentials/sql/v1/lexer/antlr4_pure/lexer.cpp +++ b/yql/essentials/sql/v1/lexer/antlr4_pure/lexer.cpp @@ -9,31 +9,31 @@ namespace NSQLTranslationV1 { - namespace { - - class TLexer: public NSQLTranslation::ILexer { - public: - bool Tokenize(const TString& query, const TString& queryName, const TTokenCallback& onNextToken, NYql::TIssues& issues, size_t maxErrors) final { - NYql::TIssues newIssues; - NSQLTranslation::TErrorCollectorOverIssues collector(newIssues, maxErrors, queryName); - NAST::TLexerTokensCollector4<NALADefaultAntlr4::SQLv1Antlr4Lexer> tokensCollector(query, queryName); - tokensCollector.CollectTokens(collector, onNextToken); - issues.AddIssues(newIssues); - return !AnyOf(newIssues.begin(), newIssues.end(), [](auto issue) { return issue.GetSeverity() == NYql::ESeverity::TSeverityIds_ESeverityId_S_ERROR; }); - } - }; - - class TFactory: public NSQLTranslation::ILexerFactory { - public: - THolder<NSQLTranslation::ILexer> MakeLexer() const final { - return MakeHolder<TLexer>(); - } - }; - - } // namespace - - NSQLTranslation::TLexerFactoryPtr MakeAntlr4PureLexerFactory() { - return MakeIntrusive<TFactory>(); +namespace { + +class TLexer: public NSQLTranslation::ILexer { +public: + bool Tokenize(const TString& query, const TString& queryName, const TTokenCallback& onNextToken, NYql::TIssues& issues, size_t maxErrors) final { + NYql::TIssues newIssues; + NSQLTranslation::TErrorCollectorOverIssues collector(newIssues, maxErrors, queryName); + NAST::TLexerTokensCollector4<NALADefaultAntlr4::SQLv1Antlr4Lexer> tokensCollector(query, queryName); + tokensCollector.CollectTokens(collector, onNextToken); + issues.AddIssues(newIssues); + return !AnyOf(newIssues.begin(), newIssues.end(), [](auto issue) { return issue.GetSeverity() == NYql::ESeverity::TSeverityIds_ESeverityId_S_ERROR; }); } +}; + +class TFactory: public NSQLTranslation::ILexerFactory { +public: + THolder<NSQLTranslation::ILexer> MakeLexer() const final { + return MakeHolder<TLexer>(); + } +}; + +} // namespace + +NSQLTranslation::TLexerFactoryPtr MakeAntlr4PureLexerFactory() { + return MakeIntrusive<TFactory>(); +} } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/antlr4_pure/lexer.h b/yql/essentials/sql/v1/lexer/antlr4_pure/lexer.h index 21c4651daca..395e53431f4 100644 --- a/yql/essentials/sql/v1/lexer/antlr4_pure/lexer.h +++ b/yql/essentials/sql/v1/lexer/antlr4_pure/lexer.h @@ -4,6 +4,6 @@ namespace NSQLTranslationV1 { - NSQLTranslation::TLexerFactoryPtr MakeAntlr4PureLexerFactory(); +NSQLTranslation::TLexerFactoryPtr MakeAntlr4PureLexerFactory(); } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/antlr4_pure_ansi/lexer.cpp b/yql/essentials/sql/v1/lexer/antlr4_pure_ansi/lexer.cpp index b1df2ac506a..ba88287b07a 100644 --- a/yql/essentials/sql/v1/lexer/antlr4_pure_ansi/lexer.cpp +++ b/yql/essentials/sql/v1/lexer/antlr4_pure_ansi/lexer.cpp @@ -9,31 +9,31 @@ namespace NSQLTranslationV1 { - namespace { - - class TLexer: public NSQLTranslation::ILexer { - public: - bool Tokenize(const TString& query, const TString& queryName, const TTokenCallback& onNextToken, NYql::TIssues& issues, size_t maxErrors) final { - NYql::TIssues newIssues; - NSQLTranslation::TErrorCollectorOverIssues collector(newIssues, maxErrors, queryName); - NAST::TLexerTokensCollector4<NALAAnsiAntlr4::SQLv1Antlr4Lexer> tokensCollector(query, queryName); - tokensCollector.CollectTokens(collector, onNextToken); - issues.AddIssues(newIssues); - return !AnyOf(newIssues.begin(), newIssues.end(), [](auto issue) { return issue.GetSeverity() == NYql::ESeverity::TSeverityIds_ESeverityId_S_ERROR; }); - } - }; - - class TFactory: public NSQLTranslation::ILexerFactory { - public: - THolder<NSQLTranslation::ILexer> MakeLexer() const final { - return MakeHolder<TLexer>(); - } - }; - - } // namespace - - NSQLTranslation::TLexerFactoryPtr MakeAntlr4PureAnsiLexerFactory() { - return MakeIntrusive<TFactory>(); +namespace { + +class TLexer: public NSQLTranslation::ILexer { +public: + bool Tokenize(const TString& query, const TString& queryName, const TTokenCallback& onNextToken, NYql::TIssues& issues, size_t maxErrors) final { + NYql::TIssues newIssues; + NSQLTranslation::TErrorCollectorOverIssues collector(newIssues, maxErrors, queryName); + NAST::TLexerTokensCollector4<NALAAnsiAntlr4::SQLv1Antlr4Lexer> tokensCollector(query, queryName); + tokensCollector.CollectTokens(collector, onNextToken); + issues.AddIssues(newIssues); + return !AnyOf(newIssues.begin(), newIssues.end(), [](auto issue) { return issue.GetSeverity() == NYql::ESeverity::TSeverityIds_ESeverityId_S_ERROR; }); } +}; + +class TFactory: public NSQLTranslation::ILexerFactory { +public: + THolder<NSQLTranslation::ILexer> MakeLexer() const final { + return MakeHolder<TLexer>(); + } +}; + +} // namespace + +NSQLTranslation::TLexerFactoryPtr MakeAntlr4PureAnsiLexerFactory() { + return MakeIntrusive<TFactory>(); +} } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/antlr4_pure_ansi/lexer.h b/yql/essentials/sql/v1/lexer/antlr4_pure_ansi/lexer.h index 232e3fec749..b43fb5bbcd4 100644 --- a/yql/essentials/sql/v1/lexer/antlr4_pure_ansi/lexer.h +++ b/yql/essentials/sql/v1/lexer/antlr4_pure_ansi/lexer.h @@ -4,6 +4,6 @@ namespace NSQLTranslationV1 { - NSQLTranslation::TLexerFactoryPtr MakeAntlr4PureAnsiLexerFactory(); +NSQLTranslation::TLexerFactoryPtr MakeAntlr4PureAnsiLexerFactory(); } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/check/check_lexers.cpp b/yql/essentials/sql/v1/lexer/check/check_lexers.cpp index d0cccefdc79..6b93e95fcd8 100644 --- a/yql/essentials/sql/v1/lexer/check/check_lexers.cpp +++ b/yql/essentials/sql/v1/lexer/check/check_lexers.cpp @@ -1,6 +1,5 @@ #include "check_lexers.h" - #include <yql/essentials/sql/settings/translation_settings.h> #include <yql/essentials/sql/v1/lexer/lexer.h> #include <yql/essentials/sql/v1/lexer/antlr4/lexer.h> @@ -31,17 +30,17 @@ bool CheckLexers(NYql::TPosition pos, const TString& query, NYql::TIssues& issue auto lexerPure = NSQLTranslationV1::MakeLexer(lexers, settings.AnsiLexer, true, NSQLTranslationV1::ELexerFlavor::Pure); auto lexerRegex = NSQLTranslationV1::MakeRegexLexerFactory(settings.AnsiLexer)->MakeLexer(); TVector<NSQLTranslation::TParsedToken> mainTokens; - if (!lexerMain->Tokenize(query, "", [&](auto token) { mainTokens.push_back(token);}, issues, NSQLTranslation::SQL_MAX_PARSER_ERRORS)) { + if (!lexerMain->Tokenize(query, "", [&](auto token) { mainTokens.push_back(token); }, issues, NSQLTranslation::SQL_MAX_PARSER_ERRORS)) { return false; } TVector<NSQLTranslation::TParsedToken> pureTokens; - if (!lexerPure->Tokenize(query, "", [&](auto token) { pureTokens.push_back(token);}, issues, NSQLTranslation::SQL_MAX_PARSER_ERRORS)) { + if (!lexerPure->Tokenize(query, "", [&](auto token) { pureTokens.push_back(token); }, issues, NSQLTranslation::SQL_MAX_PARSER_ERRORS)) { return false; } TVector<NSQLTranslation::TParsedToken> regexTokens; - if (!lexerRegex->Tokenize(query, "", [&](auto token) { regexTokens.push_back(token);}, issues, NSQLTranslation::SQL_MAX_PARSER_ERRORS)) { + if (!lexerRegex->Tokenize(query, "", [&](auto token) { regexTokens.push_back(token); }, issues, NSQLTranslation::SQL_MAX_PARSER_ERRORS)) { return false; } @@ -49,8 +48,7 @@ bool CheckLexers(NYql::TPosition pos, const TString& query, NYql::TIssues& issue auto check = [&](const char* name, const TVector<NSQLTranslation::TParsedToken>& otherTokens) { if (mainTokens.size() != otherTokens.size()) { hasErrors = true; - issues.AddIssue(NYql::TIssue(pos, TStringBuilder () << "Mismatch token count, main: " << - mainTokens.size() << ", " << name << ": " << otherTokens.size() << "\n")); + issues.AddIssue(NYql::TIssue(pos, TStringBuilder() << "Mismatch token count, main: " << mainTokens.size() << ", " << name << ": " << otherTokens.size() << "\n")); } TStringBuilder textBuilder; @@ -79,4 +77,4 @@ bool CheckLexers(NYql::TPosition pos, const TString& query, NYql::TIssues& issue return !hasErrors; } -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/check/check_lexers.h b/yql/essentials/sql/v1/lexer/check/check_lexers.h index 0fceaa2e0bd..ef71c8adeb9 100644 --- a/yql/essentials/sql/v1/lexer/check/check_lexers.h +++ b/yql/essentials/sql/v1/lexer/check/check_lexers.h @@ -6,4 +6,4 @@ namespace NSQLTranslationV1 { bool CheckLexers(NYql::TPosition pos, const TString& query, NYql::TIssues& issues); -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/lexer.cpp b/yql/essentials/sql/v1/lexer/lexer.cpp index 543d0ccfd93..da546069b84 100644 --- a/yql/essentials/sql/v1/lexer/lexer.cpp +++ b/yql/essentials/sql/v1/lexer/lexer.cpp @@ -14,7 +14,7 @@ #include <util/string/join.h> #if defined(_tsan_enabled_) -#include <util/system/mutex.h> + #include <util/system/mutex.h> #endif namespace NSQLTranslationV1 { @@ -28,7 +28,7 @@ TMutex SanitizerSQLTranslationMutex; using NSQLTranslation::ILexer; using NSQLTranslation::MakeDummyLexerFactory; -class TV1Lexer : public ILexer { +class TV1Lexer: public ILexer { public: explicit TV1Lexer(const TLexers& lexers, bool ansi, bool antlr4, ELexerFlavor flavor) : Factory_(GetFactory(lexers, ansi, antlr4, flavor)) @@ -82,14 +82,14 @@ private: } switch (flavor) { - case ELexerFlavor::Default: { - } break; - case ELexerFlavor::Pure: { - parts.emplace_back("pure"); - } break; - case ELexerFlavor::Regex: { - parts.emplace_back("regex"); - } break; + case ELexerFlavor::Default: { + } break; + case ELexerFlavor::Pure: { + parts.emplace_back("pure"); + } break; + case ELexerFlavor::Regex: { + parts.emplace_back("regex"); + } break; } if (ansi) { @@ -270,7 +270,7 @@ void SplitByStatements(TTokenIterator begin, TTokenIterator end, TVector<TTokenI } } -} +} // namespace bool SplitQueryToStatements( const TString& query, NSQLTranslation::ILexer::TPtr& lexer, @@ -318,4 +318,4 @@ bool SplitQueryToStatements( return true; } -} // namespace NSQLTranslationV1 +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/lexer.h b/yql/essentials/sql/v1/lexer/lexer.h index 226e8b6ed25..48d21a654f0 100644 --- a/yql/essentials/sql/v1/lexer/lexer.h +++ b/yql/essentials/sql/v1/lexer/lexer.h @@ -34,4 +34,4 @@ bool SplitQueryToStatements( const TString& query, NSQLTranslation::ILexer::TPtr& lexer, TVector<TString>& statements, NYql::TIssues& issues, const TString& file = "", bool areBlankSkipped = true); -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/lexer_ut.cpp b/yql/essentials/sql/v1/lexer/lexer_ut.cpp index 196ca68a8f1..483787c159b 100644 --- a/yql/essentials/sql/v1/lexer/lexer_ut.cpp +++ b/yql/essentials/sql/v1/lexer/lexer_ut.cpp @@ -114,420 +114,420 @@ TString RandomMultilineCommentLikeText(size_t maxSize) { } Y_UNIT_TEST_SUITE(SQLv1Lexer) { - Y_UNIT_TEST(UnsupportedIssues) { - NSQLTranslationV1::TLexers factories; - - TVector<ILexer::TPtr> lexers; - for (auto ansi : {false, true}) { - for (auto antlr4 : {false, true}) { - for (auto flavor : {ELexerFlavor::Default, ELexerFlavor::Pure, ELexerFlavor::Regex}) { - lexers.emplace_back(MakeLexer(factories, ansi, antlr4, flavor)); - } +Y_UNIT_TEST(UnsupportedIssues) { + NSQLTranslationV1::TLexers factories; + + TVector<ILexer::TPtr> lexers; + for (auto ansi : {false, true}) { + for (auto antlr4 : {false, true}) { + for (auto flavor : {ELexerFlavor::Default, ELexerFlavor::Pure, ELexerFlavor::Regex}) { + lexers.emplace_back(MakeLexer(factories, ansi, antlr4, flavor)); } } - - TVector<TString> actual; - for (auto& lexer : lexers) { - auto issues = GetIssueMessages(lexer, ""); - actual.emplace_back(std::move(issues.at(0))); - } - - TVector<TString> expected = { - "<main>: Error: Lexer antlr3 is not supported", - "<main>: Error: Lexer antlr3_pure is not supported", - "<main>: Error: Lexer regex is not supported", - "<main>: Error: Lexer antlr4 is not supported", - "<main>: Error: Lexer antlr4_pure is not supported", - "<main>: Error: Lexer antlr4_regex is not supported", - "<main>: Error: Lexer antlr3_ansi is not supported", - "<main>: Error: Lexer antlr3_pure_ansi is not supported", - "<main>: Error: Lexer regex_ansi is not supported", - "<main>: Error: Lexer antlr4_ansi is not supported", - "<main>: Error: Lexer antlr4_pure_ansi is not supported", - "<main>: Error: Lexer antlr4_regex_ansi is not supported", - }; - - UNIT_ASSERT_VALUES_EQUAL(actual, expected); } - Y_UNIT_TEST_ON_EACH_LEXER(AntlrAndFlavorIndependent) { - static const TVector<TString> queries = { - "", - " ", - "SELECT", - "SEL", // identifier - "SELECT FROM test", - "SELECT * FROM", - " SELECT * FROM ", - "SELECT \"\xF0\x9F\x98\x8A\" FROM ydb", - ( - "SELECT \"\xF0\x9F\x98\x8A Hello, друзья\", count, name\n" - "FROM table -- главная таблица 数据库 \n" - "WHERE count < 6\n" - " AND name = \"可靠性\"\n" - " AND count > 12"), - "\"select\"select", - }; - - static TVector<TString> expectations(queries.size()); - - if (ANSI) { + TVector<TString> actual; + for (auto& lexer : lexers) { + auto issues = GetIssueMessages(lexer, ""); + actual.emplace_back(std::move(issues.at(0))); + } + + TVector<TString> expected = { + "<main>: Error: Lexer antlr3 is not supported", + "<main>: Error: Lexer antlr3_pure is not supported", + "<main>: Error: Lexer regex is not supported", + "<main>: Error: Lexer antlr4 is not supported", + "<main>: Error: Lexer antlr4_pure is not supported", + "<main>: Error: Lexer antlr4_regex is not supported", + "<main>: Error: Lexer antlr3_ansi is not supported", + "<main>: Error: Lexer antlr3_pure_ansi is not supported", + "<main>: Error: Lexer regex_ansi is not supported", + "<main>: Error: Lexer antlr4_ansi is not supported", + "<main>: Error: Lexer antlr4_pure_ansi is not supported", + "<main>: Error: Lexer antlr4_regex_ansi is not supported", + }; + + UNIT_ASSERT_VALUES_EQUAL(actual, expected); +} + +Y_UNIT_TEST_ON_EACH_LEXER(AntlrAndFlavorIndependent) { + static const TVector<TString> queries = { + "", + " ", + "SELECT", + "SEL", // identifier + "SELECT FROM test", + "SELECT * FROM", + " SELECT * FROM ", + "SELECT \"\xF0\x9F\x98\x8A\" FROM ydb", + ( + "SELECT \"\xF0\x9F\x98\x8A Hello, друзья\", count, name\n" + "FROM table -- главная таблица 数据库 \n" + "WHERE count < 6\n" + " AND name = \"可靠性\"\n" + " AND count > 12"), + "\"select\"select", + }; + + static TVector<TString> expectations(queries.size()); + + if (ANSI) { + return; + } + + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + + for (size_t i = 0; i < queries.size(); ++i) { + const auto& query = queries[i]; + auto& expected = expectations[i]; + + if (expected.empty()) { + expected = Tokenized(lexer, query); return; } - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, query, expected); + } +} - for (size_t i = 0; i < queries.size(); ++i) { - const auto& query = queries[i]; - auto& expected = expectations[i]; +TVector<TString> InvalidQueries(); - if (expected.empty()) { - expected = Tokenized(lexer, query); - return; - } +void TestInvalidTokensSkipped(bool antlr4, const TVector<TVector<TString>>& expected) { + auto lexer = MakeLexer(Lexers, /* ansi = */ false, antlr4); - UNIT_ASSERT_TOKENIZED(lexer, query, expected); - } + auto input = InvalidQueries(); + UNIT_ASSERT_VALUES_EQUAL(input.size(), expected.size()); + + for (size_t i = 0; i < input.size(); ++i) { + UNIT_ASSERT_VALUES_EQUAL(GetTokenViews(lexer, input[i]), expected[i]); } +} - TVector<TString> InvalidQueries(); +TVector<TString> InvalidQueries() { + return { + /* 0: */ "\xF0\x9F\x98\x8A", + /* 1: */ "select \"aaaa", + /* 2: */ "\"\\\"", + /* 3: */ "\xF0\x9F\x98\x8A SELECT * FR", + /* 4: */ "! SELECT * from", + /* 5: */ "\xF0\x9F\x98\x8Aselect ! from", + /* 6: */ "\"", + /* 7: */ "!select", + /* 8: */ "SELECT \\\"\xF0\x9F\x98\x8A\\\" FROM test", + }; +} - void TestInvalidTokensSkipped(bool antlr4, const TVector<TVector<TString>>& expected) { - auto lexer = MakeLexer(Lexers, /* ansi = */ false, antlr4); +Y_UNIT_TEST(ErrorRecoveryAntlr3) { + TVector<TVector<TString>> actual = { + /* 0: */ {"EOF"}, + /* 1: */ {"SELECT", "WS", "EOF"}, + /* 2: */ {"EOF"}, + /* 3: */ {"WS", "SELECT", "WS", "ASTERISK", "WS", "ID_PLAIN (FR)", "EOF"}, + /* 4: */ {"ID_PLAIN (ELECT)", "WS", "ASTERISK", "WS", "WS", "FROM", "EOF"}, + /* 5: */ {"SELECT", "WS", "ID_PLAIN (rom)", "EOF"}, + /* 6: */ {"EOF"}, + /* 7: */ {"ID_PLAIN (lect)", "EOF"}, + /* 8: */ {"SELECT", "WS", "EOF"}, + }; + TestInvalidTokensSkipped(/* antlr4 = */ false, actual); +} - auto input = InvalidQueries(); - UNIT_ASSERT_VALUES_EQUAL(input.size(), expected.size()); +Y_UNIT_TEST(ErrorRecoveryAntlr4) { + TVector<TVector<TString>> actual = { + /* 0: */ {"EOF"}, + /* 1: */ {"SELECT", "WS", "EOF"}, + /* 2: */ {"EOF"}, + /* 3: */ {"WS", "SELECT", "WS", "ASTERISK", "WS", "ID_PLAIN (FR)", "EOF"}, + /* 4: */ {"SELECT", "WS", "ASTERISK", "WS", "WS", "FROM", "EOF"}, + /* 5: */ {"SELECT", "WS", "FROM", "EOF"}, + /* 6: */ {"EOF"}, + /* 7: */ {"ID_PLAIN (elect)", "EOF"}, + /* 8: */ {"SELECT", "WS", "EOF"}, + }; + TestInvalidTokensSkipped(/* antlr4 = */ true, actual); +} - for (size_t i = 0; i < input.size(); ++i) { - UNIT_ASSERT_VALUES_EQUAL(GetTokenViews(lexer, input[i]), expected[i]); - } - } +Y_UNIT_TEST(IssuesCollected) { + auto lexer3 = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ false); + auto lexer4 = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ true); + auto lexer4p = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ true, ELexerFlavor::Pure); + auto lexerR = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ false, ELexerFlavor::Regex); - TVector<TString> InvalidQueries() { - return { - /* 0: */ "\xF0\x9F\x98\x8A", - /* 1: */ "select \"aaaa", - /* 2: */ "\"\\\"", - /* 3: */ "\xF0\x9F\x98\x8A SELECT * FR", - /* 4: */ "! SELECT * from", - /* 5: */ "\xF0\x9F\x98\x8Aselect ! from", - /* 6: */ "\"", - /* 7: */ "!select", - /* 8: */ "SELECT \\\"\xF0\x9F\x98\x8A\\\" FROM test", - }; - } + for (const auto& query : InvalidQueries()) { + auto issues3 = GetIssueMessages(lexer3, query); + auto issues4 = GetIssueMessages(lexer4, query); + auto issues4p = GetIssueMessages(lexer4p, query); + auto issuesR = GetIssueMessages(lexerR, query); - Y_UNIT_TEST(ErrorRecoveryAntlr3) { - TVector<TVector<TString>> actual = { - /* 0: */ {"EOF"}, - /* 1: */ {"SELECT", "WS", "EOF"}, - /* 2: */ {"EOF"}, - /* 3: */ {"WS", "SELECT", "WS", "ASTERISK", "WS", "ID_PLAIN (FR)", "EOF"}, - /* 4: */ {"ID_PLAIN (ELECT)", "WS", "ASTERISK", "WS", "WS", "FROM", "EOF"}, - /* 5: */ {"SELECT", "WS", "ID_PLAIN (rom)", "EOF"}, - /* 6: */ {"EOF"}, - /* 7: */ {"ID_PLAIN (lect)", "EOF"}, - /* 8: */ {"SELECT", "WS", "EOF"}, - }; - TestInvalidTokensSkipped(/* antlr4 = */ false, actual); + UNIT_ASSERT(!issues3.empty()); + UNIT_ASSERT(!issues4.empty()); + UNIT_ASSERT(!issues4p.empty()); + UNIT_ASSERT(!issuesR.empty()); } +} - Y_UNIT_TEST(ErrorRecoveryAntlr4) { - TVector<TVector<TString>> actual = { - /* 0: */ {"EOF"}, - /* 1: */ {"SELECT", "WS", "EOF"}, - /* 2: */ {"EOF"}, - /* 3: */ {"WS", "SELECT", "WS", "ASTERISK", "WS", "ID_PLAIN (FR)", "EOF"}, - /* 4: */ {"SELECT", "WS", "ASTERISK", "WS", "WS", "FROM", "EOF"}, - /* 5: */ {"SELECT", "WS", "FROM", "EOF"}, - /* 6: */ {"EOF"}, - /* 7: */ {"ID_PLAIN (elect)", "EOF"}, - /* 8: */ {"SELECT", "WS", "EOF"}, - }; - TestInvalidTokensSkipped(/* antlr4 = */ true, actual); - } +Y_UNIT_TEST(IssueMessagesAntlr3) { + auto lexer3 = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ false); - Y_UNIT_TEST(IssuesCollected) { - auto lexer3 = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ false); - auto lexer4 = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ true); - auto lexer4p = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ true, ELexerFlavor::Pure); - auto lexerR = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ false, ELexerFlavor::Regex); - - for (const auto& query : InvalidQueries()) { - auto issues3 = GetIssueMessages(lexer3, query); - auto issues4 = GetIssueMessages(lexer4, query); - auto issues4p = GetIssueMessages(lexer4p, query); - auto issuesR = GetIssueMessages(lexerR, query); - - UNIT_ASSERT(!issues3.empty()); - UNIT_ASSERT(!issues4.empty()); - UNIT_ASSERT(!issues4p.empty()); - UNIT_ASSERT(!issuesR.empty()); - } - } + auto actual = GetIssueMessages(lexer3, "\xF0\x9F\x98\x8A SELECT * FR"); - Y_UNIT_TEST(IssueMessagesAntlr3) { - auto lexer3 = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ false); + TVector<TString> expected = { + "<main>:1:0: Error: Unexpected character '\xF0\x9F\x98\x8A' (Unicode character <128522>) : cannot match to any predicted input...", + "<main>:1:1: Error: Unexpected character : cannot match to any predicted input...", + "<main>:1:2: Error: Unexpected character : cannot match to any predicted input...", + "<main>:1:3: Error: Unexpected character : cannot match to any predicted input...", + }; - auto actual = GetIssueMessages(lexer3, "\xF0\x9F\x98\x8A SELECT * FR"); + UNIT_ASSERT_VALUES_EQUAL(actual, expected); +} - TVector<TString> expected = { - "<main>:1:0: Error: Unexpected character '\xF0\x9F\x98\x8A' (Unicode character <128522>) : cannot match to any predicted input...", - "<main>:1:1: Error: Unexpected character : cannot match to any predicted input...", - "<main>:1:2: Error: Unexpected character : cannot match to any predicted input...", - "<main>:1:3: Error: Unexpected character : cannot match to any predicted input...", - }; +Y_UNIT_TEST(IssueMessagesAntlr4) { + auto lexer4 = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ true); - UNIT_ASSERT_VALUES_EQUAL(actual, expected); - } + auto actual = GetIssueMessages(lexer4, "\xF0\x9F\x98\x8A SELECT * FR"); - Y_UNIT_TEST(IssueMessagesAntlr4) { - auto lexer4 = MakeLexer(Lexers, /* ansi = */ false, /* antlr4 = */ true); + TVector<TString> expected = { + "<main>:1:0: Error: token recognition error at: '\xF0\x9F\x98\x8A'", + }; - auto actual = GetIssueMessages(lexer4, "\xF0\x9F\x98\x8A SELECT * FR"); + UNIT_ASSERT_VALUES_EQUAL(actual, expected); +} - TVector<TString> expected = { - "<main>:1:0: Error: token recognition error at: '\xF0\x9F\x98\x8A'", - }; +Y_UNIT_TEST_ON_EACH_LEXER(Whitespace) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, "", "EOF"); + UNIT_ASSERT_TOKENIZED(lexer, " ", "WS( ) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, " ", "WS( ) WS( ) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "\n", "WS(\n) EOF"); +} - UNIT_ASSERT_VALUES_EQUAL(actual, expected); - } +Y_UNIT_TEST_ON_EACH_LEXER(Keyword) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, "SELECT", "SELECT EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "INSERT", "INSERT EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "FROM", "FROM EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "from", "FROM(from) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, " UPSERT ", "WS( ) UPSERT WS( ) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "ERROR", "ERROR EOF"); +} - Y_UNIT_TEST_ON_EACH_LEXER(Whitespace) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED(lexer, "", "EOF"); - UNIT_ASSERT_TOKENIZED(lexer, " ", "WS( ) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, " ", "WS( ) WS( ) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "\n", "WS(\n) EOF"); +Y_UNIT_TEST_ON_EACH_LEXER(KeywordSkip) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + if (ANTLR4 || FLAVOR == ELexerFlavor::Regex) { + UNIT_ASSERT_TOKENIZED(lexer, "sKip", "TSKIP(sKip) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "SKIP", "TSKIP(SKIP) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, " SKIP ", "WS( ) TSKIP(SKIP) WS( ) EOF"); + } else { + UNIT_ASSERT_TOKENIZED(lexer, "sKip", "SKIP(sKip) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "SKIP", "SKIP EOF"); + UNIT_ASSERT_TOKENIZED(lexer, " SKIP ", "WS( ) SKIP WS( ) EOF"); } +} - Y_UNIT_TEST_ON_EACH_LEXER(Keyword) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED(lexer, "SELECT", "SELECT EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "INSERT", "INSERT EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "FROM", "FROM EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "from", "FROM(from) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, " UPSERT ", "WS( ) UPSERT WS( ) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "ERROR", "ERROR EOF"); - } +Y_UNIT_TEST_ON_EACH_LEXER(Punctuation) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED( + lexer, + "* / + - <|", + "ASTERISK(*) WS( ) SLASH(/) WS( ) " + "PLUS(+) WS( ) MINUS(-) WS( ) STRUCT_OPEN(<|) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "SELECT*FROM", "SELECT ASTERISK(*) FROM EOF"); +} - Y_UNIT_TEST_ON_EACH_LEXER(KeywordSkip) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - if (ANTLR4 || FLAVOR == ELexerFlavor::Regex) { - UNIT_ASSERT_TOKENIZED(lexer, "sKip", "TSKIP(sKip) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "SKIP", "TSKIP(SKIP) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, " SKIP ", "WS( ) TSKIP(SKIP) WS( ) EOF"); - } else { - UNIT_ASSERT_TOKENIZED(lexer, "sKip", "SKIP(sKip) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "SKIP", "SKIP EOF"); - UNIT_ASSERT_TOKENIZED(lexer, " SKIP ", "WS( ) SKIP WS( ) EOF"); - } - } +Y_UNIT_TEST_ON_EACH_LEXER(IdPlain) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, "variable my_table", "ID_PLAIN(variable) WS( ) ID_PLAIN(my_table) EOF"); +} - Y_UNIT_TEST_ON_EACH_LEXER(Punctuation) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED( - lexer, - "* / + - <|", - "ASTERISK(*) WS( ) SLASH(/) WS( ) " - "PLUS(+) WS( ) MINUS(-) WS( ) STRUCT_OPEN(<|) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "SELECT*FROM", "SELECT ASTERISK(*) FROM EOF"); - } +Y_UNIT_TEST_ON_EACH_LEXER(IdQuoted) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, "``", "ID_QUOTED(``) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "` `", "ID_QUOTED(` `) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "`local/table`", "ID_QUOTED(`local/table`) EOF"); +} - Y_UNIT_TEST_ON_EACH_LEXER(IdPlain) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED(lexer, "variable my_table", "ID_PLAIN(variable) WS( ) ID_PLAIN(my_table) EOF"); - } +Y_UNIT_TEST_ON_EACH_LEXER(Number) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, "1", "DIGITS(1) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "123", "DIGITS(123) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "123u", "INTEGER_VALUE(123u) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "123ui", "INTEGER_VALUE(123ui) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "0xDEADbeef", "DIGITS(0xDEADbeef) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "123.45", "REAL(123.45) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "123.45E10", "REAL(123.45E10) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "123.45E+10", "REAL(123.45E+10) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "1E+10", "REAL(1E+10) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "123l", "INTEGER_VALUE(123l) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "0b01u", "INTEGER_VALUE(0b01u) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "0xfful", "INTEGER_VALUE(0xfful) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "0o7ut", "INTEGER_VALUE(0o7ut) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "456s", "INTEGER_VALUE(456s) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "1.2345f", "REAL(1.2345f) EOF"); +} - Y_UNIT_TEST_ON_EACH_LEXER(IdQuoted) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED(lexer, "``", "ID_QUOTED(``) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "` `", "ID_QUOTED(` `) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "`local/table`", "ID_QUOTED(`local/table`) EOF"); - } +Y_UNIT_TEST_ON_EACH_LEXER(SingleLineString) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, "\"\"", "STRING_VALUE(\"\") EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "\' \'", "STRING_VALUE(\' \') EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "\" \"", "STRING_VALUE(\" \") EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "\"test\"", "STRING_VALUE(\"test\") EOF"); - Y_UNIT_TEST_ON_EACH_LEXER(Number) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED(lexer, "1", "DIGITS(1) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "123", "DIGITS(123) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "123u", "INTEGER_VALUE(123u) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "123ui", "INTEGER_VALUE(123ui) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "0xDEADbeef", "DIGITS(0xDEADbeef) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "123.45", "REAL(123.45) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "123.45E10", "REAL(123.45E10) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "123.45E+10", "REAL(123.45E+10) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "1E+10", "REAL(1E+10) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "123l", "INTEGER_VALUE(123l) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "0b01u", "INTEGER_VALUE(0b01u) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "0xfful", "INTEGER_VALUE(0xfful) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "0o7ut", "INTEGER_VALUE(0o7ut) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "456s", "INTEGER_VALUE(456s) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "1.2345f", "REAL(1.2345f) EOF"); + if (!ANSI) { + UNIT_ASSERT_TOKENIZED(lexer, "\"\\\"\"", "STRING_VALUE(\"\\\"\") EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "\"\"\"\"", "STRING_VALUE(\"\") STRING_VALUE(\"\") EOF"); + } else if (ANTLR4 || FLAVOR == ELexerFlavor::Regex) { + UNIT_ASSERT_TOKENIZED(lexer, "\"\\\"\"", "[INVALID] STRING_VALUE(\"\\\") EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "\"\"\"\"", "STRING_VALUE(\"\"\"\") EOF"); } +} - Y_UNIT_TEST_ON_EACH_LEXER(SingleLineString) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED(lexer, "\"\"", "STRING_VALUE(\"\") EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "\' \'", "STRING_VALUE(\' \') EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "\" \"", "STRING_VALUE(\" \") EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "\"test\"", "STRING_VALUE(\"test\") EOF"); - - if (!ANSI) { - UNIT_ASSERT_TOKENIZED(lexer, "\"\\\"\"", "STRING_VALUE(\"\\\"\") EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "\"\"\"\"", "STRING_VALUE(\"\") STRING_VALUE(\"\") EOF"); - } else if (ANTLR4 || FLAVOR == ELexerFlavor::Regex) { - UNIT_ASSERT_TOKENIZED(lexer, "\"\\\"\"", "[INVALID] STRING_VALUE(\"\\\") EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "\"\"\"\"", "STRING_VALUE(\"\"\"\") EOF"); - } - } +Y_UNIT_TEST_ON_EACH_LEXER(MultiLineString) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, "@@@@", "STRING_VALUE(@@@@) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "@@ @@@", "STRING_VALUE(@@ @@@) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "@@test@@", "STRING_VALUE(@@test@@) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "@@line1\nline2@@", "STRING_VALUE(@@line1\nline2@@) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "@@@@ @@A@@ @@@A@@", "STRING_VALUE(@@@@) WS( ) STRING_VALUE(@@A@@) WS( ) STRING_VALUE(@@@A@@) EOF"); +} - Y_UNIT_TEST_ON_EACH_LEXER(MultiLineString) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED(lexer, "@@@@", "STRING_VALUE(@@@@) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "@@ @@@", "STRING_VALUE(@@ @@@) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "@@test@@", "STRING_VALUE(@@test@@) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "@@line1\nline2@@", "STRING_VALUE(@@line1\nline2@@) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "@@@@ @@A@@ @@@A@@", "STRING_VALUE(@@@@) WS( ) STRING_VALUE(@@A@@) WS( ) STRING_VALUE(@@@A@@) EOF"); - } +Y_UNIT_TEST_ON_EACH_LEXER(SingleLineComment) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, "--yql", "COMMENT(--yql) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "-- yql ", "COMMENT(-- yql ) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "-- yql\nSELECT", "COMMENT(-- yql\n) SELECT EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "-- yql --", "COMMENT(-- yql --) EOF"); +} - Y_UNIT_TEST_ON_EACH_LEXER(SingleLineComment) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED(lexer, "--yql", "COMMENT(--yql) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "-- yql ", "COMMENT(-- yql ) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "-- yql\nSELECT", "COMMENT(-- yql\n) SELECT EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "-- yql --", "COMMENT(-- yql --) EOF"); - } +Y_UNIT_TEST_ON_EACH_LEXER(MultiLineComment) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, "/* yql */", "COMMENT(/* yql */) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "/* yql */ */", "COMMENT(/* yql */) WS( ) ASTERISK(*) SLASH(/) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "/* yql\n * yql\n */", "COMMENT(/* yql\n * yql\n */) EOF"); +} - Y_UNIT_TEST_ON_EACH_LEXER(MultiLineComment) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED(lexer, "/* yql */", "COMMENT(/* yql */) EOF"); +Y_UNIT_TEST_ON_EACH_LEXER(RecursiveMultiLineComment) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + if (!ANSI) { + UNIT_ASSERT_TOKENIZED(lexer, "/* /* yql */", "COMMENT(/* /* yql */) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "/* /* yql */ */", "COMMENT(/* /* yql */) WS( ) ASTERISK(*) SLASH(/) EOF"); + } else if (ANTLR4 || FLAVOR == ELexerFlavor::Regex) { + UNIT_ASSERT_TOKENIZED(lexer, "/* /* yql */", "COMMENT(/* /* yql */) EOF"); UNIT_ASSERT_TOKENIZED(lexer, "/* yql */ */", "COMMENT(/* yql */) WS( ) ASTERISK(*) SLASH(/) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "/* yql\n * yql\n */", "COMMENT(/* yql\n * yql\n */) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "/* /* /* yql */ */", "COMMENT(/* /* /* yql */ */) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "/* /* yql */ */ */", "COMMENT(/* /* yql */ */) WS( ) ASTERISK(*) SLASH(/) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "/* /* yql */ */", "COMMENT(/* /* yql */ */) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "/*/*/*/", "COMMENT(/*/*/) ASTERISK(*) SLASH(/) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "/*/**/*/*/*/", "COMMENT(/*/**/*/) ASTERISK(*) SLASH(/) ASTERISK(*) SLASH(/) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "/* /* */ a /* /* */", "COMMENT(/* /* */ a /* /* */) EOF"); } +} - Y_UNIT_TEST_ON_EACH_LEXER(RecursiveMultiLineComment) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - if (!ANSI) { - UNIT_ASSERT_TOKENIZED(lexer, "/* /* yql */", "COMMENT(/* /* yql */) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "/* /* yql */ */", "COMMENT(/* /* yql */) WS( ) ASTERISK(*) SLASH(/) EOF"); - } else if (ANTLR4 || FLAVOR == ELexerFlavor::Regex) { - UNIT_ASSERT_TOKENIZED(lexer, "/* /* yql */", "COMMENT(/* /* yql */) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "/* yql */ */", "COMMENT(/* yql */) WS( ) ASTERISK(*) SLASH(/) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "/* /* /* yql */ */", "COMMENT(/* /* /* yql */ */) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "/* /* yql */ */ */", "COMMENT(/* /* yql */ */) WS( ) ASTERISK(*) SLASH(/) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "/* /* yql */ */", "COMMENT(/* /* yql */ */) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "/*/*/*/", "COMMENT(/*/*/) ASTERISK(*) SLASH(/) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "/*/**/*/*/*/", "COMMENT(/*/**/*/) ASTERISK(*) SLASH(/) ASTERISK(*) SLASH(/) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "/* /* */ a /* /* */", "COMMENT(/* /* */ a /* /* */) EOF"); - } +Y_UNIT_TEST_ON_EACH_LEXER(RandomRecursiveMultiLineComment) { + if (!ANTLR4 && FLAVOR != ELexerFlavor::Regex || FLAVOR != ELexerFlavor::Pure) { + return; } - Y_UNIT_TEST_ON_EACH_LEXER(RandomRecursiveMultiLineComment) { - if (!ANTLR4 && FLAVOR != ELexerFlavor::Regex || FLAVOR != ELexerFlavor::Pure) { - return; - } - - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - auto reference = MakeLexer(Lexers, ANSI, /* antlr4 = */ true, ELexerFlavor::Pure); - - SetRandomSeed(100); - for (size_t i = 0; i < 128; ++i) { - auto input = RandomMultilineCommentLikeText(/* maxSize = */ 16); - TString actual = Tokenized(lexer, input); - TString expected = Tokenized(reference, input); + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + auto reference = MakeLexer(Lexers, ANSI, /* antlr4 = */ true, ELexerFlavor::Pure); - UNIT_ASSERT_VALUES_EQUAL_C(actual, expected, "Input: " << input); - } - } + SetRandomSeed(100); + for (size_t i = 0; i < 128; ++i) { + auto input = RandomMultilineCommentLikeText(/* maxSize = */ 16); + TString actual = Tokenized(lexer, input); + TString expected = Tokenized(reference, input); - Y_UNIT_TEST_ON_EACH_LEXER(SimpleQuery) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED(lexer, "select 1", "SELECT(select) WS( ) DIGITS(1) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "SELect 1", "SELECT(SELect) WS( ) DIGITS(1) EOF"); + UNIT_ASSERT_VALUES_EQUAL_C(actual, expected, "Input: " << input); } +} - Y_UNIT_TEST_ON_EACH_LEXER(ComplexQuery) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - - TString query = - "SELECT\n" - " 123467,\n" - " \"Hello, {name}!\",\n" - " (1 + (5U * 1 / 0)),\n" - " MIN(identifier),\n" - " Bool(field),\n" - " Math::Sin(var)\n" - "FROM `local/test/space/table`\n" - "JOIN test;"; - - TString expected = - "SELECT WS(\n) " - "WS( ) WS( ) DIGITS(123467) COMMA(,) WS(\n) " - "WS( ) WS( ) STRING_VALUE(\"Hello, {name}!\") COMMA(,) WS(\n) " - "WS( ) WS( ) LPAREN(() DIGITS(1) WS( ) PLUS(+) WS( ) LPAREN(() INTEGER_VALUE(5U) WS( ) " - "ASTERISK(*) WS( ) DIGITS(1) WS( ) SLASH(/) WS( ) DIGITS(0) RPAREN()) " - "RPAREN()) COMMA(,) WS(\n) " - "WS( ) WS( ) ID_PLAIN(MIN) LPAREN(() ID_PLAIN(identifier) RPAREN()) COMMA(,) WS(\n) " - "WS( ) WS( ) ID_PLAIN(Bool) LPAREN(() ID_PLAIN(field) RPAREN()) COMMA(,) WS(\n) " - "WS( ) WS( ) ID_PLAIN(Math) NAMESPACE(::) ID_PLAIN(Sin) LPAREN(() ID_PLAIN(var) RPAREN()) WS(\n) " - "FROM WS( ) ID_QUOTED(`local/test/space/table`) WS(\n) " - "JOIN WS( ) ID_PLAIN(test) SEMICOLON(;) EOF"; +Y_UNIT_TEST_ON_EACH_LEXER(SimpleQuery) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, "select 1", "SELECT(select) WS( ) DIGITS(1) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "SELect 1", "SELECT(SELect) WS( ) DIGITS(1) EOF"); +} - UNIT_ASSERT_TOKENIZED(lexer, query, expected); - } +Y_UNIT_TEST_ON_EACH_LEXER(ComplexQuery) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + + TString query = + "SELECT\n" + " 123467,\n" + " \"Hello, {name}!\",\n" + " (1 + (5U * 1 / 0)),\n" + " MIN(identifier),\n" + " Bool(field),\n" + " Math::Sin(var)\n" + "FROM `local/test/space/table`\n" + "JOIN test;"; + + TString expected = + "SELECT WS(\n) " + "WS( ) WS( ) DIGITS(123467) COMMA(,) WS(\n) " + "WS( ) WS( ) STRING_VALUE(\"Hello, {name}!\") COMMA(,) WS(\n) " + "WS( ) WS( ) LPAREN(() DIGITS(1) WS( ) PLUS(+) WS( ) LPAREN(() INTEGER_VALUE(5U) WS( ) " + "ASTERISK(*) WS( ) DIGITS(1) WS( ) SLASH(/) WS( ) DIGITS(0) RPAREN()) " + "RPAREN()) COMMA(,) WS(\n) " + "WS( ) WS( ) ID_PLAIN(MIN) LPAREN(() ID_PLAIN(identifier) RPAREN()) COMMA(,) WS(\n) " + "WS( ) WS( ) ID_PLAIN(Bool) LPAREN(() ID_PLAIN(field) RPAREN()) COMMA(,) WS(\n) " + "WS( ) WS( ) ID_PLAIN(Math) NAMESPACE(::) ID_PLAIN(Sin) LPAREN(() ID_PLAIN(var) RPAREN()) WS(\n) " + "FROM WS( ) ID_QUOTED(`local/test/space/table`) WS(\n) " + "JOIN WS( ) ID_PLAIN(test) SEMICOLON(;) EOF"; + + UNIT_ASSERT_TOKENIZED(lexer, query, expected); +} - Y_UNIT_TEST_ON_EACH_LEXER(Examples) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED( - lexer, - R"( +Y_UNIT_TEST_ON_EACH_LEXER(Examples) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED( + lexer, + R"( SELECT YQL::@@(Uint32 '100500)@@, YQL::@@(String '[WAT])@@ ;)", - "WS(\n) " - "SELECT WS(\n) WS( ) ID_PLAIN(YQL) NAMESPACE(::) STRING_VALUE(@@(Uint32 '100500)@@) COMMA(,) WS(\n) " - "WS( ) ID_PLAIN(YQL) NAMESPACE(::) STRING_VALUE(@@(String '[WAT])@@) WS(\n) " - "SEMICOLON(;) EOF"); - } - - Y_UNIT_TEST_ON_EACH_LEXER(AsciiEscape) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - UNIT_ASSERT_TOKENIZED(lexer, "\0", "EOF"); // Null character - UNIT_ASSERT_TOKENIZED(lexer, "\t", "WS(\t) EOF"); // Horizontal Tab - UNIT_ASSERT_TOKENIZED(lexer, "\n", "WS(\n) EOF"); // Line Feed - UNIT_ASSERT_TOKENIZED(lexer, "\v", "[INVALID] EOF"); // Vertical Tabulation - UNIT_ASSERT_TOKENIZED(lexer, "\f", "WS(\x0C) EOF"); // Form Feed - UNIT_ASSERT_TOKENIZED(lexer, "\r", "WS(\r) EOF"); // Carriage Return - UNIT_ASSERT_TOKENIZED(lexer, "\r\n", "WS(\r) WS(\n) EOF"); - } + "WS(\n) " + "SELECT WS(\n) WS( ) ID_PLAIN(YQL) NAMESPACE(::) STRING_VALUE(@@(Uint32 '100500)@@) COMMA(,) WS(\n) " + "WS( ) ID_PLAIN(YQL) NAMESPACE(::) STRING_VALUE(@@(String '[WAT])@@) WS(\n) " + "SEMICOLON(;) EOF"); +} - Y_UNIT_TEST_ON_EACH_LEXER(AsciiEscapeCanon) { - static THashMap<char, TString> canon; +Y_UNIT_TEST_ON_EACH_LEXER(AsciiEscape) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + UNIT_ASSERT_TOKENIZED(lexer, "\0", "EOF"); // Null character + UNIT_ASSERT_TOKENIZED(lexer, "\t", "WS(\t) EOF"); // Horizontal Tab + UNIT_ASSERT_TOKENIZED(lexer, "\n", "WS(\n) EOF"); // Line Feed + UNIT_ASSERT_TOKENIZED(lexer, "\v", "[INVALID] EOF"); // Vertical Tabulation + UNIT_ASSERT_TOKENIZED(lexer, "\f", "WS(\x0C) EOF"); // Form Feed + UNIT_ASSERT_TOKENIZED(lexer, "\r", "WS(\r) EOF"); // Carriage Return + UNIT_ASSERT_TOKENIZED(lexer, "\r\n", "WS(\r) WS(\n) EOF"); +} - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); +Y_UNIT_TEST_ON_EACH_LEXER(AsciiEscapeCanon) { + static THashMap<char, TString> canon; - for (char c = 0; c < std::numeric_limits<char>::max(); ++c) { - TString input; - input += c; + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - TString& expected = canon[c]; - if (expected.empty()) { - expected = Tokenized(lexer, input); - } + for (char c = 0; c < std::numeric_limits<char>::max(); ++c) { + TString input; + input += c; - UNIT_ASSERT_TOKENIZED(lexer, input, expected); + TString& expected = canon[c]; + if (expected.empty()) { + expected = Tokenized(lexer, input); } + + UNIT_ASSERT_TOKENIZED(lexer, input, expected); } +} - Y_UNIT_TEST_ON_EACH_LEXER(Utf8BOM) { - auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); - if (ANTLR4 || FLAVOR == ELexerFlavor::Regex) { - UNIT_ASSERT_TOKENIZED(lexer, "\xEF\xBB\xBF 1", "WS( ) DIGITS(1) EOF"); - UNIT_ASSERT_TOKENIZED(lexer, "\xEF\xBB\xBF \xEF\xBB\xBF", "[INVALID] WS( ) EOF"); - } else { - UNIT_ASSERT_TOKENIZED(lexer, "\xEF\xBB\xBF 1", "[INVALID] WS( ) DIGITS(1) EOF"); - } +Y_UNIT_TEST_ON_EACH_LEXER(Utf8BOM) { + auto lexer = MakeLexer(Lexers, ANSI, ANTLR4, FLAVOR); + if (ANTLR4 || FLAVOR == ELexerFlavor::Regex) { + UNIT_ASSERT_TOKENIZED(lexer, "\xEF\xBB\xBF 1", "WS( ) DIGITS(1) EOF"); + UNIT_ASSERT_TOKENIZED(lexer, "\xEF\xBB\xBF \xEF\xBB\xBF", "[INVALID] WS( ) EOF"); + } else { + UNIT_ASSERT_TOKENIZED(lexer, "\xEF\xBB\xBF 1", "[INVALID] WS( ) DIGITS(1) EOF"); } +} } // Y_UNIT_TEST_SUITE(SQLv1Lexer) diff --git a/yql/essentials/sql/v1/lexer/regex/generic.cpp b/yql/essentials/sql/v1/lexer/regex/generic.cpp index 50b2d78cf77..c27eec99b28 100644 --- a/yql/essentials/sql/v1/lexer/regex/generic.cpp +++ b/yql/essentials/sql/v1/lexer/regex/generic.cpp @@ -6,176 +6,176 @@ namespace NSQLTranslationV1 { - namespace { +namespace { - TMaybe<TStringBuf> Match(TStringBuf prefix, const RE2& regex) { - re2::StringPiece input(prefix.data(), prefix.size()); - if (RE2::Consume(&input, regex)) { - return TStringBuf(prefix.data(), input.data()); - } - return Nothing(); - } - - } // namespace - - class TGenericLexer: public IGenericLexer { - private: - static constexpr TStringBuf Utf8BOM = "\xEF\xBB\xBF"; - - public: - explicit TGenericLexer(TGenericLexerGrammar grammar) - : Grammar_(std::move(grammar)) - { - } - - virtual bool Tokenize( - TStringBuf text, - const TTokenCallback& onNext, - size_t maxErrors) const override { - Y_ENSURE(0 < maxErrors); - size_t errors = 0; +TMaybe<TStringBuf> Match(TStringBuf prefix, const RE2& regex) { + re2::StringPiece input(prefix.data(), prefix.size()); + if (RE2::Consume(&input, regex)) { + return TStringBuf(prefix.data(), input.data()); + } + return Nothing(); +} - size_t pos = 0; - if (text.StartsWith(Utf8BOM)) { - pos += Utf8BOM.size(); - } +} // namespace - while (pos < text.size() && errors < maxErrors) { - TMaybe<TGenericToken> prev; - TGenericToken next = Match(TStringBuf(text, pos)); +class TGenericLexer: public IGenericLexer { +private: + static constexpr TStringBuf Utf8BOM = "\xEF\xBB\xBF"; - size_t skipped = next.Begin; - next.Begin = skipped + pos; +public: + explicit TGenericLexer(TGenericLexerGrammar grammar) + : Grammar_(std::move(grammar)) + { + } - if (skipped != 0) { - prev = Match(TStringBuf(text, pos, skipped)); - prev->Begin = pos; - } + virtual bool Tokenize( + TStringBuf text, + const TTokenCallback& onNext, + size_t maxErrors) const override { + Y_ENSURE(0 < maxErrors); + size_t errors = 0; - pos += skipped + next.Content.size(); + size_t pos = 0; + if (text.StartsWith(Utf8BOM)) { + pos += Utf8BOM.size(); + } - if (next.Name == TGenericToken::Error) { - errors += 1; - } + while (pos < text.size() && errors < maxErrors) { + TMaybe<TGenericToken> prev; + TGenericToken next = Match(TStringBuf(text, pos)); - if (prev) { - onNext(std::move(*prev)); - } - onNext(std::move(next)); - } + size_t skipped = next.Begin; + next.Begin = skipped + pos; - if (errors == maxErrors) { - return false; + if (skipped != 0) { + prev = Match(TStringBuf(text, pos, skipped)); + prev->Begin = pos; } - onNext(TGenericToken{ - .Name = "EOF", - .Content = "<EOF>", - .Begin = pos, - }); - - return errors == 0; - } + pos += skipped + next.Content.size(); - private: - TGenericToken Match(TStringBuf prefix) const { - TMaybe<TGenericToken> max; - Match(prefix, [&](TGenericToken&& token) { - if (max.Empty() || max->Content.size() < token.Content.size()) { - max = std::move(token); - } - }); - - if (max) { - return *max; + if (next.Name == TGenericToken::Error) { + errors += 1; } - return { - .Name = TGenericToken::Error, - .Content = prefix.substr(0, 1), - }; + if (prev) { + onNext(std::move(*prev)); + } + onNext(std::move(next)); } - void Match(TStringBuf prefix, auto onMatch) const { - for (const auto& matcher : Grammar_) { - if (auto token = matcher(prefix)) { - onMatch(std::move(*token)); - } - } + if (errors == maxErrors) { + return false; } - TGenericLexerGrammar Grammar_; - }; + onNext(TGenericToken{ + .Name = "EOF", + .Content = "<EOF>", + .Begin = pos, + }); - TTokenMatcher Compile(TString name, const TRegexPattern& regex) { - RE2::Options options; - options.set_case_sensitive(!regex.IsCaseInsensitive); - - return [beforeRe = MakeAtomicShared<RE2>(regex.Before, options), - bodyRe = MakeAtomicShared<RE2>(regex.Body, options), - afterRe = MakeAtomicShared<RE2>(regex.After, options), - name = std::move(name)](TStringBuf prefix) -> TMaybe<TGenericToken> { - TMaybe<TStringBuf> before, body, after; - if ((before = Match(prefix, *beforeRe)) && - (body = Match(prefix.Tail(before->size()), *bodyRe)) && - (after = Match(prefix.Tail(before->size() + body->size()), *afterRe))) { - return TGenericToken{ - .Name = name, - .Content = *body, - .Begin = before->size(), - }; - } - return Nothing(); - }; + return errors == 0; } - TRegexPattern Merged(TVector<TRegexPattern> patterns) { - Y_ENSURE(!patterns.empty()); - - const TRegexPattern& sample = patterns.back(); - Y_ENSURE(AllOf(patterns, [&](const TRegexPattern& pattern) { - return std::tie(pattern.After, pattern.Before, pattern.IsCaseInsensitive) == - std::tie(sample.After, sample.Before, sample.IsCaseInsensitive); - })); - - Sort(patterns, [](const TRegexPattern& lhs, const TRegexPattern& rhs) { - const auto lhs_length = lhs.Body.length(); - const auto rhs_length = rhs.Body.length(); - - // Note: do not compare After and Before here as they are equal. - return std::tie(lhs_length, lhs.Body) > std::tie(rhs_length, rhs.Body); +private: + TGenericToken Match(TStringBuf prefix) const { + TMaybe<TGenericToken> max; + Match(prefix, [&](TGenericToken&& token) { + if (max.Empty() || max->Content.size() < token.Content.size()) { + max = std::move(token); + } }); - TStringBuilder body; - for (const auto& pattern : patterns) { - TString regex = pattern.Body; - if (pattern.Body.Contains('|')) { - regex.prepend('('); - regex.append(')'); - } - body << regex << "|"; + if (max) { + return *max; } - Y_ENSURE(body.back() == '|'); - body.pop_back(); - - return TRegexPattern{ - .Body = std::move(body), - .After = sample.After, - .Before = sample.Before, - .IsCaseInsensitive = sample.IsCaseInsensitive, + + return { + .Name = TGenericToken::Error, + .Content = prefix.substr(0, 1), }; } - IGenericLexer::TPtr MakeGenericLexer(TGenericLexerGrammar grammar) { - return IGenericLexer::TPtr(new TGenericLexer(std::move(grammar))); + void Match(TStringBuf prefix, auto onMatch) const { + for (const auto& matcher : Grammar_) { + if (auto token = matcher(prefix)) { + onMatch(std::move(*token)); + } + } } - TVector<TGenericToken> Tokenize(IGenericLexer::TPtr& lexer, TStringBuf text) { - TVector<TGenericToken> tokens; - lexer->Tokenize(text, [&](TGenericToken&& token) { - tokens.emplace_back(std::move(token)); - }); - return tokens; + TGenericLexerGrammar Grammar_; +}; + +TTokenMatcher Compile(TString name, const TRegexPattern& regex) { + RE2::Options options; + options.set_case_sensitive(!regex.IsCaseInsensitive); + + return [beforeRe = MakeAtomicShared<RE2>(regex.Before, options), + bodyRe = MakeAtomicShared<RE2>(regex.Body, options), + afterRe = MakeAtomicShared<RE2>(regex.After, options), + name = std::move(name)](TStringBuf prefix) -> TMaybe<TGenericToken> { + TMaybe<TStringBuf> before, body, after; + if ((before = Match(prefix, *beforeRe)) && + (body = Match(prefix.Tail(before->size()), *bodyRe)) && + (after = Match(prefix.Tail(before->size() + body->size()), *afterRe))) { + return TGenericToken{ + .Name = name, + .Content = *body, + .Begin = before->size(), + }; + } + return Nothing(); + }; +} + +TRegexPattern Merged(TVector<TRegexPattern> patterns) { + Y_ENSURE(!patterns.empty()); + + const TRegexPattern& sample = patterns.back(); + Y_ENSURE(AllOf(patterns, [&](const TRegexPattern& pattern) { + return std::tie(pattern.After, pattern.Before, pattern.IsCaseInsensitive) == + std::tie(sample.After, sample.Before, sample.IsCaseInsensitive); + })); + + Sort(patterns, [](const TRegexPattern& lhs, const TRegexPattern& rhs) { + const auto lhs_length = lhs.Body.length(); + const auto rhs_length = rhs.Body.length(); + + // Note: do not compare After and Before here as they are equal. + return std::tie(lhs_length, lhs.Body) > std::tie(rhs_length, rhs.Body); + }); + + TStringBuilder body; + for (const auto& pattern : patterns) { + TString regex = pattern.Body; + if (pattern.Body.Contains('|')) { + regex.prepend('('); + regex.append(')'); + } + body << regex << "|"; } + Y_ENSURE(body.back() == '|'); + body.pop_back(); + + return TRegexPattern{ + .Body = std::move(body), + .After = sample.After, + .Before = sample.Before, + .IsCaseInsensitive = sample.IsCaseInsensitive, + }; +} + +IGenericLexer::TPtr MakeGenericLexer(TGenericLexerGrammar grammar) { + return IGenericLexer::TPtr(new TGenericLexer(std::move(grammar))); +} + +TVector<TGenericToken> Tokenize(IGenericLexer::TPtr& lexer, TStringBuf text) { + TVector<TGenericToken> tokens; + lexer->Tokenize(text, [&](TGenericToken&& token) { + tokens.emplace_back(std::move(token)); + }); + return tokens; +} } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/regex/generic.h b/yql/essentials/sql/v1/lexer/regex/generic.h index 60c2a53207c..52d1498106c 100644 --- a/yql/essentials/sql/v1/lexer/regex/generic.h +++ b/yql/essentials/sql/v1/lexer/regex/generic.h @@ -10,44 +10,44 @@ namespace NSQLTranslationV1 { - struct TGenericToken { - static constexpr const char* Error = "<ERROR>"; +struct TGenericToken { + static constexpr const char* Error = "<ERROR>"; - TString Name; - TStringBuf Content; - size_t Begin = 0; // In bytes - }; + TString Name; + TStringBuf Content; + size_t Begin = 0; // In bytes +}; - class IGenericLexer: public TThrRefBase { - public: - using TPtr = TIntrusivePtr<IGenericLexer>; - using TTokenCallback = std::function<void(TGenericToken&& token)>; +class IGenericLexer: public TThrRefBase { +public: + using TPtr = TIntrusivePtr<IGenericLexer>; + using TTokenCallback = std::function<void(TGenericToken&& token)>; - static constexpr size_t MaxErrorsLimit = Max<size_t>(); + static constexpr size_t MaxErrorsLimit = Max<size_t>(); - virtual ~IGenericLexer() = default; - virtual bool Tokenize( - TStringBuf text, - const TTokenCallback& onNext, - size_t maxErrors = IGenericLexer::MaxErrorsLimit) const = 0; - }; + virtual ~IGenericLexer() = default; + virtual bool Tokenize( + TStringBuf text, + const TTokenCallback& onNext, + size_t maxErrors = IGenericLexer::MaxErrorsLimit) const = 0; +}; - using TTokenMatcher = std::function<TMaybe<TGenericToken>(TStringBuf prefix)>; +using TTokenMatcher = std::function<TMaybe<TGenericToken>(TStringBuf prefix)>; - using TGenericLexerGrammar = TVector<TTokenMatcher>; +using TGenericLexerGrammar = TVector<TTokenMatcher>; - struct TRegexPattern { - TString Body; - TString After = ""; - TString Before = ""; - bool IsCaseInsensitive = false; - }; +struct TRegexPattern { + TString Body; + TString After = ""; + TString Before = ""; + bool IsCaseInsensitive = false; +}; - TTokenMatcher Compile(TString name, const TRegexPattern& regex); - TRegexPattern Merged(TVector<TRegexPattern> patterns); +TTokenMatcher Compile(TString name, const TRegexPattern& regex); +TRegexPattern Merged(TVector<TRegexPattern> patterns); - IGenericLexer::TPtr MakeGenericLexer(TGenericLexerGrammar grammar); +IGenericLexer::TPtr MakeGenericLexer(TGenericLexerGrammar grammar); - TVector<TGenericToken> Tokenize(IGenericLexer::TPtr& lexer, TStringBuf text); +TVector<TGenericToken> Tokenize(IGenericLexer::TPtr& lexer, TStringBuf text); } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/regex/lexer.cpp b/yql/essentials/sql/v1/lexer/regex/lexer.cpp index 5d48c092716..7b9f2ba6e33 100644 --- a/yql/essentials/sql/v1/lexer/regex/lexer.cpp +++ b/yql/essentials/sql/v1/lexer/regex/lexer.cpp @@ -17,219 +17,219 @@ namespace NSQLTranslationV1 { - using NSQLReflect::TLexerGrammar; - using NSQLTranslation::TParsedToken; - using NSQLTranslation::TParsedTokenList; +using NSQLReflect::TLexerGrammar; +using NSQLTranslation::TParsedToken; +using NSQLTranslation::TParsedTokenList; - size_t MatchANSIMultilineComment(TStringBuf remaining); +size_t MatchANSIMultilineComment(TStringBuf remaining); - TTokenMatcher ANSICommentMatcher(TString name, TTokenMatcher defaultComment) { - return [defaultComment, name = std::move(name)](TStringBuf prefix) -> TMaybe<TGenericToken> { - const auto basic = defaultComment(prefix); - if (basic.Empty()) { - return Nothing(); - } - - if (!prefix.StartsWith("/*")) { - return basic; - } - - size_t ll1Length = MatchANSIMultilineComment(prefix); - TStringBuf ll1Content = prefix.SubString(0, ll1Length); - - Y_ENSURE(ll1Content == 0 || basic->Content <= ll1Content); - if (ll1Content == 0) { - return basic; - } - - return TGenericToken{ - .Name = name, - .Content = ll1Content, - }; - }; - } +TTokenMatcher ANSICommentMatcher(TString name, TTokenMatcher defaultComment) { + return [defaultComment, name = std::move(name)](TStringBuf prefix) -> TMaybe<TGenericToken> { + const auto basic = defaultComment(prefix); + if (basic.Empty()) { + return Nothing(); + } - size_t MatchANSIMultilineComment(TStringBuf prefix) { if (!prefix.StartsWith("/*")) { - return 0; + return basic; } - size_t skipped = 0; + size_t ll1Length = MatchANSIMultilineComment(prefix); + TStringBuf ll1Content = prefix.SubString(0, ll1Length); - prefix.Skip(2); - skipped += 2; + Y_ENSURE(ll1Content == 0 || basic->Content <= ll1Content); + if (ll1Content == 0) { + return basic; + } - for (;;) { - if (prefix.StartsWith("*/")) { - prefix.Skip(2); - skipped += 2; - return skipped; - } + return TGenericToken{ + .Name = name, + .Content = ll1Content, + }; + }; +} - bool isSkipped = false; - if (prefix.StartsWith("/*")) { - size_t limit = prefix.rfind("*/"); - if (limit == std::string::npos) { - return 0; - } +size_t MatchANSIMultilineComment(TStringBuf prefix) { + if (!prefix.StartsWith("/*")) { + return 0; + } - size_t len = MatchANSIMultilineComment(prefix.Head(limit)); - prefix.Skip(len); - skipped += len; + size_t skipped = 0; - isSkipped = len != 0; - } + prefix.Skip(2); + skipped += 2; - if (isSkipped) { - continue; - } + for (;;) { + if (prefix.StartsWith("*/")) { + prefix.Skip(2); + skipped += 2; + return skipped; + } - if (prefix.size() == 0) { + bool isSkipped = false; + if (prefix.StartsWith("/*")) { + size_t limit = prefix.rfind("*/"); + if (limit == std::string::npos) { return 0; } - prefix.Skip(1); - skipped += 1; - } - } + size_t len = MatchANSIMultilineComment(prefix.Head(limit)); + prefix.Skip(len); + skipped += len; - TTokenMatcher KeywordMatcher(const NSQLReflect::TLexerGrammar& grammar) { - auto keyword = Compile("Keyword", KeywordPattern(grammar)); - return [keyword = std::move(keyword)](TStringBuf content) -> TMaybe<TGenericToken> { - if (auto token = keyword(content)) { - return TGenericToken{ - .Name = TLexerGrammar::KeywordNameByBlock(token->Content), - .Content = token->Content, - }; - } - return Nothing(); - }; - } - - TRegexPattern KeywordPattern(const NSQLReflect::TLexerGrammar& grammar) { - TVector<TRegexPattern> patterns; - patterns.reserve(grammar.KeywordNames.size()); - for (const auto& keyword : grammar.KeywordNames) { - const TStringBuf content = TLexerGrammar::KeywordBlockByName(keyword); - patterns.push_back({ - .Body = TString(content), - .IsCaseInsensitive = true, - }); + isSkipped = len != 0; } - return Merged(std::move(patterns)); - } - TTokenMatcher PuntuationMatcher(const NSQLReflect::TLexerGrammar& grammar) { - THashMap<TString, TString> nameByBlock; - nameByBlock.reserve(grammar.PunctuationNames.size()); - for (const auto& name : grammar.PunctuationNames) { - const auto& block = grammar.BlockByName.at(name); - nameByBlock[block] = name; + if (isSkipped) { + continue; } - auto punct = Compile("Punctuation", PuntuationPattern(grammar)); + if (prefix.size() == 0) { + return 0; + } - return [nameByBlock = std::move(nameByBlock), - punct = std::move(punct)](TStringBuf content) -> TMaybe<TGenericToken> { - if (auto token = punct(content)) { - return TGenericToken{ - .Name = nameByBlock.at(token->Content), - .Content = token->Content, - }; - } - return Nothing(); - }; + prefix.Skip(1); + skipped += 1; } +} - TRegexPattern PuntuationPattern(const NSQLReflect::TLexerGrammar& grammar) { - TVector<TRegexPattern> patterns; - patterns.reserve(grammar.PunctuationNames.size()); - for (const auto& name : grammar.PunctuationNames) { - patterns.push_back({RE2::QuoteMeta(grammar.BlockByName.at(name))}); +TTokenMatcher KeywordMatcher(const NSQLReflect::TLexerGrammar& grammar) { + auto keyword = Compile("Keyword", KeywordPattern(grammar)); + return [keyword = std::move(keyword)](TStringBuf content) -> TMaybe<TGenericToken> { + if (auto token = keyword(content)) { + return TGenericToken{ + .Name = TLexerGrammar::KeywordNameByBlock(token->Content), + .Content = token->Content, + }; } - return Merged(std::move(patterns)); + return Nothing(); + }; +} + +TRegexPattern KeywordPattern(const NSQLReflect::TLexerGrammar& grammar) { + TVector<TRegexPattern> patterns; + patterns.reserve(grammar.KeywordNames.size()); + for (const auto& keyword : grammar.KeywordNames) { + const TStringBuf content = TLexerGrammar::KeywordBlockByName(keyword); + patterns.push_back({ + .Body = TString(content), + .IsCaseInsensitive = true, + }); + } + return Merged(std::move(patterns)); +} + +TTokenMatcher PuntuationMatcher(const NSQLReflect::TLexerGrammar& grammar) { + THashMap<TString, TString> nameByBlock; + nameByBlock.reserve(grammar.PunctuationNames.size()); + for (const auto& name : grammar.PunctuationNames) { + const auto& block = grammar.BlockByName.at(name); + nameByBlock[block] = name; } - TGenericLexerGrammar MakeGenericLexerGrammar( - bool ansi, - const TLexerGrammar& grammar, - const TVector<std::tuple<TString, TString>>& regexByOtherName) { - TGenericLexerGrammar generic; - - generic.emplace_back(KeywordMatcher(grammar)); - generic.emplace_back(PuntuationMatcher(grammar)); + auto punct = Compile("Punctuation", PuntuationPattern(grammar)); - for (const auto& [name, regex] : regexByOtherName) { - generic.emplace_back(Compile(name, {regex})); - if (name == "COMMENT" && ansi) { - generic.back() = ANSICommentMatcher(name, std::move(generic.back())); - } + return [nameByBlock = std::move(nameByBlock), + punct = std::move(punct)](TStringBuf content) -> TMaybe<TGenericToken> { + if (auto token = punct(content)) { + return TGenericToken{ + .Name = nameByBlock.at(token->Content), + .Content = token->Content, + }; } + return Nothing(); + }; +} - return generic; +TRegexPattern PuntuationPattern(const NSQLReflect::TLexerGrammar& grammar) { + TVector<TRegexPattern> patterns; + patterns.reserve(grammar.PunctuationNames.size()); + for (const auto& name : grammar.PunctuationNames) { + patterns.push_back({RE2::QuoteMeta(grammar.BlockByName.at(name))}); } - - class TRegexLexer: public NSQLTranslation::ILexer { - public: - TRegexLexer(IGenericLexer::TPtr lexer) - : Lexer_(std::move(lexer)) - { + return Merged(std::move(patterns)); +} + +TGenericLexerGrammar MakeGenericLexerGrammar( + bool ansi, + const TLexerGrammar& grammar, + const TVector<std::tuple<TString, TString>>& regexByOtherName) { + TGenericLexerGrammar generic; + + generic.emplace_back(KeywordMatcher(grammar)); + generic.emplace_back(PuntuationMatcher(grammar)); + + for (const auto& [name, regex] : regexByOtherName) { + generic.emplace_back(Compile(name, {regex})); + if (name == "COMMENT" && ansi) { + generic.back() = ANSICommentMatcher(name, std::move(generic.back())); } + } - bool Tokenize( - const TString& query, - const TString& queryName, - const TTokenCallback& onNextToken, - NYql::TIssues& issues, - size_t maxErrors) override { - bool isFailed = false; - - const auto onNext = [&](TGenericToken&& token) { - if (token.Name == TGenericToken::Error) { - NYql::TPosition pos(token.Begin, 0, queryName); - TString message = TString("no candidates, skipping ") + token.Content; - issues.AddIssue(std::move(pos), std::move(message)); - isFailed = true; - return; - } - - onNextToken({ - .Name = TString(token.Name), - .Content = TString(token.Content), - }); - }; + return generic; +} - Lexer_->Tokenize(query, onNext, maxErrors); - return !isFailed; - } +class TRegexLexer: public NSQLTranslation::ILexer { +public: + TRegexLexer(IGenericLexer::TPtr lexer) + : Lexer_(std::move(lexer)) + { + } - private: - IGenericLexer::TPtr Lexer_; - }; + bool Tokenize( + const TString& query, + const TString& queryName, + const TTokenCallback& onNextToken, + NYql::TIssues& issues, + size_t maxErrors) override { + bool isFailed = false; + + const auto onNext = [&](TGenericToken&& token) { + if (token.Name == TGenericToken::Error) { + NYql::TPosition pos(token.Begin, 0, queryName); + TString message = TString("no candidates, skipping ") + token.Content; + issues.AddIssue(std::move(pos), std::move(message)); + isFailed = true; + return; + } - namespace { + onNextToken({ + .Name = TString(token.Name), + .Content = TString(token.Content), + }); + }; - class TFactory final: public NSQLTranslation::ILexerFactory { - public: - explicit TFactory(bool ansi) { - auto grammar = NSQLReflect::LoadLexerGrammar(); - auto regexes = MakeRegexByOtherName(grammar, ansi); - Lexer_ = MakeGenericLexer(MakeGenericLexerGrammar(ansi, grammar, regexes)); - } + Lexer_->Tokenize(query, onNext, maxErrors); + return !isFailed; + } - NSQLTranslation::ILexer::TPtr MakeLexer() const override { - return NSQLTranslation::ILexer::TPtr( - new TRegexLexer(Lexer_)); - } +private: + IGenericLexer::TPtr Lexer_; +}; - private: - IGenericLexer::TPtr Lexer_; - }; +namespace { - } // namespace +class TFactory final: public NSQLTranslation::ILexerFactory { +public: + explicit TFactory(bool ansi) { + auto grammar = NSQLReflect::LoadLexerGrammar(); + auto regexes = MakeRegexByOtherName(grammar, ansi); + Lexer_ = MakeGenericLexer(MakeGenericLexerGrammar(ansi, grammar, regexes)); + } - NSQLTranslation::TLexerFactoryPtr MakeRegexLexerFactory(bool ansi) { - return NSQLTranslation::TLexerFactoryPtr(new TFactory(ansi)); + NSQLTranslation::ILexer::TPtr MakeLexer() const override { + return NSQLTranslation::ILexer::TPtr( + new TRegexLexer(Lexer_)); } +private: + IGenericLexer::TPtr Lexer_; +}; + +} // namespace + +NSQLTranslation::TLexerFactoryPtr MakeRegexLexerFactory(bool ansi) { + return NSQLTranslation::TLexerFactoryPtr(new TFactory(ansi)); +} + } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/regex/lexer.h b/yql/essentials/sql/v1/lexer/regex/lexer.h index 32c145c6484..462d749f1ae 100644 --- a/yql/essentials/sql/v1/lexer/regex/lexer.h +++ b/yql/essentials/sql/v1/lexer/regex/lexer.h @@ -7,12 +7,12 @@ namespace NSQLTranslationV1 { - TTokenMatcher ANSICommentMatcher(TString name, TTokenMatcher defaultComment); +TTokenMatcher ANSICommentMatcher(TString name, TTokenMatcher defaultComment); - TRegexPattern KeywordPattern(const NSQLReflect::TLexerGrammar& grammar); +TRegexPattern KeywordPattern(const NSQLReflect::TLexerGrammar& grammar); - TRegexPattern PuntuationPattern(const NSQLReflect::TLexerGrammar& grammar); +TRegexPattern PuntuationPattern(const NSQLReflect::TLexerGrammar& grammar); - NSQLTranslation::TLexerFactoryPtr MakeRegexLexerFactory(bool ansi); +NSQLTranslation::TLexerFactoryPtr MakeRegexLexerFactory(bool ansi); } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/regex/lexer_ut.cpp b/yql/essentials/sql/v1/lexer/regex/lexer_ut.cpp index 6ac25008b34..cbff9085514 100644 --- a/yql/essentials/sql/v1/lexer/regex/lexer_ut.cpp +++ b/yql/essentials/sql/v1/lexer/regex/lexer_ut.cpp @@ -92,128 +92,128 @@ void Check(TString input, TString expected) { } Y_UNIT_TEST_SUITE(RegexLexerTests) { - Y_UNIT_TEST(Whitespace) { - Check("", "EOF"); - Check(" ", "WS( ) EOF"); - Check(" ", "WS( ) WS( ) EOF"); - Check("\n", "WS(\n) EOF"); - } +Y_UNIT_TEST(Whitespace) { + Check("", "EOF"); + Check(" ", "WS( ) EOF"); + Check(" ", "WS( ) WS( ) EOF"); + Check("\n", "WS(\n) EOF"); +} - Y_UNIT_TEST(SinleLineComment) { - Check("--yql", "COMMENT(--yql) EOF"); - Check("-- yql ", "COMMENT(-- yql ) EOF"); - Check("-- yql\nSELECT", "COMMENT(-- yql\n) SELECT EOF"); - Check("-- yql --", "COMMENT(-- yql --) EOF"); - } +Y_UNIT_TEST(SinleLineComment) { + Check("--yql", "COMMENT(--yql) EOF"); + Check("-- yql ", "COMMENT(-- yql ) EOF"); + Check("-- yql\nSELECT", "COMMENT(-- yql\n) SELECT EOF"); + Check("-- yql --", "COMMENT(-- yql --) EOF"); +} - Y_UNIT_TEST(MultiLineComment) { - Check("/* yql */", "COMMENT(/* yql */) EOF"); - Check("/* yql */ */", "COMMENT(/* yql */) WS( ) ASTERISK(*) SLASH(/) EOF"); - Check("/* yql\n * yql\n */", "COMMENT(/* yql\n * yql\n */) EOF"); - } +Y_UNIT_TEST(MultiLineComment) { + Check("/* yql */", "COMMENT(/* yql */) EOF"); + Check("/* yql */ */", "COMMENT(/* yql */) WS( ) ASTERISK(*) SLASH(/) EOF"); + Check("/* yql\n * yql\n */", "COMMENT(/* yql\n * yql\n */) EOF"); +} - Y_UNIT_TEST(RecursiveMultiLineCommentDefault) { - Check("/* /* yql */", "COMMENT(/* /* yql */) EOF", /* ansi = */ false); - Check("/* /* yql */ */", "COMMENT(/* /* yql */) WS( ) ASTERISK(*) SLASH(/) EOF", /* ansi = */ false); - } +Y_UNIT_TEST(RecursiveMultiLineCommentDefault) { + Check("/* /* yql */", "COMMENT(/* /* yql */) EOF", /* ansi = */ false); + Check("/* /* yql */ */", "COMMENT(/* /* yql */) WS( ) ASTERISK(*) SLASH(/) EOF", /* ansi = */ false); +} - Y_UNIT_TEST(RecursiveMultiLineCommentAnsi) { - Check("/* /* yql */", "COMMENT(/* /* yql */) EOF", /* ansi = */ true); - Check("/* yql */ */", "COMMENT(/* yql */) WS( ) ASTERISK(*) SLASH(/) EOF", /* ansi = */ true); - Check("/* /* /* yql */ */", "COMMENT(/* /* /* yql */ */) EOF", /* ansi = */ true); - Check("/* /* yql */ */ */", "COMMENT(/* /* yql */ */) WS( ) ASTERISK(*) SLASH(/) EOF", /* ansi = */ true); - Check("/* /* yql */ */", "COMMENT(/* /* yql */ */) EOF", /* ansi = */ true); - Check("/*/*/*/", "COMMENT(/*/*/) ASTERISK(*) SLASH(/) EOF", /* ansi = */ true); - Check("/*/**/*/*/*/", "COMMENT(/*/**/*/) ASTERISK(*) SLASH(/) ASTERISK(*) SLASH(/) EOF", /* ansi = */ true); - Check("/* /* */ a /* /* */", "COMMENT(/* /* */ a /* /* */) EOF", /* ansi = */ true); - } +Y_UNIT_TEST(RecursiveMultiLineCommentAnsi) { + Check("/* /* yql */", "COMMENT(/* /* yql */) EOF", /* ansi = */ true); + Check("/* yql */ */", "COMMENT(/* yql */) WS( ) ASTERISK(*) SLASH(/) EOF", /* ansi = */ true); + Check("/* /* /* yql */ */", "COMMENT(/* /* /* yql */ */) EOF", /* ansi = */ true); + Check("/* /* yql */ */ */", "COMMENT(/* /* yql */ */) WS( ) ASTERISK(*) SLASH(/) EOF", /* ansi = */ true); + Check("/* /* yql */ */", "COMMENT(/* /* yql */ */) EOF", /* ansi = */ true); + Check("/*/*/*/", "COMMENT(/*/*/) ASTERISK(*) SLASH(/) EOF", /* ansi = */ true); + Check("/*/**/*/*/*/", "COMMENT(/*/**/*/) ASTERISK(*) SLASH(/) ASTERISK(*) SLASH(/) EOF", /* ansi = */ true); + Check("/* /* */ a /* /* */", "COMMENT(/* /* */ a /* /* */) EOF", /* ansi = */ true); +} - Y_UNIT_TEST(RecursiveMultiLineCommentAnsiReferenceComparion) { - SetRandomSeed(100); - for (size_t i = 0; i < 512; ++i) { - auto input = RandomMultilineCommentLikeText(/* maxSize = */ 128); - TString actual = Tokenized(*AnsiLexer, input); - TString expected = Tokenized(*PureAnsiLexer, input); - UNIT_ASSERT_VALUES_EQUAL_C(actual, expected, "Input: " << input); - } +Y_UNIT_TEST(RecursiveMultiLineCommentAnsiReferenceComparion) { + SetRandomSeed(100); + for (size_t i = 0; i < 512; ++i) { + auto input = RandomMultilineCommentLikeText(/* maxSize = */ 128); + TString actual = Tokenized(*AnsiLexer, input); + TString expected = Tokenized(*PureAnsiLexer, input); + UNIT_ASSERT_VALUES_EQUAL_C(actual, expected, "Input: " << input); } +} - Y_UNIT_TEST(Keyword) { - Check("SELECT", "SELECT EOF"); - Check("INSERT", "INSERT EOF"); - Check("FROM", "FROM EOF"); - } +Y_UNIT_TEST(Keyword) { + Check("SELECT", "SELECT EOF"); + Check("INSERT", "INSERT EOF"); + Check("FROM", "FROM EOF"); +} - Y_UNIT_TEST(Punctuation) { - Check( - "* / + - <|", - "ASTERISK(*) WS( ) SLASH(/) WS( ) " - "PLUS(+) WS( ) MINUS(-) WS( ) STRUCT_OPEN(<|) EOF"); - Check("SELECT*FROM", "SELECT ASTERISK(*) FROM EOF"); - } +Y_UNIT_TEST(Punctuation) { + Check( + "* / + - <|", + "ASTERISK(*) WS( ) SLASH(/) WS( ) " + "PLUS(+) WS( ) MINUS(-) WS( ) STRUCT_OPEN(<|) EOF"); + Check("SELECT*FROM", "SELECT ASTERISK(*) FROM EOF"); +} - Y_UNIT_TEST(IdPlain) { - Check("variable my_table", "ID_PLAIN(variable) WS( ) ID_PLAIN(my_table) EOF"); - } +Y_UNIT_TEST(IdPlain) { + Check("variable my_table", "ID_PLAIN(variable) WS( ) ID_PLAIN(my_table) EOF"); +} - Y_UNIT_TEST(IdQuoted) { - Check("``", "ID_QUOTED(``) EOF"); - Check("` `", "ID_QUOTED(` `) EOF"); - Check("` `", "ID_QUOTED(` `) EOF"); - Check("`local/table`", "ID_QUOTED(`local/table`) EOF"); - } +Y_UNIT_TEST(IdQuoted) { + Check("``", "ID_QUOTED(``) EOF"); + Check("` `", "ID_QUOTED(` `) EOF"); + Check("` `", "ID_QUOTED(` `) EOF"); + Check("`local/table`", "ID_QUOTED(`local/table`) EOF"); +} - Y_UNIT_TEST(SinleLineString) { - Check("\"\"", "STRING_VALUE(\"\") EOF"); - Check("\' \'", "STRING_VALUE(\' \') EOF"); - Check("\" \"", "STRING_VALUE(\" \") EOF"); - Check("\"test\"", "STRING_VALUE(\"test\") EOF"); +Y_UNIT_TEST(SinleLineString) { + Check("\"\"", "STRING_VALUE(\"\") EOF"); + Check("\' \'", "STRING_VALUE(\' \') EOF"); + Check("\" \"", "STRING_VALUE(\" \") EOF"); + Check("\"test\"", "STRING_VALUE(\"test\") EOF"); - Check("\"\\\"\"", "STRING_VALUE(\"\\\"\") EOF", /* ansi = */ false); - Check("\"\\\"\"", "[INVALID] STRING_VALUE(\"\\\") EOF", /* ansi = */ true); + Check("\"\\\"\"", "STRING_VALUE(\"\\\"\") EOF", /* ansi = */ false); + Check("\"\\\"\"", "[INVALID] STRING_VALUE(\"\\\") EOF", /* ansi = */ true); - Check("\"\"\"\"", "STRING_VALUE(\"\") STRING_VALUE(\"\") EOF", /* ansi = */ false); - Check("\"\"\"\"", "STRING_VALUE(\"\"\"\") EOF", /* ansi = */ true); - } + Check("\"\"\"\"", "STRING_VALUE(\"\") STRING_VALUE(\"\") EOF", /* ansi = */ false); + Check("\"\"\"\"", "STRING_VALUE(\"\"\"\") EOF", /* ansi = */ true); +} - Y_UNIT_TEST(MultiLineString) { - Check("@@@@", "STRING_VALUE(@@@@) EOF"); - Check("@@ @@@", "STRING_VALUE(@@ @@@) EOF"); - Check("@@test@@", "STRING_VALUE(@@test@@) EOF"); - Check("@@line1\nline2@@", "STRING_VALUE(@@line1\nline2@@) EOF"); - } +Y_UNIT_TEST(MultiLineString) { + Check("@@@@", "STRING_VALUE(@@@@) EOF"); + Check("@@ @@@", "STRING_VALUE(@@ @@@) EOF"); + Check("@@test@@", "STRING_VALUE(@@test@@) EOF"); + Check("@@line1\nline2@@", "STRING_VALUE(@@line1\nline2@@) EOF"); +} - Y_UNIT_TEST(Query) { - TString query = - "SELECT\n" - " 123467,\n" - " \"Hello, {name}!\",\n" - " (1 + (5 * 1 / 0)),\n" - " MIN(identifier),\n" - " Bool(field),\n" - " Math::Sin(var)\n" - "FROM `local/test/space/table`\n" - "JOIN test;"; - - TString expected = - "SELECT WS(\n) " - "WS( ) WS( ) DIGITS(123467) COMMA(,) WS(\n) " - "WS( ) WS( ) STRING_VALUE(\"Hello, {name}!\") COMMA(,) WS(\n) " - "WS( ) WS( ) LPAREN(() DIGITS(1) WS( ) PLUS(+) WS( ) LPAREN(() DIGITS(5) WS( ) " - "ASTERISK(*) WS( ) DIGITS(1) WS( ) SLASH(/) WS( ) DIGITS(0) RPAREN()) " - "RPAREN()) COMMA(,) WS(\n) " - "WS( ) WS( ) ID_PLAIN(MIN) LPAREN(() ID_PLAIN(identifier) RPAREN()) COMMA(,) WS(\n) " - "WS( ) WS( ) ID_PLAIN(Bool) LPAREN(() ID_PLAIN(field) RPAREN()) COMMA(,) WS(\n) " - "WS( ) WS( ) ID_PLAIN(Math) NAMESPACE(::) ID_PLAIN(Sin) LPAREN(() ID_PLAIN(var) RPAREN()) WS(\n) " - "FROM WS( ) ID_QUOTED(`local/test/space/table`) WS(\n) " - "JOIN WS( ) ID_PLAIN(test) SEMICOLON(;) EOF"; - - Check(query, expected); - } +Y_UNIT_TEST(Query) { + TString query = + "SELECT\n" + " 123467,\n" + " \"Hello, {name}!\",\n" + " (1 + (5 * 1 / 0)),\n" + " MIN(identifier),\n" + " Bool(field),\n" + " Math::Sin(var)\n" + "FROM `local/test/space/table`\n" + "JOIN test;"; + + TString expected = + "SELECT WS(\n) " + "WS( ) WS( ) DIGITS(123467) COMMA(,) WS(\n) " + "WS( ) WS( ) STRING_VALUE(\"Hello, {name}!\") COMMA(,) WS(\n) " + "WS( ) WS( ) LPAREN(() DIGITS(1) WS( ) PLUS(+) WS( ) LPAREN(() DIGITS(5) WS( ) " + "ASTERISK(*) WS( ) DIGITS(1) WS( ) SLASH(/) WS( ) DIGITS(0) RPAREN()) " + "RPAREN()) COMMA(,) WS(\n) " + "WS( ) WS( ) ID_PLAIN(MIN) LPAREN(() ID_PLAIN(identifier) RPAREN()) COMMA(,) WS(\n) " + "WS( ) WS( ) ID_PLAIN(Bool) LPAREN(() ID_PLAIN(field) RPAREN()) COMMA(,) WS(\n) " + "WS( ) WS( ) ID_PLAIN(Math) NAMESPACE(::) ID_PLAIN(Sin) LPAREN(() ID_PLAIN(var) RPAREN()) WS(\n) " + "FROM WS( ) ID_QUOTED(`local/test/space/table`) WS(\n) " + "JOIN WS( ) ID_PLAIN(test) SEMICOLON(;) EOF"; + + Check(query, expected); +} - Y_UNIT_TEST(Invalid) { - Check("\"", "[INVALID] EOF"); - Check("\" SELECT", "[INVALID] WS( ) SELECT EOF"); - } +Y_UNIT_TEST(Invalid) { + Check("\"", "[INVALID] EOF"); + Check("\" SELECT", "[INVALID] WS( ) SELECT EOF"); +} } // Y_UNIT_TEST_SUITE(RegexLexerTests) diff --git a/yql/essentials/sql/v1/lexer/regex/regex.cpp b/yql/essentials/sql/v1/lexer/regex/regex.cpp index 4d50d26e046..05e62b65423 100644 --- a/yql/essentials/sql/v1/lexer/regex/regex.cpp +++ b/yql/essentials/sql/v1/lexer/regex/regex.cpp @@ -18,254 +18,254 @@ namespace NSQLTranslationV1 { - class TLexerGrammarToRegexTranslator { - private: - struct TRewriteRule { - TString Repr; - std::function<void(TString&)> Apply; - }; +class TLexerGrammarToRegexTranslator { +private: + struct TRewriteRule { + TString Repr; + std::function<void(TString&)> Apply; + }; - using TRewriteRules = TVector<TRewriteRule>; + using TRewriteRules = TVector<TRewriteRule>; - public: - explicit TLexerGrammarToRegexTranslator(const NSQLReflect::TLexerGrammar& grammar, bool ansi) - : Grammar_(&grammar) - , Mode_(ansi ? "ANSI" : "DEFAULT") - { - AddExternalRules(Inliners_); - AddFragmentRules(Inliners_); +public: + explicit TLexerGrammarToRegexTranslator(const NSQLReflect::TLexerGrammar& grammar, bool ansi) + : Grammar_(&grammar) + , Mode_(ansi ? "ANSI" : "DEFAULT") + { + AddExternalRules(Inliners_); + AddFragmentRules(Inliners_); - AddLetterRules(Transformations_); - AddTransformationRules(Transformations_); + AddLetterRules(Transformations_); + AddTransformationRules(Transformations_); - UnwrapQuotes_ = UnwrapQuotesRule(); - AddSpaceCollapses(SpaceCollapses_); - UnwrapQuotedSpace_ = UnwrapQuotedSpaceRule(); - AddRegexOptimizations(RegexOptimizations_); - } + UnwrapQuotes_ = UnwrapQuotesRule(); + AddSpaceCollapses(SpaceCollapses_); + UnwrapQuotedSpace_ = UnwrapQuotedSpaceRule(); + AddRegexOptimizations(RegexOptimizations_); + } - TString ToRegex(const TStringBuf name) { - TString text = Grammar_->BlockByName.at(name); - Preprocess(text); - Inline(text); - Transform(text); - Finalize(text); - return text; - } + TString ToRegex(const TStringBuf name) { + TString text = Grammar_->BlockByName.at(name); + Preprocess(text); + Inline(text); + Transform(text); + Finalize(text); + return text; + } - private: - void Preprocess(TString& text) { - text = ChangedDigitsPrecendence(std::move(text)); - } +private: + void Preprocess(TString& text) { + text = ChangedDigitsPrecendence(std::move(text)); + } - void Inline(TString& text) { - ApplyEachWhileChanging(text, Inliners_); - } + void Inline(TString& text) { + ApplyEachWhileChanging(text, Inliners_); + } - void AddExternalRules(TRewriteRules& rules) { - THashMap<TString, THashMap<TString, TString>> Substitutions = { - SUBSTITUTIONS(DEFAULT), - SUBSTITUTIONS(ANSI), - }; + void AddExternalRules(TRewriteRules& rules) { + THashMap<TString, THashMap<TString, TString>> Substitutions = { + SUBSTITUTIONS(DEFAULT), + SUBSTITUTIONS(ANSI), + }; - // ANSI mode MULTILINE_COMMENT is recursive - Substitutions["ANSI"]["GRAMMAR_MULTILINE_COMMENT_CORE"] = - Substitutions["DEFAULT"]["GRAMMAR_MULTILINE_COMMENT_CORE"]; + // ANSI mode MULTILINE_COMMENT is recursive + Substitutions["ANSI"]["GRAMMAR_MULTILINE_COMMENT_CORE"] = + Substitutions["DEFAULT"]["GRAMMAR_MULTILINE_COMMENT_CORE"]; - for (const auto& [k, v] : Substitutions.at(Mode_)) { - rules.emplace_back(RegexRewriteRule("@" + k + "@", v)); - } + for (const auto& [k, v] : Substitutions.at(Mode_)) { + rules.emplace_back(RegexRewriteRule("@" + k + "@", v)); } + } - void AddFragmentRules(TRewriteRules& rules) { - const THashSet<TString> PunctuationFragments = { - "BACKSLASH", - "QUOTE_DOUBLE", - "QUOTE_SINGLE", - "BACKTICK", - "DOUBLE_COMMAT", - }; - - for (const auto& [name, definition] : Grammar_->BlockByName) { - TString def = definition; - if ( - Grammar_->PunctuationNames.contains(name) || - PunctuationFragments.contains(name)) { - def = "'" + def + "'"; - } else if (name == "DIGITS") { - def = ChangedDigitsPrecendence(std::move(def)); - } - def = QuoteAntlrRewrite(std::move(def)); + void AddFragmentRules(TRewriteRules& rules) { + const THashSet<TString> PunctuationFragments = { + "BACKSLASH", + "QUOTE_DOUBLE", + "QUOTE_SINGLE", + "BACKTICK", + "DOUBLE_COMMAT", + }; - rules.emplace_back(RegexRewriteRule( - "(\\b" + name + "\\b)", - "(" + def + ")")); + for (const auto& [name, definition] : Grammar_->BlockByName) { + TString def = definition; + if ( + Grammar_->PunctuationNames.contains(name) || + PunctuationFragments.contains(name)) { + def = "'" + def + "'"; + } else if (name == "DIGITS") { + def = ChangedDigitsPrecendence(std::move(def)); } - } + def = QuoteAntlrRewrite(std::move(def)); - // Regex engine matches the first matched alternative, - // even if it is not the longest one, while ANTLR is more gready. - TString ChangedDigitsPrecendence(TString body) { - if (SubstGlobal(body, "DECDIGITS | ", "") != 0) { - SubstGlobal(body, "BINDIGITS", "BINDIGITS | DECDIGITS"); - } - return body; + rules.emplace_back(RegexRewriteRule( + "(\\b" + name + "\\b)", + "(" + def + ")")); } + } - void Transform(TString& text) { - ApplyEachWhileChanging(text, Transformations_); + // Regex engine matches the first matched alternative, + // even if it is not the longest one, while ANTLR is more gready. + TString ChangedDigitsPrecendence(TString body) { + if (SubstGlobal(body, "DECDIGITS | ", "") != 0) { + SubstGlobal(body, "BINDIGITS", "BINDIGITS | DECDIGITS"); } + return body; + } - void AddLetterRules(TRewriteRules& rules) { - for (char letter = 'A'; letter <= 'Z'; ++letter) { - TString lower(char(ToLower(letter))); - TString upper(char(ToUpper(letter))); - rules.emplace_back(RegexRewriteRule( - "([^'\\w\\[\\]]|^)" + upper + "([^'\\w\\[\\]]|$)", - "\\1[" + lower + upper + "]\\2")); - } - } + void Transform(TString& text) { + ApplyEachWhileChanging(text, Transformations_); + } - void AddTransformationRules(TRewriteRules& rules) { + void AddLetterRules(TRewriteRules& rules) { + for (char letter = 'A'; letter <= 'Z'; ++letter) { + TString lower(char(ToLower(letter))); + TString upper(char(ToUpper(letter))); rules.emplace_back(RegexRewriteRule( - R"(~\('(..?)' \| '(..?)'\))", R"([^\1\2])")); + "([^'\\w\\[\\]]|^)" + upper + "([^'\\w\\[\\]]|$)", + "\\1[" + lower + upper + "]\\2")); + } + } - rules.emplace_back(RegexRewriteRule( - R"(~\('(..?)'\))", R"([^\1])")); + void AddTransformationRules(TRewriteRules& rules) { + rules.emplace_back(RegexRewriteRule( + R"(~\('(..?)' \| '(..?)'\))", R"([^\1\2])")); - rules.emplace_back(RegexRewriteRule( - R"(('..?')\.\.('..?'))", R"([\1-\2])")); + rules.emplace_back(RegexRewriteRule( + R"(~\('(..?)'\))", R"([^\1])")); - rules.emplace_back(RegexRewriteRule( - R"(\((.)\))", R"(\1)")); + rules.emplace_back(RegexRewriteRule( + R"(('..?')\.\.('..?'))", R"([\1-\2])")); - rules.emplace_back(RegexRewriteRule( - R"(\((\[.{1,8}\])\))", R"(\1)")); + rules.emplace_back(RegexRewriteRule( + R"(\((.)\))", R"(\1)")); - rules.emplace_back(RegexRewriteRule( - R"(\(('..?')\))", R"(\1)")); + rules.emplace_back(RegexRewriteRule( + R"(\((\[.{1,8}\])\))", R"(\1)")); - rules.emplace_back(RegexRewriteRule( - R"( \.)", R"( (.|\\n))")); + rules.emplace_back(RegexRewriteRule( + R"(\(('..?')\))", R"(\1)")); - rules.emplace_back(RegexRewriteRule( - R"(\bEOF\b)", R"($)")); + rules.emplace_back(RegexRewriteRule( + R"( \.)", R"( (.|\\n))")); - rules.emplace_back(RegexRewriteRule( - R"('\\u000C' \|)", R"('\\f' |)")); - } + rules.emplace_back(RegexRewriteRule( + R"(\bEOF\b)", R"($)")); - void Finalize(TString& text) { - UnwrapQuotes_.Apply(text); - ApplyEachWhileChanging(text, SpaceCollapses_); - UnwrapQuotedSpace_.Apply(text); - ApplyEachWhileChanging(text, RegexOptimizations_); - } + rules.emplace_back(RegexRewriteRule( + R"('\\u000C' \|)", R"('\\f' |)")); + } - void AddSpaceCollapses(TRewriteRules& rules) { - rules.emplace_back(RegexRewriteRule(R"(([^']|^) )", R"(\1)")); - rules.emplace_back(RegexRewriteRule(R"( ([^']|$))", R"(\1)")); - } + void Finalize(TString& text) { + UnwrapQuotes_.Apply(text); + ApplyEachWhileChanging(text, SpaceCollapses_); + UnwrapQuotedSpace_.Apply(text); + ApplyEachWhileChanging(text, RegexOptimizations_); + } - void AddRegexOptimizations(TRewriteRules& rules) { - // ([a-z]|_) -> ([a-z_]) - rules.emplace_back(RegexRewriteRule( - R"re(\[([^\^\[\]]+)\]\|(.)([\)\|]))re", - R"re([\1\2]\3)re")); + void AddSpaceCollapses(TRewriteRules& rules) { + rules.emplace_back(RegexRewriteRule(R"(([^']|^) )", R"(\1)")); + rules.emplace_back(RegexRewriteRule(R"( ([^']|$))", R"(\1)")); + } - // ([a-z]|[A-Z]) -> ([a-zA-Z]) - rules.emplace_back(RegexRewriteRule( - R"re(\[([^\^\[\]]+)\]\|\[([^\^\[\]]+)\]([\)\|]))re", - R"re([\1\2]\3)re")); - } + void AddRegexOptimizations(TRewriteRules& rules) { + // ([a-z]|_) -> ([a-z_]) + rules.emplace_back(RegexRewriteRule( + R"re(\[([^\^\[\]]+)\]\|(.)([\)\|]))re", + R"re([\1\2]\3)re")); - void ApplyEachOnce(TString& text, const TRewriteRules& rules) { - for (const auto& rule : rules) { - rule.Apply(text); - } + // ([a-z]|[A-Z]) -> ([a-zA-Z]) + rules.emplace_back(RegexRewriteRule( + R"re(\[([^\^\[\]]+)\]\|\[([^\^\[\]]+)\]([\)\|]))re", + R"re([\1\2]\3)re")); + } + + void ApplyEachOnce(TString& text, const TRewriteRules& rules) { + for (const auto& rule : rules) { + rule.Apply(text); } + } - void ApplyEachWhileChanging(TString& text, const TRewriteRules& rules) { - constexpr size_t Limit = 16; + void ApplyEachWhileChanging(TString& text, const TRewriteRules& rules) { + constexpr size_t Limit = 16; - TString prev; - for (size_t i = 0; i < Limit + 1 && prev != text; ++i) { - prev = text; - ApplyEachOnce(text, rules); - Y_ENSURE(i != Limit); - } + TString prev; + for (size_t i = 0; i < Limit + 1 && prev != text; ++i) { + prev = text; + ApplyEachOnce(text, rules); + Y_ENSURE(i != Limit); } + } - TRewriteRule RegexRewriteRule(const TString& regex, TString rewrite) { - auto re2 = std::make_shared<RE2>(regex, RE2::Quiet); - Y_ENSURE(re2->ok(), re2->error() << " on regex '" << regex << "'"); - - TString error; - Y_ENSURE( - re2->CheckRewriteString(rewrite, &error), - error << " on rewrite '" << rewrite << "'"); - - return { - .Repr = regex + " -> " + rewrite, - .Apply = [re2, rewrite = std::move(rewrite)](TString& text) { - RE2::GlobalReplace(&text, *re2, rewrite); - }, - }; - } + TRewriteRule RegexRewriteRule(const TString& regex, TString rewrite) { + auto re2 = std::make_shared<RE2>(regex, RE2::Quiet); + Y_ENSURE(re2->ok(), re2->error() << " on regex '" << regex << "'"); + + TString error; + Y_ENSURE( + re2->CheckRewriteString(rewrite, &error), + error << " on rewrite '" << rewrite << "'"); + + return { + .Repr = regex + " -> " + rewrite, + .Apply = [re2, rewrite = std::move(rewrite)](TString& text) { + RE2::GlobalReplace(&text, *re2, rewrite); + }, + }; + } - TRewriteRule UnwrapQuotesRule() { - const TString regex = R"('([^ ][^ ]?)')"; - auto re2 = std::make_shared<RE2>(regex, RE2::Quiet); - Y_ENSURE(re2->ok(), re2->error() << " on regex '" << regex << "'"); - - return { - .Repr = regex + " -> Quoted(\\1)", - .Apply = [re2](TString& text) { - TString content; - std::size_t i = 256; - while (RE2::PartialMatch(text, *re2, &content) && --i != 0) { - TString quoted = RE2::QuoteMeta(content); - for (size_t i = 0; i < 2 && quoted.StartsWith(R"(\\)"); ++i) { - quoted.erase(std::begin(quoted)); - } - SubstGlobal(text, "'" + content + "'", quoted); + TRewriteRule UnwrapQuotesRule() { + const TString regex = R"('([^ ][^ ]?)')"; + auto re2 = std::make_shared<RE2>(regex, RE2::Quiet); + Y_ENSURE(re2->ok(), re2->error() << " on regex '" << regex << "'"); + + return { + .Repr = regex + " -> Quoted(\\1)", + .Apply = [re2](TString& text) { + TString content; + std::size_t i = 256; + while (RE2::PartialMatch(text, *re2, &content) && --i != 0) { + TString quoted = RE2::QuoteMeta(content); + for (size_t i = 0; i < 2 && quoted.StartsWith(R"(\\)"); ++i) { + quoted.erase(std::begin(quoted)); } - Y_ENSURE(i != 0); - }, - }; - } + SubstGlobal(text, "'" + content + "'", quoted); + } + Y_ENSURE(i != 0); + }, + }; + } - TRewriteRule UnwrapQuotedSpaceRule() { - return RegexRewriteRule(R"(' ')", R"( )"); - } + TRewriteRule UnwrapQuotedSpaceRule() { + return RegexRewriteRule(R"(' ')", R"( )"); + } - TString QuoteAntlrRewrite(TString rewrite) { - SubstGlobal(rewrite, R"(\)", R"(\\)"); - SubstGlobal(rewrite, R"('\\')", R"('\\\\')"); - return rewrite; - } + TString QuoteAntlrRewrite(TString rewrite) { + SubstGlobal(rewrite, R"(\)", R"(\\)"); + SubstGlobal(rewrite, R"('\\')", R"('\\\\')"); + return rewrite; + } - const NSQLReflect::TLexerGrammar* Grammar_; - const TStringBuf Mode_; + const NSQLReflect::TLexerGrammar* Grammar_; + const TStringBuf Mode_; - TRewriteRules Inliners_; + TRewriteRules Inliners_; - TRewriteRules Transformations_; + TRewriteRules Transformations_; - TRewriteRule UnwrapQuotes_; - TRewriteRules SpaceCollapses_; - TRewriteRule UnwrapQuotedSpace_; - TRewriteRules RegexOptimizations_; - }; + TRewriteRule UnwrapQuotes_; + TRewriteRules SpaceCollapses_; + TRewriteRule UnwrapQuotedSpace_; + TRewriteRules RegexOptimizations_; +}; - TVector<std::tuple<TString, TString>> MakeRegexByOtherName(const NSQLReflect::TLexerGrammar& grammar, bool ansi) { - TLexerGrammarToRegexTranslator translator(grammar, ansi); +TVector<std::tuple<TString, TString>> MakeRegexByOtherName(const NSQLReflect::TLexerGrammar& grammar, bool ansi) { + TLexerGrammarToRegexTranslator translator(grammar, ansi); - TVector<std::tuple<TString, TString>> regexes; - for (const auto& token : grammar.OtherNames) { - regexes.emplace_back(token, translator.ToRegex(token)); - } - return regexes; + TVector<std::tuple<TString, TString>> regexes; + for (const auto& token : grammar.OtherNames) { + regexes.emplace_back(token, translator.ToRegex(token)); } + return regexes; +} } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/regex/regex.h b/yql/essentials/sql/v1/lexer/regex/regex.h index 1e9d92b6535..943f8c73e42 100644 --- a/yql/essentials/sql/v1/lexer/regex/regex.h +++ b/yql/essentials/sql/v1/lexer/regex/regex.h @@ -6,9 +6,9 @@ namespace NSQLTranslationV1 { - // Makes regexes only for tokens from OtherNames, - // as keywords and punctuation are trivially matched. - TVector<std::tuple<TString, TString>> MakeRegexByOtherName( - const NSQLReflect::TLexerGrammar& grammar, bool ansi); +// Makes regexes only for tokens from OtherNames, +// as keywords and punctuation are trivially matched. +TVector<std::tuple<TString, TString>> MakeRegexByOtherName( + const NSQLReflect::TLexerGrammar& grammar, bool ansi); } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/lexer/regex/regex_ut.cpp b/yql/essentials/sql/v1/lexer/regex/regex_ut.cpp index b8d78799dda..2f05d02d776 100644 --- a/yql/essentials/sql/v1/lexer/regex/regex_ut.cpp +++ b/yql/essentials/sql/v1/lexer/regex/regex_ut.cpp @@ -11,80 +11,80 @@ auto grammar = NSQLReflect::LoadLexerGrammar(); auto defaultRegexes = MakeRegexByOtherName(grammar, /* ansi = */ false); auto ansiRegexes = MakeRegexByOtherName(grammar, /* ansi = */ true); -TString Get(const TVector<std::tuple<TString, TString>> ®exes, +TString Get(const TVector<std::tuple<TString, TString>>& regexes, const TStringBuf name) { - return std::get<1>(*FindIf( - regexes, [&](const auto &pair) { return std::get<0>(pair) == name; })); + return std::get<1>(*FindIf( + regexes, [&](const auto& pair) { return std::get<0>(pair) == name; })); } void CheckRegex(bool ansi, const TStringBuf name, const TStringBuf expected) { - const auto ®exes = ansi ? ansiRegexes : defaultRegexes; - const TString regex = Get(regexes, name); + const auto& regexes = ansi ? ansiRegexes : defaultRegexes; + const TString regex = Get(regexes, name); - const RE2 re2(regex); - Y_ENSURE(re2.ok(), re2.error()); + const RE2 re2(regex); + Y_ENSURE(re2.ok(), re2.error()); - UNIT_ASSERT_VALUES_EQUAL(regex, expected); + UNIT_ASSERT_VALUES_EQUAL(regex, expected); } } // namespace Y_UNIT_TEST_SUITE(SqlRegexTests) { - Y_UNIT_TEST(StringValue) { +Y_UNIT_TEST(StringValue) { CheckRegex( /* ansi = */ false, "STRING_VALUE", R"(((((\'([^'\\]|(\\(.|\n)))*\'))|((\"([^"\\]|(\\(.|\n)))*\"))|((\@\@(.|\n)*?\@\@)+\@?))([sSuUyYjJ]|[pP]([tTbBvV])?)?))"); - } +} - Y_UNIT_TEST(AnsiStringValue) { +Y_UNIT_TEST(AnsiStringValue) { CheckRegex( /* ansi = */ true, "STRING_VALUE", R"(((((\'([^']|(\'\'))*\'))|((\"([^"]|(\"\"))*\"))|((\@\@(.|\n)*?\@\@)+\@?))([sSuUyYjJ]|[pP]([tTbBvV])?)?))"); - } +} - Y_UNIT_TEST(IdPlain) { +Y_UNIT_TEST(IdPlain) { CheckRegex( /* ansi = */ false, "ID_PLAIN", R"(([a-zA-Z_])([a-zA-Z_0-9])*)"); - } +} - Y_UNIT_TEST(IdQuoted) { +Y_UNIT_TEST(IdQuoted) { CheckRegex( /* ansi = */ false, "ID_QUOTED", R"(\`(\\(.|\n)|\`\`|[^`\\])*\`)"); - } +} - Y_UNIT_TEST(Digits) { +Y_UNIT_TEST(Digits) { CheckRegex( /* ansi = */ false, "DIGITS", R"((0[xX]([0-9a-fA-F])+)|(0[oO][0-8]+)|(0[bB](0|1)+)|([0-9]+))"); - } +} - Y_UNIT_TEST(IntegerValue) { +Y_UNIT_TEST(IntegerValue) { CheckRegex( /* ansi = */ false, "INTEGER_VALUE", R"(((0[xX]([0-9a-fA-F])+)|(0[oO][0-8]+)|(0[bB](0|1)+)|([0-9]+))(([pPuU])?([lLsStTiIbBnN])?))"); - } +} - Y_UNIT_TEST(Real) { +Y_UNIT_TEST(Real) { CheckRegex( /* ansi = */ false, "REAL", R"((([0-9]+)\.[0-9]*([eE](\+|\-)?([0-9]+))?|([0-9]+)([eE](\+|\-)?([0-9]+)))([fF]|[pP]([fF](4|8)|[nN])?)?)"); - } +} - Y_UNIT_TEST(Ws) { +Y_UNIT_TEST(Ws) { CheckRegex( /* ansi = */ false, "WS", R"(( |\r|\t|\f|\n))"); - } +} - Y_UNIT_TEST(Comment) { +Y_UNIT_TEST(Comment) { CheckRegex( /* ansi = */ false, "COMMENT", R"(((\/\*(.|\n)*?\*\/)|(\-\-[^\n\r]*(\r\n?|\n|$))))"); - } +} - Y_UNIT_TEST(AnsiCommentSameAsDefault) { +Y_UNIT_TEST(AnsiCommentSameAsDefault) { // Because of recursive definition UNIT_ASSERT_VALUES_EQUAL(Get(ansiRegexes, "COMMENT"), Get(defaultRegexes, "COMMENT")); - } +} } // Y_UNIT_TEST_SUITE(SqlRegexTests) diff --git a/yql/essentials/sql/v1/lexer/ya.make b/yql/essentials/sql/v1/lexer/ya.make index 6462ced1991..d56156f2280 100644 --- a/yql/essentials/sql/v1/lexer/ya.make +++ b/yql/essentials/sql/v1/lexer/ya.make @@ -1,5 +1,7 @@ LIBRARY() +ENABLE(YQL_STYLE_CPP) + PEERDIR( yql/essentials/core/issue/protos yql/essentials/sql/settings diff --git a/yql/essentials/sql/v1/list_builtin.cpp b/yql/essentials/sql/v1/list_builtin.cpp index b1ba690dcde..03c97ccf80f 100644 --- a/yql/essentials/sql/v1/list_builtin.cpp +++ b/yql/essentials/sql/v1/list_builtin.cpp @@ -50,7 +50,7 @@ bool TListExtractBuiltin::DoInit(TContext& ctx, ISource* src) { } bool TListProcessBuiltin::CheckArgs(TContext& ctx, ISource* src) { - if (Args_.size() != 2 ) { + if (Args_.size() != 2) { ctx.Error(Pos_) << OpName_ << " requires exactly two parameters"; return false; } diff --git a/yql/essentials/sql/v1/list_builtin.h b/yql/essentials/sql/v1/list_builtin.h index d4e11e4951c..3fce070a715 100644 --- a/yql/essentials/sql/v1/list_builtin.h +++ b/yql/essentials/sql/v1/list_builtin.h @@ -17,12 +17,13 @@ namespace NSQLTranslationV1 { class TListBuiltin: public TCallNode { public: TListBuiltin(TPosition pos, - const TString& opName, - const TVector<TNodePtr>& args) + const TString& opName, + const TVector<TNodePtr>& args) : TCallNode(pos, opName, args.size(), args.size(), args) , OpName_(opName) , Args_(args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override = 0; @@ -41,7 +42,8 @@ public: TListSortBuiltin(TPosition pos, const TVector<TNodePtr>& args, bool asc) : TListBuiltin(pos, "ListSort", args) , Asc_(asc) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override; @@ -57,7 +59,8 @@ class TListExtractBuiltin final: public TListBuiltin { public: TListExtractBuiltin(TPosition pos, const TVector<TNodePtr>& args) : TListBuiltin(pos, "ListExtract", args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override; @@ -69,10 +72,11 @@ public: class TListProcessBuiltin: public TListBuiltin { protected: TListProcessBuiltin(TPosition pos, - const TString& opName, - const TVector<TNodePtr>& args) + const TString& opName, + const TVector<TNodePtr>& args) : TListBuiltin(pos, opName, args) - {} + { + } bool CheckArgs(TContext& ctx, ISource* src); }; @@ -84,13 +88,15 @@ public: bool flat) : TListProcessBuiltin(pos, flat ? "ListFlatMap" : "ListMap", args) , Flat_(flat) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override; TNodePtr DoClone() const final { return new TListMapBuiltin(Pos_, CloneContainer(Args_), Flat_); } + private: bool Flat_; }; @@ -100,14 +106,15 @@ public: TListFilterBuiltin(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TListProcessBuiltin(pos, opName, args) - {} - + { + } bool DoInit(TContext& ctx, ISource* src) override; TNodePtr DoClone() const final { return new TListFilterBuiltin(Pos_, OpName_, CloneContainer(Args_)); } + protected: virtual TNodePtr GetFilterLambda(); }; @@ -115,9 +122,10 @@ protected: class TListCreateBuiltin final: public TListBuiltin { public: TListCreateBuiltin(TPosition pos, - const TVector<TNodePtr>& args) + const TVector<TNodePtr>& args) : TListBuiltin(pos, "ListCreate", args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override; void DoUpdateState() const override; @@ -130,9 +138,10 @@ public: class TDictCreateBuiltin final: public TListBuiltin { public: TDictCreateBuiltin(TPosition pos, - const TVector<TNodePtr>& args) + const TVector<TNodePtr>& args) : TListBuiltin(pos, "DictCreate", args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override; void DoUpdateState() const override; @@ -145,9 +154,10 @@ public: class TSetCreateBuiltin final: public TListBuiltin { public: TSetCreateBuiltin(TPosition pos, - const TVector<TNodePtr>& args) + const TVector<TNodePtr>& args) : TListBuiltin(pos, "SetCreate", args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override; void DoUpdateState() const override; @@ -160,9 +170,10 @@ public: class TMutDictCreateBuiltin final: public TListBuiltin { public: TMutDictCreateBuiltin(TPosition pos, - const TVector<TNodePtr>& args) + const TVector<TNodePtr>& args) : TListBuiltin(pos, "MutDictCreate", args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override; void DoUpdateState() const override; @@ -175,9 +186,10 @@ public: class TToMutDictBuiltin final: public TListBuiltin { public: TToMutDictBuiltin(TPosition pos, - const TVector<TNodePtr>& args) + const TVector<TNodePtr>& args) : TListBuiltin(pos, "ToMutDict", args) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override; diff --git a/yql/essentials/sql/v1/match_recognize.cpp b/yql/essentials/sql/v1/match_recognize.cpp index ce31d3fc6cf..c70987efd48 100644 --- a/yql/essentials/sql/v1/match_recognize.cpp +++ b/yql/essentials/sql/v1/match_recognize.cpp @@ -12,12 +12,13 @@ constexpr auto VarDataName = "data"; constexpr auto VarMatchedVarsName = "vars"; constexpr auto VarLastRowIndexName = "lri"; -class TMatchRecognizeColumnAccessNode final : public TAstListNode { +class TMatchRecognizeColumnAccessNode final: public TAstListNode { public: TMatchRecognizeColumnAccessNode(TPosition pos, TString var, TString column) - : TAstListNode(pos) - , Var_(std::move(var)) - , Column_(std::move(column)) { + : TAstListNode(pos) + , Var_(std::move(var)) + , Column_(std::move(column)) + { } const TString* GetColumnName() const override { @@ -26,32 +27,31 @@ public: bool DoInit(TContext& ctx, ISource* /* src */) override { switch (ctx.GetColumnReferenceState()) { - case EColumnRefState::MatchRecognizeMeasures: - if (!ctx.SetMatchRecognizeAggrVar(Var_)) { - return false; - } - Add( - "Member", - BuildAtom(Pos_, "row"), - Q(Column_) - ); - break; - case EColumnRefState::MatchRecognizeDefine: - if (ctx.GetMatchRecognizeDefineVar() != Var_) { - ctx.Error() << "Row pattern navigation function is required"; - return false; - } - BuildLookup(VarLastRowIndexName); - break; - case EColumnRefState::MatchRecognizeDefineAggregate: - if (!ctx.SetMatchRecognizeAggrVar(Var_)) { + case EColumnRefState::MatchRecognizeMeasures: + if (!ctx.SetMatchRecognizeAggrVar(Var_)) { + return false; + } + Add( + "Member", + BuildAtom(Pos_, "row"), + Q(Column_)); + break; + case EColumnRefState::MatchRecognizeDefine: + if (ctx.GetMatchRecognizeDefineVar() != Var_) { + ctx.Error() << "Row pattern navigation function is required"; + return false; + } + BuildLookup(VarLastRowIndexName); + break; + case EColumnRefState::MatchRecognizeDefineAggregate: + if (!ctx.SetMatchRecognizeAggrVar(Var_)) { + return false; + } + BuildLookup("index"); + break; + default: + ctx.Error(Pos_) << "Unexpected column reference state"; return false; - } - BuildLookup("index"); - break; - default: - ctx.Error(Pos_) << "Unexpected column reference state"; - return false; } return true; } @@ -68,12 +68,9 @@ private: "Lookup", Y( "ToIndexDict", - BuildAtom(Pos_, VarDataName) - ), - BuildAtom(Pos_, std::move(varKeyName)) - ), - Q(Column_) - ); + BuildAtom(Pos_, VarDataName)), + BuildAtom(Pos_, std::move(varKeyName))), + Q(Column_)); } private: @@ -81,12 +78,13 @@ private: TString Column_; }; -class TMatchRecognizeDefineAggregate final : public TAstListNode { +class TMatchRecognizeDefineAggregate final: public TAstListNode { public: TMatchRecognizeDefineAggregate(TPosition pos, TString name, TVector<TNodePtr> args) - : TAstListNode(pos) - , Name_(std::move(name)) - , Args_(std::move(args)) { + : TAstListNode(pos) + , Name_(std::move(name)) + , Args_(std::move(args)) + { } bool DoInit(TContext& ctx, ISource* src) override { @@ -130,11 +128,12 @@ private: TVector<TNodePtr> Args_; }; -class TMatchRecognizeVarAccessNode final : public INode { +class TMatchRecognizeVarAccessNode final: public INode { public: TMatchRecognizeVarAccessNode(TPosition pos, TNodePtr aggr) - : INode(pos) - , Aggr_(std::move(aggr)) { + : INode(pos) + , Aggr_(std::move(aggr)) + { } bool DoInit(TContext& ctx, ISource* src) override { @@ -144,23 +143,21 @@ public: auto var = ctx.ExtractMatchRecognizeAggrVar(); Expr_ = [&]() -> TNodePtr { switch (ctx.GetColumnReferenceState()) { - case EColumnRefState::MatchRecognizeMeasures: { - ctx.GetMatchRecognizeAggregations().emplace_back(std::move(var), Aggr_->GetAggregation()); - return Aggr_; - } - case EColumnRefState::MatchRecognizeDefine: - return Y( - "Apply", - BuildLambda(Pos_, Y("item"), Aggr_), - Y( - "Member", - BuildAtom(ctx.Pos(), VarMatchedVarsName), - Q(std::move(var)) - ) - ); - default: - ctx.Error(Pos_) << "Unexpected column reference state"; - return {}; + case EColumnRefState::MatchRecognizeMeasures: { + ctx.GetMatchRecognizeAggregations().emplace_back(std::move(var), Aggr_->GetAggregation()); + return Aggr_; + } + case EColumnRefState::MatchRecognizeDefine: + return Y( + "Apply", + BuildLambda(Pos_, Y("item"), Aggr_), + Y( + "Member", + BuildAtom(ctx.Pos(), VarMatchedVarsName), + Q(std::move(var)))); + default: + ctx.Error(Pos_) << "Unexpected column reference state"; + return {}; } }(); return Expr_ && Expr_->Init(ctx, src); @@ -179,7 +176,7 @@ private: TNodePtr Expr_; }; -class TMatchRecognize final : public TAstListNode { +class TMatchRecognize final: public TAstListNode { public: TMatchRecognize( TPosition pos, @@ -194,18 +191,19 @@ public: TNodePtr patternVars, TNodePtr subset, TVector<TNamedFunction> definitions) - : TAstListNode(pos) - , Label_(std::move(label)) - , PartitionKeySelector_(std::move(partitionKeySelector)) - , PartitionColumns_(std::move(partitionColumns)) - , SortSpecs_(std::move(sortSpecs)) - , Measures_(std::move(measures)) - , RowsPerMatch_(std::move(rowsPerMatch)) - , SkipTo_(std::move(skipTo)) - , Pattern_(std::move(pattern)) - , PatternVars_(std::move(patternVars)) - , Subset_(std::move(subset)) - , Definitions_(std::move(definitions)) { + : TAstListNode(pos) + , Label_(std::move(label)) + , PartitionKeySelector_(std::move(partitionKeySelector)) + , PartitionColumns_(std::move(partitionColumns)) + , SortSpecs_(std::move(sortSpecs)) + , Measures_(std::move(measures)) + , RowsPerMatch_(std::move(rowsPerMatch)) + , SkipTo_(std::move(skipTo)) + , Pattern_(std::move(pattern)) + , PatternVars_(std::move(patternVars)) + , Subset_(std::move(subset)) + , Definitions_(std::move(definitions)) + { } private: @@ -226,7 +224,7 @@ private: auto measureNames = Y(); auto measuresCallables = Y(); - for (auto& m: Measures_) { + for (auto& m : Measures_) { TColumnRefScope scope(ctx, EColumnRefState::MatchRecognizeMeasures); if (!m.Callable || !m.Callable->Init(ctx, src)) { return false; @@ -253,9 +251,7 @@ private: "MatchRecognizeMeasuresCallable", BuildLambda(pos, Y("row"), std::move(m.Callable)), Q(measuresVars), - Q(measuresAggregates) - ) - ); + Q(measuresAggregates))); } auto measuresNode = Y("MatchRecognizeMeasuresCallables", inputRowType, Q(PatternVars_), Q(measureNames), Q(measuresCallables)); @@ -276,11 +272,11 @@ private: } auto defineNames = Y(); - for (auto& d: Definitions_) { + for (auto& d : Definitions_) { defineNames = L(defineNames, BuildQuotedAtom(d.Callable->GetPos(), d.Name)); } auto defineNode = Y("MatchRecognizeDefines", inputRowType, Q(PatternVars_), Q(defineNames)); - for (auto& d: Definitions_) { + for (auto& d : Definitions_) { TColumnRefScope scope(ctx, EColumnRefState::MatchRecognizeDefine, true, d.Name); if (!d.Callable || !d.Callable->Init(ctx, src)) { return false; @@ -303,21 +299,17 @@ private: Y("let", "subset", Subset_ ? Subset_ : Q("")), Y("let", "define", defineNode), Y("let", "res", Y("MatchRecognize", - "input", - "partitionKeySelector", - "partitionColumns", - "sortTraits", - Y("MatchRecognizeParams", - "measures", - "rowsPerMatch", - "skipTo", - "pattern", - "define" - ) - )), - Y("return", "res") - )) - ); + "input", + "partitionKeySelector", + "partitionColumns", + "sortTraits", + Y("MatchRecognizeParams", + "measures", + "rowsPerMatch", + "skipTo", + "pattern", + "define"))), + Y("return", "res")))); return true; } @@ -334,8 +326,7 @@ private: Pattern_, PatternVars_, Subset_, - Definitions_ - ); + Definitions_); } private: @@ -367,8 +358,7 @@ TNodePtr TMatchRecognizeBuilder::Build(TContext& ctx, TString label, ISource* sr std::move(Pattern_), std::move(PatternVars_), std::move(Subset_), - std::move(Definitions_) - ); + std::move(Definitions_)); if (!node->Init(ctx, src)) { return {}; } diff --git a/yql/essentials/sql/v1/match_recognize.h b/yql/essentials/sql/v1/match_recognize.h index 5e6f2912e98..984c15ca47a 100644 --- a/yql/essentials/sql/v1/match_recognize.h +++ b/yql/essentials/sql/v1/match_recognize.h @@ -26,18 +26,19 @@ public: TNodePtr patternVars, TNodePtr subset, TVector<TNamedFunction> definitions) - : Pos_(pos) - , PartitionKeySelector_(std::move(partitionKeySelector)) - , PartitionColumns_(std::move(partitionColumns)) - , SortSpecs_(std::move(sortSpecs)) - , Measures_(std::move(measures)) - , RowsPerMatch_(std::move(rowsPerMatch)) - , SkipTo_(std::move(skipTo)) - , Pattern_(std::move(pattern)) - , PatternVars_(std::move(patternVars)) - , Subset_(std::move(subset)) - , Definitions_(std::move(definitions)) - {} + : Pos_(pos) + , PartitionKeySelector_(std::move(partitionKeySelector)) + , PartitionColumns_(std::move(partitionColumns)) + , SortSpecs_(std::move(sortSpecs)) + , Measures_(std::move(measures)) + , RowsPerMatch_(std::move(rowsPerMatch)) + , SkipTo_(std::move(skipTo)) + , Pattern_(std::move(pattern)) + , PatternVars_(std::move(patternVars)) + , Subset_(std::move(subset)) + , Definitions_(std::move(definitions)) + { + } TNodePtr Build(TContext& ctx, TString label, ISource* source); diff --git a/yql/essentials/sql/v1/node.cpp b/yql/essentials/sql/v1/node.cpp index 3fc4836e2aa..748dac521eb 100644 --- a/yql/essentials/sql/v1/node.cpp +++ b/yql/essentials/sql/v1/node.cpp @@ -23,7 +23,8 @@ namespace NSQLTranslationV1 { TString ErrorDistinctWithoutCorrelation(const TString& column) { return TStringBuilder() << "DISTINCT columns for JOIN in SELECT should have table aliases (correlation name)," - " add it if necessary to FROM section over 'AS <alias>' keyword and put it like '<alias>." << column << "'"; + " add it if necessary to FROM section over 'AS <alias>' keyword and put it like '<alias>." + << column << "'"; } TString ErrorDistinctByGroupKey(const TString& column) { @@ -38,7 +39,7 @@ TTopicRef::TTopicRef(const TString& refName, const TDeferredAtom& cluster, TNode } TColumnSchema::TColumnSchema(TPosition pos, const TString& name, const TNodePtr& type, bool nullable, - TVector<TIdentifier> families, bool serial, TNodePtr defaultExpr, ETypeOfChange typeOfChange) + TVector<TIdentifier> families, bool serial, TNodePtr defaultExpr, ETypeOfChange typeOfChange) : Pos(pos) , Name(name) , Type(type) @@ -149,7 +150,7 @@ INode::TPtr INode::ApplyUnaryOp(TContext& ctx, TPosition pos, const TString& opN if (IsNull()) { return BuildLiteralNull(pos); } - return new TCallNodeImpl(pos, opName, { Clone() }); + return new TCallNodeImpl(pos, opName, {Clone()}); } bool INode::IsAsterisk() const { @@ -417,7 +418,7 @@ void INode::PrecacheState() const { /// Not work right now! It's better use Init at first, because some kind of update depend on it /// \todo turn on and remove all issues - //Y_DEBUG_ABORT_UNLESS(State.Test(ENodeState::Initialized)); + // Y_DEBUG_ABORT_UNLESS(State.Test(ENodeState::Initialized)); if (State_.Test(ENodeState::Precached)) { return; } @@ -729,7 +730,7 @@ TAstListNode::~TAstListNode() } bool TAstListNode::DoInit(TContext& ctx, ISource* src) { - for (auto& node: Nodes_) { + for (auto& node : Nodes_) { if (!node->Init(ctx, src)) { return false; } @@ -741,7 +742,7 @@ TAstNode* TAstListNode::Translate(TContext& ctx) const { TSmallVec<TAstNode*> children; children.reserve(Nodes_.size()); auto listPos = Pos_; - for (auto& node: Nodes_) { + for (auto& node : Nodes_) { if (node) { auto astNode = node->Translate(ctx); if (!astNode) { @@ -765,10 +766,10 @@ void TAstListNode::UpdateStateByListNodes(const TVector<TNodePtr>& nodes) const }; std::array<ENodeState, 3> checkStates = {{ENodeState::Aggregated, ENodeState::AggregationKey, ENodeState::OverWindow}}; std::map<ENodeState, TAttributesFlags> flags; - for (auto& node: nodes) { + for (auto& node : nodes) { const bool isNodeConst = node->IsConstant(); const bool isNodeMaybeConst = node->MaybeConstant(); - for (auto state: checkStates) { + for (auto state : checkStates) { if (node->HasState(state)) { flags[state].Has = true; } else if (!isNodeConst && !isNodeMaybeConst) { @@ -781,7 +782,7 @@ void TAstListNode::UpdateStateByListNodes(const TVector<TNodePtr>& nodes) const } } State_.Set(ENodeState::Const, isConst); - for (auto& flag: flags) { + for (auto& flag : flags) { State_.Set(flag.first, flag.second.Has && flag.second.All); } State_.Set(ENodeState::MaybeConst, !isConst && AllOf(nodes, [](const auto& node) { return node->IsConstant() || node->MaybeConstant(); })); @@ -809,7 +810,7 @@ TAstListNode::TAstListNode(TPosition pos, TVector<TNodePtr>&& nodes) : INode(pos) , Nodes_(std::move(nodes)) { - for (const auto& node: Nodes_) { + for (const auto& node : Nodes_) { YQL_ENSURE(node, "Null ptr passed as list element"); } } @@ -826,12 +827,13 @@ void TAstListNode::DoAdd(TNodePtr node) { TAstListNodeImpl::TAstListNodeImpl(TPosition pos) : TAstListNode(pos) -{} +{ +} TAstListNodeImpl::TAstListNodeImpl(TPosition pos, TVector<TNodePtr> nodes) : TAstListNode(pos) { - for (const auto& node: nodes) { + for (const auto& node : nodes) { YQL_ENSURE(node, "Null ptr passed as list element"); } Nodes_.swap(nodes); @@ -854,7 +856,7 @@ TCallNode::TCallNode(TPosition pos, const TString& opName, i32 minArgs, i32 maxA , MaxArgs_(maxArgs) , Args_(args) { - for (const auto& arg: Args_) { + for (const auto& arg : Args_) { YQL_ENSURE(arg, "Null ptr passed as call argument"); } } @@ -863,9 +865,9 @@ TString TCallNode::GetOpName() const { return OpName_; } -const TString* DeriveCommonSourceName(const TVector<TNodePtr> &nodes) { +const TString* DeriveCommonSourceName(const TVector<TNodePtr>& nodes) { const TString* name = nullptr; - for (auto& node: nodes) { + for (auto& node : nodes) { auto n = node->GetSourceName(); if (!n) { continue; @@ -878,7 +880,6 @@ const TString* DeriveCommonSourceName(const TVector<TNodePtr> &nodes) { return name; } - const TString* TCallNode::GetSourceName() const { return DeriveCommonSourceName(Args_); } @@ -933,7 +934,7 @@ bool TCallNode::DoInit(TContext& ctx, ISource* src) { } bool hasError = false; - for (auto& arg: Args_) { + for (auto& arg : Args_) { if (!arg->Init(ctx, src)) { hasError = true; continue; @@ -945,7 +946,7 @@ bool TCallNode::DoInit(TContext& ctx, ISource* src) { } Nodes_.push_back(BuildAtom(Pos_, OpName_, - OpName_.cend() == std::find_if_not(OpName_.cbegin(), OpName_.cend(), [](char c) { return bool(std::isalnum(c)); }) ? TNodeFlags::Default : TNodeFlags::ArbitraryContent)); + OpName_.cend() == std::find_if_not(OpName_.cbegin(), OpName_.cend(), [](char c) { return bool(std::isalnum(c)); }) ? TNodeFlags::Default : TNodeFlags::ArbitraryContent)); Nodes_.insert(Nodes_.end(), Args_.begin(), Args_.end()); return true; } @@ -960,11 +961,13 @@ const TCallNode* TCallNode::GetCallNode() const { TCallNodeImpl::TCallNodeImpl(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args) : TCallNode(pos, opName, minArgs, maxArgs, args) -{} +{ +} TCallNodeImpl::TCallNodeImpl(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TCallNode(pos, opName, args.size(), args.size(), args) -{} +{ +} TCallNode::TPtr TCallNodeImpl::DoClone() const { return new TCallNodeImpl(GetPos(), OpName_, MinArgs_, MaxArgs_, CloneContainer(Args_)); @@ -972,7 +975,8 @@ TCallNode::TPtr TCallNodeImpl::DoClone() const { TFuncNodeImpl::TFuncNodeImpl(TPosition pos, const TString& opName) : TCallNode(pos, opName, 0, 0, {}) -{} +{ +} TCallNode::TPtr TFuncNodeImpl::DoClone() const { return new TFuncNodeImpl(GetPos(), OpName_); @@ -985,12 +989,14 @@ const TString* TFuncNodeImpl::FuncName() const { TCallNodeDepArgs::TCallNodeDepArgs(ui32 reqArgsCount, TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args) : TCallNode(pos, opName, minArgs, maxArgs, args) , ReqArgsCount_(reqArgsCount) -{} +{ +} TCallNodeDepArgs::TCallNodeDepArgs(ui32 reqArgsCount, TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TCallNode(pos, opName, args.size(), args.size(), args) , ReqArgsCount_(reqArgsCount) -{} +{ +} TCallNode::TPtr TCallNodeDepArgs::DoClone() const { return new TCallNodeDepArgs(ReqArgsCount_, GetPos(), OpName_, MinArgs_, MaxArgs_, CloneContainer(Args_)); @@ -1013,11 +1019,13 @@ INode::TPtr TCallDirectRow::DoClone() const { TCallDirectRow::TCallDirectRow(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args) : TCallNode(pos, opName, minArgs, maxArgs, args) -{} +{ +} TCallDirectRow::TCallDirectRow(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) : TCallNode(pos, opName, 0, 0, args) -{} +{ +} bool TCallDirectRow::DoInit(TContext& ctx, ISource* src) { if (!src || (ctx.CompactNamedExprs && src->IsFake())) { @@ -1076,7 +1084,7 @@ bool TWinAggrEmulation::DoInit(TContext& ctx, ISource* src) { INode::TPtr TWinAggrEmulation::WindowSpecFunc(const TPtr& type) const { auto result = Y(OpName_, type); - for (const auto& arg: Args_) { + for (const auto& arg : Args_) { result = L(result, arg); } return Q(Y(Q(FuncAlias_), result)); @@ -1085,15 +1093,18 @@ INode::TPtr TWinAggrEmulation::WindowSpecFunc(const TPtr& type) const { TWinAggrEmulation::TWinAggrEmulation(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args) : TCallNode(pos, opName, minArgs, maxArgs, args) , FuncAlias_(opName) -{} +{ +} TWinRowNumber::TWinRowNumber(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args) : TWinAggrEmulation(pos, opName, minArgs, maxArgs, args) -{} +{ +} TWinCumeDist::TWinCumeDist(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args) : TWinAggrEmulation(pos, opName, minArgs, maxArgs, args) -{} +{ +} bool TWinCumeDist::DoInit(TContext& ctx, ISource* src) { if (!ValidateArguments(ctx)) { @@ -1103,7 +1114,7 @@ bool TWinCumeDist::DoInit(TContext& ctx, ISource* src) { YQL_ENSURE(Args_.size() == 0); TVector<TNodePtr> optionsElements; if (ctx.AnsiCurrentRow) { - optionsElements.push_back(BuildTuple(Pos_, { BuildQuotedAtom(Pos_, "ansi", NYql::TNodeFlags::Default) })); + optionsElements.push_back(BuildTuple(Pos_, {BuildQuotedAtom(Pos_, "ansi", NYql::TNodeFlags::Default)})); } Args_.push_back(BuildTuple(Pos_, optionsElements)); @@ -1135,7 +1146,8 @@ bool TWinNTile::DoInit(TContext& ctx, ISource* src) { TWinLeadLag::TWinLeadLag(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args) : TWinAggrEmulation(pos, opName, minArgs, maxArgs, args) -{} +{ +} bool TWinLeadLag::DoInit(TContext& ctx, ISource* src) { if (Args_.size() >= 2) { @@ -1156,11 +1168,10 @@ bool TWinLeadLag::DoInit(TContext& ctx, ISource* src) { TWinRank::TWinRank(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args) : TWinAggrEmulation(pos, opName, minArgs, maxArgs, args) { - } bool TExternalFunctionConfig::DoInit(TContext& ctx, ISource* src) { - for (auto& param: Config_) { + for (auto& param : Config_) { auto paramName = Y(BuildQuotedAtom(Pos_, param.first)); if (!param.second->Init(ctx, src)) { return false; @@ -1204,21 +1215,21 @@ bool TWinRank::DoInit(TContext& ctx, ISource* src) { if (orderSpec.empty()) { if (Args_.empty()) { if (!ctx.Warning(GetPos(), TIssuesIds::YQL_RANK_WITHOUT_ORDER_BY, [&](auto& out) { - out << OpName_ << "() is used with unordered window - all rows will be considered equal to each other"; - })) { + out << OpName_ << "() is used with unordered window - all rows will be considered equal to each other"; + })) { return false; } } else { if (!ctx.Warning(GetPos(), TIssuesIds::YQL_RANK_WITHOUT_ORDER_BY, [&](auto& out) { - out << OpName_ << "(<expression>) is used with unordered window - the result is likely to be undefined"; - })) { + out << OpName_ << "(<expression>) is used with unordered window - the result is likely to be undefined"; + })) { return false; } } } if (Args_.empty()) { - for (const auto& spec: orderSpec) { + for (const auto& spec : orderSpec) { Args_.push_back(spec->Clone()->OrderExpr); } @@ -1231,9 +1242,9 @@ bool TWinRank::DoInit(TContext& ctx, ISource* src) { TVector<TNodePtr> optionsElements; if (!ctx.AnsiRankForNullableKeys.Defined()) { - optionsElements.push_back(BuildTuple(Pos_, { BuildQuotedAtom(Pos_, "warnNoAnsi", NYql::TNodeFlags::Default) })); + optionsElements.push_back(BuildTuple(Pos_, {BuildQuotedAtom(Pos_, "warnNoAnsi", NYql::TNodeFlags::Default)})); } else if (*ctx.AnsiRankForNullableKeys) { - optionsElements.push_back(BuildTuple(Pos_, { BuildQuotedAtom(Pos_, "ansi", NYql::TNodeFlags::Default) })); + optionsElements.push_back(BuildTuple(Pos_, {BuildQuotedAtom(Pos_, "ansi", NYql::TNodeFlags::Default)})); } Args_.push_back(BuildTuple(Pos_, optionsElements)); @@ -1270,7 +1281,6 @@ TNodePtr BuildQuotedAtom(TPosition pos, const TString& content, ui32 flags) { return new TQuotedAtomNode(pos, content, flags); } - TNodePtr ITableKeys::AddView(TNodePtr key, const TViewDescription& view) { if (view.PrimaryFlag) { return L(key, Q(Y(Q("primary_view")))); @@ -1386,7 +1396,7 @@ bool MaybeAutogenerated(const TString& name) { } bool MatchDotSuffix(const TSet<TString>& columns, const TString& column) { - for (const auto& col: columns) { + for (const auto& col : columns) { const auto pos = col.find_first_of("."); if (pos == TString::npos) { continue; @@ -1398,7 +1408,7 @@ bool MatchDotSuffix(const TSet<TString>& columns, const TString& column) { return false; } -} +} // namespace bool TColumns::IsColumnPossible(TContext& ctx, const TString& name) const { if (All || Real.contains(name) || Artificial.contains(name)) { @@ -1420,7 +1430,7 @@ bool TColumns::IsColumnPossible(TContext& ctx, const TString& name) const { return true; } } - for (const auto& real: Real) { + for (const auto& real : Real) { const auto pos = real.find_first_of("*"); if (pos == TString::npos) { continue; @@ -1479,7 +1489,7 @@ TWindowSpecificationPtr TWindowSpecification::Clone() const { TWinSpecs CloneContainer(const TWinSpecs& specs) { TWinSpecs newSpecs; - for (auto cur: specs) { + for (auto cur : specs) { newSpecs.emplace(cur.first, cur.second->Clone()); } return newSpecs; @@ -1534,7 +1544,7 @@ TColumnNode* TColumnNode::GetColumnNode() { return this; } -const TColumnNode* TColumnNode::GetColumnNode () const { +const TColumnNode* TColumnNode::GetColumnNode() const { return this; } @@ -1735,8 +1745,12 @@ void IAggregation::MarkKeyColumnAsGenerated() { } IAggregation::IAggregation(TPosition pos, const TString& name, const TString& func, EAggregateMode aggMode) - : INode(pos), Name_(name), Func_(func), AggMode_(aggMode) -{} + : INode(pos) + , Name_(name) + , Func_(func) + , AggMode_(aggMode) +{ +} TAstNode* IAggregation::Translate(TContext& ctx) const { Y_DEBUG_ABORT_UNLESS(false); @@ -1749,17 +1763,15 @@ std::pair<TNodePtr, bool> IAggregation::AggregationTraits(const TNodePtr& type, const auto listType = distinct ? Y("ListType", Y("StructMemberType", Y("ListItemType", type), BuildQuotedAtom(Pos_, DistinctKey_))) : type; auto apply = GetApply(listType, many, allowAggApply, ctx); if (!apply) { - return { nullptr, false }; + return {nullptr, false}; } auto wrapped = WrapIfOverState(apply, overState, many, ctx); if (!wrapped) { - return { nullptr, false }; + return {nullptr, false}; } - return { distinct ? - Q(Y(Q(Name_), wrapped, BuildQuotedAtom(Pos_, DistinctKey_))) : - Q(Y(Q(Name_), wrapped)), true }; + return {distinct ? Q(Y(Q(Name_), wrapped, BuildQuotedAtom(Pos_, DistinctKey_))) : Q(Y(Q(Name_), wrapped)), true}; } TNodePtr IAggregation::WrapIfOverState(const TNodePtr& input, bool overState, bool many, TContext& ctx) const { @@ -1829,7 +1841,7 @@ TString UnescapeAnsiQuoted(const TString& str) { return result; } -enum class EStringContentMode : int { +enum class EStringContentMode: int { Default = 0, AnsiIdent, TypedStringLiteral, @@ -1879,8 +1891,8 @@ StringContentInternal(TContext& ctx, TPosition pos, const TString& input, EStrin } else { if (ctx.Scoped->WarnUntypedStringLiterals) { if (!ctx.Warning(pos, TIssuesIds::YQL_UNTYPED_STRING_LITERALS, [](auto& out) { - out << "Please add suffix u for Utf8 strings or s for arbitrary binary strings"; - })) { + out << "Please add suffix u for Utf8 strings or s for arbitrary binary strings"; + })) { return {}; } } @@ -1941,12 +1953,13 @@ TMaybe<TStringContent> StringContent(TContext& ctx, TPosition pos, const TString TMaybe<TStringContent> StringContentOrIdContent(TContext& ctx, TPosition pos, const TString& input) { return StringContentInternal(ctx, pos, input, - (ctx.AnsiQuotedIdentifiers && input.StartsWith('"'))? EStringContentMode::AnsiIdent : EStringContentMode::Default); + (ctx.AnsiQuotedIdentifiers && input.StartsWith('"')) ? EStringContentMode::AnsiIdent : EStringContentMode::Default); } TTtlSettings::TTierSettings::TTierSettings(const TNodePtr& evictionDelay, const std::optional<TIdentifier>& storageName) : EvictionDelay(evictionDelay) - , StorageName(storageName) { + , StorageName(storageName) +{ } TTtlSettings::TTtlSettings(const TIdentifier& columnName, const std::vector<TTierSettings>& tiers, const TMaybe<EUnit>& columnUnit) @@ -2006,7 +2019,6 @@ TString IdContentFromString(TContext& ctx, const TString& str) { return parsed->Content; } - namespace { class TInvalidLiteralNode final: public INode { public: @@ -2031,7 +2043,7 @@ public: } }; -} +} // namespace TLiteralNode::TLiteralNode(TPosition pos, bool isNull) : TAstListNode(pos) @@ -2109,18 +2121,19 @@ TNodePtr TLiteralNode::DoClone() const { return res; } -template<typename T> +template <typename T> TLiteralNumberNode<T>::TLiteralNumberNode(TPosition pos, const TString& type, const TString& value, bool implicitType) : TLiteralNode(pos, type, value) , ImplicitType_(implicitType) -{} +{ +} -template<typename T> +template <typename T> TNodePtr TLiteralNumberNode<T>::DoClone() const { return new TLiteralNumberNode<T>(Pos_, Type_, Value_, ImplicitType_); } -template<typename T> +template <typename T> bool TLiteralNumberNode<T>::DoInit(TContext& ctx, ISource* src) { Y_UNUSED(src); T val; @@ -2131,12 +2144,12 @@ bool TLiteralNumberNode<T>::DoInit(TContext& ctx, ISource* src) { return true; } -template<typename T> +template <typename T> bool TLiteralNumberNode<T>::IsIntegerLiteral() const { return std::numeric_limits<T>::is_integer; } -template<typename T> +template <typename T> TNodePtr TLiteralNumberNode<T>::ApplyUnaryOp(TContext& ctx, TPosition pos, const TString& opName) const { YQL_ENSURE(!Value_.empty()); if (opName == "Minus" && IsIntegerLiteral() && Value_[0] != '-') { @@ -2167,7 +2180,6 @@ TNodePtr TLiteralNumberNode<T>::ApplyUnaryOp(TContext& ctx, TPosition pos, const return INode::ApplyUnaryOp(ctx, pos, opName); } - template class TLiteralNumberNode<i32>; template class TLiteralNumberNode<i64>; template class TLiteralNumberNode<ui32>; @@ -2217,7 +2229,6 @@ TMaybe<TExprOrIdent> BuildLiteralTypedSmartStringOrId(TContext& ctx, const TStri return result; } - TNodePtr BuildLiteralRawString(TPosition pos, const TString& value, bool isUtf8) { return new TLiteralNode(pos, isUtf8 ? "Utf8" : "String", value); } @@ -2227,8 +2238,9 @@ TNodePtr BuildLiteralBool(TPosition pos, bool value) { } TAsteriskNode::TAsteriskNode(TPosition pos) - : INode(pos) -{} + : INode(pos) +{ +} bool TAsteriskNode::IsAsterisk() const { return true; @@ -2251,7 +2263,8 @@ TNodePtr BuildEmptyAction(TPosition pos) { } TDeferredAtom::TDeferredAtom() -{} +{ +} TDeferredAtom::TDeferredAtom(TPosition pos, const TString& str) { @@ -2299,7 +2312,8 @@ bool TDeferredAtom::HasNode() const { TTupleNode::TTupleNode(TPosition pos, const TVector<TNodePtr>& exprs) : TAstListNode(pos) , Exprs_(exprs) -{} +{ +} bool TTupleNode::IsEmpty() const { return Exprs_.empty(); @@ -2319,7 +2333,7 @@ const TTupleNode* TTupleNode::GetTupleNode() const { bool TTupleNode::DoInit(TContext& ctx, ISource* src) { auto node(Y()); - for (auto& expr: Exprs_) { + for (auto& expr : Exprs_) { if (expr->GetLabel()) { ctx.Error(expr->GetPos()) << "Tuple does not allow named members"; return false; @@ -2424,7 +2438,8 @@ TNodePtr BuildOrderedStructure(TPosition pos, const TVector<TNodePtr>& exprsUnla TListOfNamedNodes::TListOfNamedNodes(TPosition pos, TVector<TNodePtr>&& exprs) : INode(pos) , Exprs_(std::move(exprs)) -{} +{ +} TVector<TNodePtr>* TListOfNamedNodes::ContentListPtr() { return &Exprs_; @@ -2450,8 +2465,9 @@ TNodePtr BuildListOfNamedNodes(TPosition pos, TVector<TNodePtr>&& exprs) { return new TListOfNamedNodes(pos, std::move(exprs)); } -TArgPlaceholderNode::TArgPlaceholderNode(TPosition pos, const TString &name) : - INode(pos), +TArgPlaceholderNode::TArgPlaceholderNode(TPosition pos, const TString& name) + : INode(pos) + , Name_(name) { } @@ -2564,7 +2580,7 @@ public: if (!expr->Init(ctx, src)) { return false; } - for (auto& id: Ids_) { + for (auto& id : Ids_) { if (id.Expr && !id.Expr->Init(ctx, src)) { return false; } @@ -2631,7 +2647,7 @@ public: YQL_ENSURE(!Node_, "TAccessNode::Clone: Node should not be initialized"); TVector<TIdPart> cloneIds; cloneIds.reserve(Ids_.size()); - for (const auto& id: Ids_) { + for (const auto& id : Ids_) { cloneIds.emplace_back(id.Clone()); } auto copy = new TAccessNode(Pos_, cloneIds, IsLookup_); @@ -2796,7 +2812,7 @@ bool WarnIfAliasFromSelectIsUsedInGroupBy(TContext& ctx, const TVector<TNodePtr> } bool ValidateAllNodesForAggregation(TContext& ctx, const TVector<TNodePtr>& nodes) { - for (auto& node: nodes) { + for (auto& node : nodes) { if (!node->HasState(ENodeState::Initialized) || node->IsConstant() || node->MaybeConstant()) { continue; } @@ -2846,6 +2862,7 @@ public: { Add("bind", AstNode(module), BuildQuotedAtom(pos, alias)); } + private: TBindNode(const TBindNode& other) : TAstListNode(other.GetPos()) @@ -2962,7 +2979,7 @@ TNodePtr BuildSimpleType(TContext& ctx, TPosition pos, const TString& typeName, bool explicitPgType = ctx.GetColumnReferenceState() == EColumnRefState::AsPgType; auto found = LookupSimpleType(typeName, ctx.FlexibleTypes, explicitPgType); if (!found) { - ctx.Error(pos) << "Unknown " << (explicitPgType ? "pg" : "simple") << " type '" << typeName << "'"; + ctx.Error(pos) << "Unknown " << (explicitPgType ? "pg" : "simple") << " type '" << typeName << "'"; return {}; } @@ -2983,10 +3000,10 @@ TNodePtr BuildSimpleType(TContext& ctx, TPosition pos, const TString& typeName, } else { pgType = type.substr(2); } - return new TCallNodeImpl(pos, "PgType", { BuildQuotedAtom(pos, pgType, TNodeFlags::Default) }); + return new TCallNodeImpl(pos, "PgType", {BuildQuotedAtom(pos, pgType, TNodeFlags::Default)}); } - return new TCallNodeImpl(pos, "DataType", { BuildQuotedAtom(pos, type, TNodeFlags::Default) }); + return new TCallNodeImpl(pos, "DataType", {BuildQuotedAtom(pos, type, TNodeFlags::Default)}); } TString TypeByAlias(const TString& alias, bool normalize) { @@ -3018,8 +3035,6 @@ TNodePtr BuildIsNullOp(TPosition pos, TNodePtr a) { return new TCallNodeImpl(pos, "Not", {new TCallNodeImpl(pos, "Exists", {a})}); } - - TUdfNode::TUdfNode(TPosition pos, const TVector<TNodePtr>& args) : INode(pos) , Args_(args) @@ -3089,7 +3104,7 @@ bool TUdfNode::DoInit(TContext& ctx, ISource* src) { } if (TStructNode* named_args = Args_[1]->GetStructNode(); named_args) { - for (const auto &arg: named_args->GetExprs()) { + for (const auto& arg : named_args->GetExprs()) { if (arg->GetLabel() == "TypeConfig") { if (function->IsScript()) { ctx.Error() << "Udf: TypeConfig is not supported for script udfs"; @@ -3110,10 +3125,10 @@ bool TUdfNode::DoInit(TContext& ctx, ISource* src) { ExtraMem_ = MakeAtomFromExpression(Pos_, ctx, arg); } else if (arg->GetLabel() == "Depends") { if (!IsBackwardCompatibleFeatureAvailable(ctx.Settings.LangVer, - NYql::MakeLangVersion(2025,3), ctx.Settings.BackportMode)) { - ctx.Error() << "Udf: named argument Depends is not available before version 2025.03"; - return false; - } + NYql::MakeLangVersion(2025, 3), ctx.Settings.BackportMode)) { + ctx.Error() << "Udf: named argument Depends is not available before version 2025.03"; + return false; + } Depends_.push_back(arg); } else { ctx.Error() << "Udf: unexpected named argument: " << arg->GetLabel(); @@ -3191,7 +3206,6 @@ TNodePtr TUdfNode::DoClone() const { return new TUdfNode(Pos_, CloneContainer(Args_)); } - class TBinaryOpNode final: public TCallNode { public: TBinaryOpNode(TPosition pos, const TString& opName, TNodePtr a, TNodePtr b); @@ -3203,7 +3217,7 @@ public: }; TBinaryOpNode::TBinaryOpNode(TPosition pos, const TString& opName, TNodePtr a, TNodePtr b) - : TCallNode(pos, opName, 2, 2, { a, b }) + : TCallNode(pos, opName, 2, 2, {a, b}) { } @@ -3214,18 +3228,17 @@ TNodePtr BuildBinaryOp(TContext& ctx, TPosition pos, const TString& opName, TNod static const THashSet<TStringBuf> nullSafeOps = { "IsDistinctFrom", "IsNotDistinctFrom", - "EqualsIgnoreCase", "StartsWithIgnoreCase", "EndsWithIgnoreCase", "StringContainsIgnoreCase" - }; + "EqualsIgnoreCase", "StartsWithIgnoreCase", "EndsWithIgnoreCase", "StringContainsIgnoreCase"}; if (!nullSafeOps.contains(opName)) { const bool bothArgNull = a->IsNull() && b->IsNull(); - const bool oneArgNull = a->IsNull() || b->IsNull(); + const bool oneArgNull = a->IsNull() || b->IsNull(); if (bothArgNull || (oneArgNull && opName != "Or" && opName != "And")) { if (!ctx.Warning(pos, TIssuesIds::YQL_OPERATION_WILL_RETURN_NULL, [&](auto& out) { - out << "Binary operation " - << opName.substr(0, opName.size() - 7 * opName.EndsWith("MayWarn")) - << " will return NULL here"; - })) { + out << "Binary operation " + << opName.substr(0, opName.size() - 7 * opName.EndsWith("MayWarn")) + << " will return NULL here"; + })) { return nullptr; } } @@ -3248,7 +3261,8 @@ public: : INode(pos) , WindowName_(windowName) , FuncNode_(node) - {} + { + } TAstNode* Translate(TContext& ctx) const override { return FuncNode_->Translate(ctx); @@ -3286,6 +3300,7 @@ public: INode::CollectPreaggregateExprs(ctx, src, exprs); } } + protected: const TString WindowName_; TNodePtr FuncNode_; @@ -3295,7 +3310,7 @@ TNodePtr BuildCalcOverWindow(TPosition pos, const TString& windowName, TNodePtr return new TCalcOverWindow(pos, windowName, call); } -template<bool Fast> +template <bool Fast> class TYsonOptionsNode final: public INode { public: TYsonOptionsNode(TPosition pos, bool autoConvert, bool strict) @@ -3308,7 +3323,7 @@ public: autoConvertNode->SetLabel("AutoConvert"); auto strictNode = BuildLiteralBool(pos, strict); strictNode->SetLabel("Strict"); - Node_ = Y("NamedApply", udf, Q(Y()), BuildStructure(pos, { autoConvertNode, strictNode })); + Node_ = Y("NamedApply", udf, Q(Y()), BuildStructure(pos, {autoConvertNode, strictNode})); } TAstNode* Translate(TContext& ctx) const override { @@ -3337,13 +3352,14 @@ protected: }; TNodePtr BuildYsonOptionsNode(TPosition pos, bool autoConvert, bool strict, bool fastYson) { - if (fastYson) + if (fastYson) { return new TYsonOptionsNode<true>(pos, autoConvert, strict); - else + } else { return new TYsonOptionsNode<false>(pos, autoConvert, strict); + } } -class TDoCall final : public INode { +class TDoCall final: public INode { public: TDoCall(TPosition pos, const TNodePtr& node) : INode(pos) @@ -3377,6 +3393,7 @@ public: Y_DEBUG_ABORT_UNLESS(Node_); Node_->VisitTree(func, visited); } + private: TNodePtr Node_; TSourcePtr FakeSource_; @@ -3403,7 +3420,7 @@ TNodePtr GroundWithExpr(const TNodePtr& ground, const TNodePtr& expr) { } TSourcePtr TryMakeSourceFromExpression(TPosition pos, TContext& ctx, const TString& currService, const TDeferredAtom& currCluster, - TNodePtr node, const TString& view) { + TNodePtr node, const TString& view) { if (currCluster.Empty()) { ctx.Error() << "No cluster name given and no default cluster is selected"; return nullptr; @@ -3421,10 +3438,8 @@ TSourcePtr TryMakeSourceFromExpression(TPosition pos, TContext& ctx, const TStri return nullptr; } - auto wrappedNode = new TAstListNodeImpl(pos, { - new TAstAtomNodeImpl(pos, "EvaluateAtom", TNodeFlags::Default), - node - }); + auto wrappedNode = new TAstListNodeImpl(pos, {new TAstAtomNodeImpl(pos, "EvaluateAtom", TNodeFlags::Default), + node}); TNodePtr tableKey = BuildTableKey(node->GetPos(), currService, currCluster, TDeferredAtom(wrappedNode, ctx), {view}); TTableRef table(ctx.MakeName("table"), currService, currCluster, tableKey); @@ -3450,10 +3465,8 @@ void MakeTableFromExpression(TPosition pos, TContext& ctx, TNodePtr node, TDefer node = node->Y("Concat", node->Y("String", node->Q(prefix)), node); } - auto wrappedNode = new TAstListNodeImpl(pos, { - new TAstAtomNodeImpl(pos, "EvaluateAtom", TNodeFlags::Default), - node - }); + auto wrappedNode = new TAstListNodeImpl(pos, {new TAstAtomNodeImpl(pos, "EvaluateAtom", TNodeFlags::Default), + node}); table = TDeferredAtom(wrappedNode, ctx); } @@ -3467,10 +3480,8 @@ TDeferredAtom MakeAtomFromExpression(TPosition pos, TContext& ctx, TNodePtr node node = node->Y("Concat", node->Y("String", node->Q(prefix)), node); } - auto wrappedNode = new TAstListNodeImpl(pos, { - new TAstAtomNodeImpl(pos, "EvaluateAtom", TNodeFlags::Default), - node - }); + auto wrappedNode = new TAstListNodeImpl(pos, {new TAstAtomNodeImpl(pos, "EvaluateAtom", TNodeFlags::Default), + node}); return TDeferredAtom(wrappedNode, ctx); } @@ -3506,6 +3517,7 @@ public: Y_DEBUG_ABORT_UNLESS(Node_); Node_->VisitTree(func, visited); } + protected: TNodePtr Node_; const size_t EnsureTupleSize_; diff --git a/yql/essentials/sql/v1/node.h b/yql/essentials/sql/v1/node.h index fcb0a15955a..54d97262a25 100644 --- a/yql/essentials/sql/v1/node.h +++ b/yql/essentials/sql/v1/node.h @@ -22,1650 +22,1676 @@ #include <variant> namespace NSQLTranslationV1 { - constexpr const size_t SQL_MAX_INLINE_SCRIPT_LEN = 24; - - using NYql::TPosition; - using NYql::TAstNode; - - enum class ENodeState { - Begin, - Precached = Begin, - Initialized, - CountHint, - Const, - MaybeConst, - Aggregated, - AggregationKey, - OverWindow, - OverWindowDistinct, - Failed, - End, - }; - typedef TEnumBitSet<ENodeState, static_cast<int>(ENodeState::Begin), static_cast<int>(ENodeState::End)> TNodeState; - - enum class ESQLWriteColumnMode { - InsertInto, - InsertOrAbortInto, - InsertOrIgnoreInto, - InsertOrRevertInto, - UpsertInto, - ReplaceInto, - InsertIntoWithTruncate, - Update, - Delete, - }; - - enum class EWriteColumnMode { - Default, - Insert, - InsertOrAbort, - InsertOrIgnore, - InsertOrRevert, - Upsert, - Replace, - Renew, - Update, - UpdateOn, - Delete, - DeleteOn, - }; - - enum class EAlterTableIntentnt { - AddColumn, - DropColumn - }; - - enum class ETableType { - Table, - TableStore, - ExternalTable - }; - - class TContext; - class ITableKeys; - class ISource; - class IAggregation; - class TObjectOperatorContext; - typedef TIntrusivePtr<IAggregation> TAggregationPtr; - class TColumnNode; - class TTupleNode; - class TCallNode; - class TStructNode; - class TAccessNode; - class TLambdaNode; - class TUdfNode; - typedef TIntrusivePtr<ISource> TSourcePtr; - - struct TScopedState; - typedef TIntrusivePtr<TScopedState> TScopedStatePtr; - - inline TString DotJoin(const TString& lhs, const TString& rhs) { - TStringBuilder sb; - sb << lhs << "." << rhs; - return sb; - } - - TString ErrorDistinctByGroupKey(const TString& column); - TString ErrorDistinctWithoutCorrelation(const TString& column); - - class INode: public TSimpleRefCount<INode> { - public: - typedef TIntrusivePtr<INode> TPtr; - - struct TIdPart { - TString Name; - TPtr Expr; - - TIdPart(const TString& name) - : Name(name) - { - } - TIdPart(TPtr expr) - : Expr(expr) - { - } - TIdPart Clone() const { - TIdPart res(Name); - res.Expr = Expr ? Expr->Clone() : nullptr; - return res; - } - }; - - public: - INode(TPosition pos); - virtual ~INode(); - - TPosition GetPos() const; - const TString& GetLabel() const; - TMaybe<TPosition> GetLabelPos() const; - void SetLabel(const TString& label, TMaybe<TPosition> pos = {}); - bool IsImplicitLabel() const; - void MarkImplicitLabel(bool isImplicitLabel); - void SetRefPos(TPosition pos); - TMaybe<TPosition> GetRefPos() const; - - void SetCountHint(bool isCount); - bool GetCountHint() const; - bool Init(TContext& ctx, ISource* src); - virtual bool InitReference(TContext& ctx); - - bool IsConstant() const; - bool MaybeConstant() const; - bool IsAggregated() const; - bool IsAggregationKey() const; - bool IsOverWindow() const; - bool IsOverWindowDistinct() const; - bool HasState(ENodeState state) const { - PrecacheState(); - return State_.Test(state); - } - - virtual bool IsNull() const; - virtual bool IsLiteral() const; - virtual TString GetLiteralType() const; - virtual TString GetLiteralValue() const; - virtual bool IsIntegerLiteral() const; - virtual TPtr ApplyUnaryOp(TContext& ctx, TPosition pos, const TString& opName) const; - virtual bool IsAsterisk() const; - virtual const TString* SubqueryAlias() const; - virtual TString GetOpName() const; - virtual const TString* GetLiteral(const TString& type) const; - virtual const TString* GetColumnName() const; - virtual bool IsPlainColumn() const; - virtual bool IsTableRow() const; - virtual void AssumeColumn(); - virtual const TString* GetSourceName() const; - virtual const TString* GetAtomContent() const; - virtual bool IsOptionalArg() const; - virtual size_t GetTupleSize() const; - virtual TPtr GetTupleElement(size_t index) const; - virtual ITableKeys* GetTableKeys(); - virtual ISource* GetSource(); - virtual TVector<INode::TPtr>* ContentListPtr(); - virtual TAstNode* Translate(TContext& ctx) const = 0; - virtual TAggregationPtr GetAggregation() const; - virtual void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs); - virtual TPtr WindowSpecFunc(const TPtr& type) const; - virtual bool SetViewName(TContext& ctx, TPosition pos, const TString& view); - virtual bool SetPrimaryView(TContext& ctx, TPosition pos); - void UseAsInner(); - void DisableSort(); - virtual bool UsedSubquery() const; - virtual bool IsSelect() const; - virtual bool HasSelectResult() const; - virtual const TString* FuncName() const; - virtual const TString* ModuleName() const; - virtual bool IsScript() const; - virtual bool HasSkip() const; - - virtual TColumnNode* GetColumnNode(); - virtual const TColumnNode* GetColumnNode() const; - - virtual TTupleNode* GetTupleNode(); - virtual const TTupleNode* GetTupleNode() const; - - virtual TCallNode* GetCallNode(); - virtual const TCallNode* GetCallNode() const; - - virtual TStructNode* GetStructNode(); - virtual const TStructNode* GetStructNode() const; - - virtual TAccessNode* GetAccessNode(); - virtual const TAccessNode* GetAccessNode() const; - - virtual TLambdaNode* GetLambdaNode(); - virtual const TLambdaNode* GetLambdaNode() const; - - virtual TUdfNode* GetUdfNode(); - virtual const TUdfNode* GetUdfNode() const; - - using TVisitFunc = std::function<bool (const INode&)>; - using TVisitNodeSet = std::unordered_set<const INode*>; - - void VisitTree(const TVisitFunc& func) const; - void VisitTree(const TVisitFunc& func, TVisitNodeSet& visited) const; - - TPtr AstNode() const; - TPtr AstNode(TAstNode* node) const; - TPtr AstNode(TPtr node) const; - TPtr AstNode(const TString& str) const; - - template <typename TVal, typename... TVals> - void Add(TVal val, TVals... vals) { - DoAdd(AstNode(val)); - Add(vals...); - } - - void Add() {} - - // Y() Q() L() - TPtr Y() const { - return AstNode(); - } +constexpr const size_t SQL_MAX_INLINE_SCRIPT_LEN = 24; + +using NYql::TAstNode; +using NYql::TPosition; + +enum class ENodeState { + Begin, + Precached = Begin, + Initialized, + CountHint, + Const, + MaybeConst, + Aggregated, + AggregationKey, + OverWindow, + OverWindowDistinct, + Failed, + End, +}; +typedef TEnumBitSet<ENodeState, static_cast<int>(ENodeState::Begin), static_cast<int>(ENodeState::End)> TNodeState; + +enum class ESQLWriteColumnMode { + InsertInto, + InsertOrAbortInto, + InsertOrIgnoreInto, + InsertOrRevertInto, + UpsertInto, + ReplaceInto, + InsertIntoWithTruncate, + Update, + Delete, +}; + +enum class EWriteColumnMode { + Default, + Insert, + InsertOrAbort, + InsertOrIgnore, + InsertOrRevert, + Upsert, + Replace, + Renew, + Update, + UpdateOn, + Delete, + DeleteOn, +}; + +enum class EAlterTableIntentnt { + AddColumn, + DropColumn +}; + +enum class ETableType { + Table, + TableStore, + ExternalTable +}; + +class TContext; +class ITableKeys; +class ISource; +class IAggregation; +class TObjectOperatorContext; +typedef TIntrusivePtr<IAggregation> TAggregationPtr; +class TColumnNode; +class TTupleNode; +class TCallNode; +class TStructNode; +class TAccessNode; +class TLambdaNode; +class TUdfNode; +typedef TIntrusivePtr<ISource> TSourcePtr; + +struct TScopedState; +typedef TIntrusivePtr<TScopedState> TScopedStatePtr; + +inline TString DotJoin(const TString& lhs, const TString& rhs) { + TStringBuilder sb; + sb << lhs << "." << rhs; + return sb; +} + +TString ErrorDistinctByGroupKey(const TString& column); +TString ErrorDistinctWithoutCorrelation(const TString& column); + +class INode: public TSimpleRefCount<INode> { +public: + typedef TIntrusivePtr<INode> TPtr; + + struct TIdPart { + TString Name; + TPtr Expr; - template <typename... TVals> - TPtr Y(TVals... vals) const { - TPtr node(AstNode()); - node->Add(vals...); - return node; + TIdPart(const TString& name) + : Name(name) + { } - - template <typename T> - TPtr Q(T a) const { - return Y("quote", a); + TIdPart(TPtr expr) + : Expr(expr) + { } - - template <typename... TVals> - TPtr L(TPtr list, TVals... vals) const { - Y_DEBUG_ABORT_UNLESS(list); - auto copy = list->ShallowCopy(); - copy->Add(vals...); - return copy; + TIdPart Clone() const { + TIdPart res(Name); + res.Expr = Expr ? Expr->Clone() : nullptr; + return res; } - - TPtr Clone() const; - protected: - virtual TPtr ShallowCopy() const; - virtual void DoUpdateState() const; - virtual TPtr DoClone() const = 0; - void PrecacheState() const; - - virtual void DoVisitChildren(const TVisitFunc& func, TVisitNodeSet& visited) const; - private: - virtual bool DoInit(TContext& ctx, ISource* src); - virtual void DoAdd(TPtr node); - - protected: - TPosition Pos_; - TString Label_; - TMaybe<TPosition> LabelPos_; - bool ImplicitLabel_ = false; - TMaybe<TPosition> RefPos_; - mutable TNodeState State_; - bool AsInner_ = false; - bool DisableSort_ = false; }; - typedef INode::TPtr TNodePtr; - - class IProxyNode : public INode { - public: - IProxyNode(TPosition pos, const TNodePtr& parent) - : INode(pos) - , Inner_(parent) - {} - - protected: - virtual bool IsNull() const override; - virtual bool IsLiteral() const override; - virtual TString GetLiteralType() const override; - virtual TString GetLiteralValue() const override; - virtual bool IsIntegerLiteral() const override; - virtual TPtr ApplyUnaryOp(TContext& ctx, TPosition pos, const TString& opName) const override; - virtual bool IsAsterisk() const override; - virtual const TString* SubqueryAlias() const override; - virtual TString GetOpName() const override; - virtual const TString* GetLiteral(const TString &type) const override; - virtual const TString* GetColumnName() const override; - virtual bool IsPlainColumn() const override; - virtual bool IsTableRow() const override; - virtual void AssumeColumn() override; - virtual const TString* GetSourceName() const override; - virtual const TString* GetAtomContent() const override; - virtual bool IsOptionalArg() const override; - virtual size_t GetTupleSize() const override; - virtual TPtr GetTupleElement(size_t index) const override; - virtual ITableKeys* GetTableKeys() override; - virtual ISource* GetSource() override; - virtual TVector<INode::TPtr>* ContentListPtr() override; - virtual TAggregationPtr GetAggregation() const override; - virtual void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs) override; - virtual TPtr WindowSpecFunc(const TPtr& type) const override; - virtual bool SetViewName(TContext& ctx, TPosition pos, const TString& view) override; - virtual bool SetPrimaryView(TContext& ctx, TPosition pos) override; - virtual bool UsedSubquery() const override; - virtual bool IsSelect() const override; - virtual bool HasSelectResult() const override; - virtual const TString* FuncName() const override; - virtual const TString* ModuleName() const override; - virtual bool IsScript() const override; - virtual bool HasSkip() const override; - - virtual TColumnNode* GetColumnNode() override; - virtual const TColumnNode* GetColumnNode() const override; - - virtual TTupleNode* GetTupleNode() override; - virtual const TTupleNode* GetTupleNode() const override; - - virtual TCallNode* GetCallNode() override; - virtual const TCallNode* GetCallNode() const override; - - virtual TStructNode* GetStructNode() override; - virtual const TStructNode* GetStructNode() const override; - - virtual TAccessNode* GetAccessNode() override; - virtual const TAccessNode* GetAccessNode() const override; - - virtual TLambdaNode* GetLambdaNode() override; - virtual const TLambdaNode* GetLambdaNode() const override; - - virtual TUdfNode* GetUdfNode() override; - virtual const TUdfNode* GetUdfNode() const override; - - protected: - virtual void DoUpdateState() const override; - virtual void DoVisitChildren(const TVisitFunc& func, TVisitNodeSet& visited) const override; - virtual bool InitReference(TContext& ctx) override; - virtual bool DoInit(TContext& ctx, ISource* src) override; - - private: - virtual void DoAdd(TPtr node) override; - - protected: - const TNodePtr Inner_; - }; - - using TTableHints = TMap<TString, TVector<TNodePtr>>; - void MergeHints(TTableHints& base, const TTableHints& overrides); - template<class T> - inline T SafeClone(const T& node) { - return node ? node->Clone() : nullptr; +public: + INode(TPosition pos); + virtual ~INode(); + + TPosition GetPos() const; + const TString& GetLabel() const; + TMaybe<TPosition> GetLabelPos() const; + void SetLabel(const TString& label, TMaybe<TPosition> pos = {}); + bool IsImplicitLabel() const; + void MarkImplicitLabel(bool isImplicitLabel); + void SetRefPos(TPosition pos); + TMaybe<TPosition> GetRefPos() const; + + void SetCountHint(bool isCount); + bool GetCountHint() const; + bool Init(TContext& ctx, ISource* src); + virtual bool InitReference(TContext& ctx); + + bool IsConstant() const; + bool MaybeConstant() const; + bool IsAggregated() const; + bool IsAggregationKey() const; + bool IsOverWindow() const; + bool IsOverWindowDistinct() const; + bool HasState(ENodeState state) const { + PrecacheState(); + return State_.Test(state); } - template<class T> - inline TVector<T> CloneContainer(const TVector<T>& args) { - TVector<T> cloneArgs; - cloneArgs.reserve(args.size()); - for (const auto& arg: args) { - cloneArgs.emplace_back(SafeClone(arg)); - } - return cloneArgs; + virtual bool IsNull() const; + virtual bool IsLiteral() const; + virtual TString GetLiteralType() const; + virtual TString GetLiteralValue() const; + virtual bool IsIntegerLiteral() const; + virtual TPtr ApplyUnaryOp(TContext& ctx, TPosition pos, const TString& opName) const; + virtual bool IsAsterisk() const; + virtual const TString* SubqueryAlias() const; + virtual TString GetOpName() const; + virtual const TString* GetLiteral(const TString& type) const; + virtual const TString* GetColumnName() const; + virtual bool IsPlainColumn() const; + virtual bool IsTableRow() const; + virtual void AssumeColumn(); + virtual const TString* GetSourceName() const; + virtual const TString* GetAtomContent() const; + virtual bool IsOptionalArg() const; + virtual size_t GetTupleSize() const; + virtual TPtr GetTupleElement(size_t index) const; + virtual ITableKeys* GetTableKeys(); + virtual ISource* GetSource(); + virtual TVector<INode::TPtr>* ContentListPtr(); + virtual TAstNode* Translate(TContext& ctx) const = 0; + virtual TAggregationPtr GetAggregation() const; + virtual void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs); + virtual TPtr WindowSpecFunc(const TPtr& type) const; + virtual bool SetViewName(TContext& ctx, TPosition pos, const TString& view); + virtual bool SetPrimaryView(TContext& ctx, TPosition pos); + void UseAsInner(); + void DisableSort(); + virtual bool UsedSubquery() const; + virtual bool IsSelect() const; + virtual bool HasSelectResult() const; + virtual const TString* FuncName() const; + virtual const TString* ModuleName() const; + virtual bool IsScript() const; + virtual bool HasSkip() const; + + virtual TColumnNode* GetColumnNode(); + virtual const TColumnNode* GetColumnNode() const; + + virtual TTupleNode* GetTupleNode(); + virtual const TTupleNode* GetTupleNode() const; + + virtual TCallNode* GetCallNode(); + virtual const TCallNode* GetCallNode() const; + + virtual TStructNode* GetStructNode(); + virtual const TStructNode* GetStructNode() const; + + virtual TAccessNode* GetAccessNode(); + virtual const TAccessNode* GetAccessNode() const; + + virtual TLambdaNode* GetLambdaNode(); + virtual const TLambdaNode* GetLambdaNode() const; + + virtual TUdfNode* GetUdfNode(); + virtual const TUdfNode* GetUdfNode() const; + + using TVisitFunc = std::function<bool(const INode&)>; + using TVisitNodeSet = std::unordered_set<const INode*>; + + void VisitTree(const TVisitFunc& func) const; + void VisitTree(const TVisitFunc& func, TVisitNodeSet& visited) const; + + TPtr AstNode() const; + TPtr AstNode(TAstNode* node) const; + TPtr AstNode(TPtr node) const; + TPtr AstNode(const TString& str) const; + + template <typename TVal, typename... TVals> + void Add(TVal val, TVals... vals) { + DoAdd(AstNode(val)); + Add(vals...); } - TTableHints CloneContainer(const TTableHints& hints); - - class TAstAtomNode: public INode { - public: - TAstAtomNode(TPosition pos, const TString& content, ui32 flags, bool isOptionalArg); - - ~TAstAtomNode() override; - - TAstNode* Translate(TContext& ctx) const override; - const TString& GetContent() const { - return Content_; - } - - const TString* GetAtomContent() const override; - bool IsOptionalArg() const override; - - protected: - TString Content_; - ui32 Flags_; - bool IsOptionalArg_; - - void DoUpdateState() const override; - }; - - class TAstAtomNodeImpl final: public TAstAtomNode { - public: - TAstAtomNodeImpl(TPosition pos, const TString& content, ui32 flags, bool isOptionalArg = false) - : TAstAtomNode(pos, content, flags, isOptionalArg) - {} - - TNodePtr DoClone() const final { - return new TAstAtomNodeImpl(Pos_, Content_, Flags_, IsOptionalArg_); - } - }; - - class TAstDirectNode final: public INode { - public: - TAstDirectNode(TAstNode* node); - - TAstNode* Translate(TContext& ctx) const override; - - TPtr DoClone() const final { - return new TAstDirectNode(Node_); - } - protected: - TAstNode* Node_; - }; - - class TAstListNode: public INode { - public: - TAstListNode(TPosition pos); - virtual ~TAstListNode(); - - TAstNode* Translate(TContext& ctx) const override; - - protected: - explicit TAstListNode(const TAstListNode& node); - explicit TAstListNode(TPosition pos, TVector<TNodePtr>&& nodes); - TPtr ShallowCopy() const override; - bool DoInit(TContext& ctx, ISource* src) override; - void DoAdd(TNodePtr node) override; - void DoVisitChildren(const TVisitFunc& func, TVisitNodeSet& visited) const override; - - void DoUpdateState() const override; - - void UpdateStateByListNodes(const TVector<TNodePtr>& Nodes) const; - - protected: - TVector<TNodePtr> Nodes_; - mutable TMaybe<bool> CacheGroupKey_; - }; - - class TAstListNodeImpl final: public TAstListNode { - public: - TAstListNodeImpl(TPosition pos); - TAstListNodeImpl(TPosition pos, TVector<TNodePtr> nodes); - void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs) override; - - protected: - TNodePtr DoClone() const final; - }; - - class TCallNode: public TAstListNode { - public: - TCallNode(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - TCallNode(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) - : TCallNode(pos, opName, args.size(), args.size(), args) - {} - - TString GetOpName() const override; - const TString* GetSourceName() const override; - - const TVector<TNodePtr>& GetArgs() const; - TCallNode* GetCallNode() override; - const TCallNode* GetCallNode() const override; - - protected: - bool DoInit(TContext& ctx, ISource* src) override; - bool ValidateArguments(TContext& ctx) const; - TString GetCallExplain() const; - void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs) override; - - protected: - TString OpName_; - i32 MinArgs_; - i32 MaxArgs_; - TVector<TNodePtr> Args_; - mutable TMaybe<bool> CacheGroupKey_; - - void DoUpdateState() const override; - }; - - class TCallNodeImpl final: public TCallNode { - TPtr DoClone() const final; - public: - TCallNodeImpl(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - TCallNodeImpl(TPosition pos, const TString& opName, const TVector<TNodePtr>& args); - }; - - class TFuncNodeImpl final : public TCallNode { - TPtr DoClone() const final; - public: - TFuncNodeImpl(TPosition pos, const TString& opName); - const TString* FuncName() const override; - }; - - class TCallNodeDepArgs final : public TCallNode { - TPtr DoClone() const final; - public: - TCallNodeDepArgs(ui32 reqArgsCount, TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - TCallNodeDepArgs(ui32 reqArgsCount, TPosition pos, const TString& opName, const TVector<TNodePtr>& args); - protected: - bool DoInit(TContext& ctx, ISource* src) override; - - private: - const ui32 ReqArgsCount_; - }; - - class TCallDirectRow final : public TCallNode { - TPtr DoClone() const final; - public: - TCallDirectRow(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - TCallDirectRow(TPosition pos, const TString& opName, const TVector<TNodePtr>& args); - protected: - bool DoInit(TContext& ctx, ISource* src) override; - void DoUpdateState() const override; - }; - - class TWinAggrEmulation: public TCallNode { - protected: - void DoUpdateState() const override; - bool DoInit(TContext& ctx, ISource* src) override; - TPtr WindowSpecFunc(const TNodePtr& type) const override; - public: - TWinAggrEmulation(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - protected: - template<class TNodeType> - TPtr CallNodeClone() const { - return new TNodeType(GetPos(), OpName_, MinArgs_, MaxArgs_, CloneContainer(Args_)); - } - TString FuncAlias_; - }; - - using TFunctionConfig = TMap<TString, TNodePtr>; - - class TExternalFunctionConfig final: public TAstListNode { - public: - TExternalFunctionConfig(TPosition pos, const TFunctionConfig& config) - : TAstListNode(pos) - , Config_(config) - { - } - - bool DoInit(TContext& ctx, ISource* src) override; - TPtr DoClone() const final; - - private: - TFunctionConfig Config_; - }; - - class TWinRowNumber final: public TWinAggrEmulation { - TPtr DoClone() const final { - return CallNodeClone<TWinRowNumber>(); - } - public: - TWinRowNumber(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - }; - - class TWinCumeDist final: public TWinAggrEmulation { - TPtr DoClone() const final { - return CallNodeClone<TWinCumeDist>(); - } - - bool DoInit(TContext& ctx, ISource* src) override; - public: - TWinCumeDist(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - }; - - class TWinNTile final: public TWinAggrEmulation { - TPtr DoClone() const final { - return CallNodeClone<TWinNTile>(); - } - bool DoInit(TContext& ctx, ISource* src) override; - public: - TWinNTile(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - - private: - TSourcePtr FakeSource_; - }; - - class TWinLeadLag final: public TWinAggrEmulation { - TPtr DoClone() const final { - return CallNodeClone<TWinLeadLag>(); - } - bool DoInit(TContext& ctx, ISource* src) override; - public: - TWinLeadLag(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - }; - - class TWinRank final: public TWinAggrEmulation { - TPtr DoClone() const final { - return CallNodeClone<TWinRank>(); - } - bool DoInit(TContext& ctx, ISource* src) override; - public: - TWinRank(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - }; - - struct TViewDescription { - TString ViewName = ""; - bool PrimaryFlag = false; - - bool empty() const { return *this == TViewDescription(); } - bool operator == (const TViewDescription&) const = default; - }; - - class ITableKeys: public INode { - public: - enum class EBuildKeysMode { - CREATE, - DROP, - INPUT, - WRITE - }; - - ITableKeys(TPosition pos); - virtual const TString* GetTableName() const; - virtual TNodePtr BuildKeys(TContext& ctx, EBuildKeysMode mode) = 0; - - protected: - TNodePtr AddView(TNodePtr key, const TViewDescription& view); - - private: - /// all TableKeys no clonnable - TPtr DoClone() const final { - return {}; - } - - ITableKeys* GetTableKeys() override; - TAstNode* Translate(TContext& ctx) const override; - }; - - enum class ESampleClause { - TableSample, //from SQL standard, percantage rate (0..100) - Sample //simplified (implied Bernulli mode), fraction (0..1) - }; - - enum class ESampleMode { - Bernoulli, - System - }; - - class TDeferredAtom { - public: - TDeferredAtom(); - TDeferredAtom(TPosition pos, const TString& str); - TDeferredAtom(TNodePtr node, TContext& ctx); - const TString* GetLiteral() const; - bool GetLiteral(TString& value, TContext& ctx) const; - TNodePtr Build() const; - TString GetRepr() const; - bool Empty() const; - bool HasNode() const; - - private: - TMaybe<TString> Explicit_; - TNodePtr Node_; // atom or evaluation node - TString Repr_; - }; - - struct TTopicRef { - TString RefName; - TDeferredAtom Cluster; - TNodePtr Consumers; - TNodePtr Settings; - TNodePtr Keys; - - TTopicRef() = default; - TTopicRef(const TString& refName, const TDeferredAtom& cluster, TNodePtr keys); - TTopicRef(const TTopicRef&) = default; - TTopicRef& operator=(const TTopicRef&) = default; - }; - - struct TIdentifier { - TPosition Pos; - TString Name; - - TIdentifier(TPosition pos, const TString& name) - : Pos(pos) - , Name(name) {} - }; - - struct TColumnOptions { - TNodePtr DefaultExpr; - bool Nullable = true; - TVector<TIdentifier> Families; - }; - - struct TColumnSchema { - enum class ETypeOfChange { - Nothing, - DropNotNullConstraint, - SetNotNullConstraint, - SetFamily - }; - - TPosition Pos; - TString Name; - TNodePtr Type; - bool Nullable; - TVector<TIdentifier> Families; - bool Serial; - TNodePtr DefaultExpr; - const ETypeOfChange TypeOfChange; - - TColumnSchema(TPosition pos, const TString& name, const TNodePtr& type, bool nullable, - TVector<TIdentifier> families, bool serial, TNodePtr defaultExpr, ETypeOfChange typeOfChange = ETypeOfChange::Nothing); - }; - - struct TColumns: public TSimpleRefCount<TColumns> { - TSet<TString> Real; - TSet<TString> Artificial; - TVector<TString> List; - TVector<bool> NamedColumns; - bool All = false; - bool QualifiedAll = false; - bool HasUnreliable = false; - bool HasUnnamed = false; - - bool Add(const TString* column, bool countHint, bool isArtificial = false, bool isReliable = true); - TString AddUnnamed(); - void Merge(const TColumns& columns); - void SetPrefix(const TString& prefix); - void SetAll(); - bool IsColumnPossible(TContext& ctx, const TString& column) const; - }; - - class TSortSpecification: public TSimpleRefCount<TSortSpecification> { - public: - TSortSpecification(const TNodePtr& orderExpr, bool ascending); - const TNodePtr OrderExpr; - const bool Ascending; - TIntrusivePtr<TSortSpecification> Clone() const; - ~TSortSpecification() {} - private: - const TNodePtr CleanOrderExpr_; - }; - typedef TIntrusivePtr<TSortSpecification> TSortSpecificationPtr; - - enum EFrameType { - FrameByRows, - FrameByRange, - FrameByGroups, - }; - enum EFrameExclusions { - FrameExclNone, // same as EXCLUDE NO OTHERS - FrameExclCurRow, - FrameExclGroup, - FrameExclTies, - }; - enum EFrameSettings { - // keep order - FrameUndefined, - FramePreceding, - FrameCurrentRow, - FrameFollowing, - }; - - struct TFrameBound: public TSimpleRefCount<TFrameBound> { - TPosition Pos; - TNodePtr Bound; - EFrameSettings Settings = FrameUndefined; - - TIntrusivePtr<TFrameBound> Clone() const; - ~TFrameBound() {} - }; - typedef TIntrusivePtr<TFrameBound> TFrameBoundPtr; - - - struct TFrameSpecification: public TSimpleRefCount<TFrameSpecification> { - EFrameType FrameType = FrameByRows; - TFrameBoundPtr FrameBegin; - TFrameBoundPtr FrameEnd; - EFrameExclusions FrameExclusion = FrameExclNone; - - TIntrusivePtr<TFrameSpecification> Clone() const; - ~TFrameSpecification() {} - }; - typedef TIntrusivePtr<TFrameSpecification> TFrameSpecificationPtr; - - struct TLegacyHoppingWindowSpec: public TSimpleRefCount<TLegacyHoppingWindowSpec> { - TNodePtr TimeExtractor; - TNodePtr Hop; - TNodePtr Interval; - TNodePtr Delay; - bool DataWatermarks; - - TIntrusivePtr<TLegacyHoppingWindowSpec> Clone() const; - ~TLegacyHoppingWindowSpec() {} - }; - typedef TIntrusivePtr<TLegacyHoppingWindowSpec> TLegacyHoppingWindowSpecPtr; - - struct TWindowSpecification: public TSimpleRefCount<TWindowSpecification> { - TMaybe<TString> ExistingWindowName; - TVector<TNodePtr> Partitions; - bool IsCompact = false; - TVector<TSortSpecificationPtr> OrderBy; - TNodePtr Session; - TFrameSpecificationPtr Frame; - - TIntrusivePtr<TWindowSpecification> Clone() const; - ~TWindowSpecification() {} - }; - typedef TIntrusivePtr<TWindowSpecification> TWindowSpecificationPtr; - typedef TMap<TString, TWindowSpecificationPtr> TWinSpecs; + void Add() { + } - TWinSpecs CloneContainer(const TWinSpecs& specs); + // Y() Q() L() + TPtr Y() const { + return AstNode(); + } - bool WarnIfAliasFromSelectIsUsedInGroupBy(TContext& ctx, const TVector<TNodePtr>& selectTerms, const TVector<TNodePtr>& groupByTerms, - const TVector<TNodePtr>& groupByExprTerms); - bool ValidateAllNodesForAggregation(TContext& ctx, const TVector<TNodePtr>& nodes); + template <typename... TVals> + TPtr Y(TVals... vals) const { + TPtr node(AstNode()); + node->Add(vals...); + return node; + } - struct TWriteSettings { - bool Discard = false; - TDeferredAtom Label; - }; + template <typename T> + TPtr Q(T a) const { + return Y("quote", a); + } - class TColumnNode final: public INode { - public: - TColumnNode(TPosition pos, const TString& column, const TString& source, bool maybeType); - TColumnNode(TPosition pos, const TNodePtr& column, const TString& source); - - virtual ~TColumnNode(); - bool IsAsterisk() const override; - virtual bool IsArtificial() const; - const TString* GetColumnName() const override; - const TString* GetSourceName() const override; - TColumnNode* GetColumnNode() override; - const TColumnNode* GetColumnNode() const override; - TAstNode* Translate(TContext& ctx) const override; - void ResetColumn(const TString& column, const TString& source); - void ResetColumn(const TNodePtr& column, const TString& source); - - void SetUseSourceAsColumn(); - void SetUseSource(); - void ResetAsReliable(); - void SetAsNotReliable(); - bool IsReliable() const; - bool IsUseSourceAsColumn() const; - bool IsUseSource() const; - bool CanBeType() const; - - private: - bool DoInit(TContext& ctx, ISource* src) override; - TPtr DoClone() const final; - - void DoUpdateState() const override; - - private: - static const TString Empty; - TNodePtr Node_; - TString ColumnName_; - TNodePtr ColumnExpr_; - TString Source_; - bool GroupKey_ = false; - bool Artificial_ = false; - bool Reliable_ = true; - bool UseSource_ = false; - bool UseSourceAsColumn_ = false; - bool MaybeType_ = false; - }; + template <typename... TVals> + TPtr L(TPtr list, TVals... vals) const { + Y_DEBUG_ABORT_UNLESS(list); + auto copy = list->ShallowCopy(); + copy->Add(vals...); + return copy; + } - class TArgPlaceholderNode final: public INode + TPtr Clone() const; + +protected: + virtual TPtr ShallowCopy() const; + virtual void DoUpdateState() const; + virtual TPtr DoClone() const = 0; + void PrecacheState() const; + + virtual void DoVisitChildren(const TVisitFunc& func, TVisitNodeSet& visited) const; + +private: + virtual bool DoInit(TContext& ctx, ISource* src); + virtual void DoAdd(TPtr node); + +protected: + TPosition Pos_; + TString Label_; + TMaybe<TPosition> LabelPos_; + bool ImplicitLabel_ = false; + TMaybe<TPosition> RefPos_; + mutable TNodeState State_; + bool AsInner_ = false; + bool DisableSort_ = false; +}; +typedef INode::TPtr TNodePtr; + +class IProxyNode: public INode { +public: + IProxyNode(TPosition pos, const TNodePtr& parent) + : INode(pos) + , Inner_(parent) { - public: - TArgPlaceholderNode(TPosition pos, const TString &name); - - TAstNode* Translate(TContext& ctx) const override; - - TString GetName() const; - TNodePtr DoClone() const final; - - protected: - bool DoInit(TContext& ctx, ISource* src) override; - - private: - TString Name_; - }; - - enum class EAggregateMode { - Normal, - Distinct, - OverWindow, - OverWindowDistinct, - }; - - class TTupleNode: public TAstListNode { - public: - TTupleNode(TPosition pos, const TVector<TNodePtr>& exprs); - - bool IsEmpty() const; - const TVector<TNodePtr>& Elements() const; - TTupleNode* GetTupleNode() override; - const TTupleNode* GetTupleNode() const override; - bool DoInit(TContext& ctx, ISource* src) override; - size_t GetTupleSize() const override; - TPtr GetTupleElement(size_t index) const override; - TNodePtr DoClone() const final; - private: - void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs) override; - const TString* GetSourceName() const override; - - const TVector<TNodePtr> Exprs_; - }; - - class TStructNode: public TAstListNode { - public: - TStructNode(TPosition pos, const TVector<TNodePtr>& exprs, const TVector<TNodePtr>& labels, bool ordered); - - bool DoInit(TContext& ctx, ISource* src) override; - TNodePtr DoClone() const final; - const TVector<TNodePtr>& GetExprs() { - return Exprs_; - } - TStructNode* GetStructNode() override; - const TStructNode* GetStructNode() const override; - - private: - void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs) override; - const TString* GetSourceName() const override; - - const TVector<TNodePtr> Exprs_; - const TVector<TNodePtr> Labels_; - const bool Ordered_; - }; - - - class TUdfNode: public INode { - public: - TUdfNode(TPosition pos, const TVector<TNodePtr>& args); - bool DoInit(TContext& ctx, ISource* src) override final; - TNodePtr DoClone() const override final; - TAstNode* Translate(TContext& ctx) const override; - const TNodePtr GetExternalTypes() const; - const TString& GetFunction() const; - const TString& GetModule() const; - TNodePtr GetRunConfig() const; - const TDeferredAtom& GetTypeConfig() const; - TUdfNode* GetUdfNode() override; - const TUdfNode* GetUdfNode() const override; - bool IsScript() const override; - const TVector<TNodePtr>& GetScriptArgs() const; - const TVector<TNodePtr>& GetDepends() const; - TNodePtr BuildOptions() const; - private: - TVector<TNodePtr> Args_; - const TString* FunctionName_; - const TString* ModuleName_; - TNodePtr ExternalTypesTuple_ = nullptr; - TNodePtr RunConfig_; - TDeferredAtom TypeConfig_; - TDeferredAtom Cpu_; - TDeferredAtom ExtraMem_; - bool ScriptUdf_ = false; - TVector<TNodePtr> ScriptArgs_; - TVector<TNodePtr> Depends_; - }; + } - class IAggregation: public INode { - public: - bool IsDistinct() const; +protected: + virtual bool IsNull() const override; + virtual bool IsLiteral() const override; + virtual TString GetLiteralType() const override; + virtual TString GetLiteralValue() const override; + virtual bool IsIntegerLiteral() const override; + virtual TPtr ApplyUnaryOp(TContext& ctx, TPosition pos, const TString& opName) const override; + virtual bool IsAsterisk() const override; + virtual const TString* SubqueryAlias() const override; + virtual TString GetOpName() const override; + virtual const TString* GetLiteral(const TString& type) const override; + virtual const TString* GetColumnName() const override; + virtual bool IsPlainColumn() const override; + virtual bool IsTableRow() const override; + virtual void AssumeColumn() override; + virtual const TString* GetSourceName() const override; + virtual const TString* GetAtomContent() const override; + virtual bool IsOptionalArg() const override; + virtual size_t GetTupleSize() const override; + virtual TPtr GetTupleElement(size_t index) const override; + virtual ITableKeys* GetTableKeys() override; + virtual ISource* GetSource() override; + virtual TVector<INode::TPtr>* ContentListPtr() override; + virtual TAggregationPtr GetAggregation() const override; + virtual void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs) override; + virtual TPtr WindowSpecFunc(const TPtr& type) const override; + virtual bool SetViewName(TContext& ctx, TPosition pos, const TString& view) override; + virtual bool SetPrimaryView(TContext& ctx, TPosition pos) override; + virtual bool UsedSubquery() const override; + virtual bool IsSelect() const override; + virtual bool HasSelectResult() const override; + virtual const TString* FuncName() const override; + virtual const TString* ModuleName() const override; + virtual bool IsScript() const override; + virtual bool HasSkip() const override; + + virtual TColumnNode* GetColumnNode() override; + virtual const TColumnNode* GetColumnNode() const override; + + virtual TTupleNode* GetTupleNode() override; + virtual const TTupleNode* GetTupleNode() const override; + + virtual TCallNode* GetCallNode() override; + virtual const TCallNode* GetCallNode() const override; + + virtual TStructNode* GetStructNode() override; + virtual const TStructNode* GetStructNode() const override; + + virtual TAccessNode* GetAccessNode() override; + virtual const TAccessNode* GetAccessNode() const override; + + virtual TLambdaNode* GetLambdaNode() override; + virtual const TLambdaNode* GetLambdaNode() const override; + + virtual TUdfNode* GetUdfNode() override; + virtual const TUdfNode* GetUdfNode() const override; + +protected: + virtual void DoUpdateState() const override; + virtual void DoVisitChildren(const TVisitFunc& func, TVisitNodeSet& visited) const override; + virtual bool InitReference(TContext& ctx) override; + virtual bool DoInit(TContext& ctx, ISource* src) override; + +private: + virtual void DoAdd(TPtr node) override; + +protected: + const TNodePtr Inner_; +}; + +using TTableHints = TMap<TString, TVector<TNodePtr>>; +void MergeHints(TTableHints& base, const TTableHints& overrides); + +template <class T> +inline T SafeClone(const T& node) { + return node ? node->Clone() : nullptr; +} + +template <class T> +inline TVector<T> CloneContainer(const TVector<T>& args) { + TVector<T> cloneArgs; + cloneArgs.reserve(args.size()); + for (const auto& arg : args) { + cloneArgs.emplace_back(SafeClone(arg)); + } + return cloneArgs; +} - void DoUpdateState() const override; +TTableHints CloneContainer(const TTableHints& hints); - virtual TMaybe<TString> GetGenericKey() const; +class TAstAtomNode: public INode { +public: + TAstAtomNode(TPosition pos, const TString& content, ui32 flags, bool isOptionalArg); - virtual bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) = 0; + ~TAstAtomNode() override; - virtual std::pair<TNodePtr, bool> AggregationTraits(const TNodePtr& type, bool overState, bool many, bool allowAggApply, TContext& ctx) const; + TAstNode* Translate(TContext& ctx) const override; + const TString& GetContent() const { + return Content_; + } - virtual TNodePtr AggregationTraitsFactory() const = 0; + const TString* GetAtomContent() const override; + bool IsOptionalArg() const override; - virtual std::vector<ui32> GetFactoryColumnIndices() const; +protected: + TString Content_; + ui32 Flags_; + bool IsOptionalArg_; - virtual void AddFactoryArguments(TNodePtr& apply) const; + void DoUpdateState() const override; +}; - virtual TNodePtr WindowTraits(const TNodePtr& type, TContext& ctx) const; +class TAstAtomNodeImpl final: public TAstAtomNode { +public: + TAstAtomNodeImpl(TPosition pos, const TString& content, ui32 flags, bool isOptionalArg = false) + : TAstAtomNode(pos, content, flags, isOptionalArg) + { + } - const TString& GetName() const; + TNodePtr DoClone() const final { + return new TAstAtomNodeImpl(Pos_, Content_, Flags_, IsOptionalArg_); + } +}; - EAggregateMode GetAggregationMode() const; - void MarkKeyColumnAsGenerated(); +class TAstDirectNode final: public INode { +public: + TAstDirectNode(TAstNode* node); - virtual void Join(IAggregation* aggr); + TAstNode* Translate(TContext& ctx) const override; - private: - virtual TNodePtr GetApply(const TNodePtr& type, bool many, bool allowAggApply, TContext& ctx) const = 0; + TPtr DoClone() const final { + return new TAstDirectNode(Node_); + } - protected: - IAggregation(TPosition pos, const TString& name, const TString& func, EAggregateMode mode); - TAstNode* Translate(TContext& ctx) const override; - TNodePtr WrapIfOverState(const TNodePtr& input, bool overState, bool many, TContext& ctx) const; - virtual TNodePtr GetExtractor(bool many, TContext& ctx) const = 0; +protected: + TAstNode* Node_; +}; + +class TAstListNode: public INode { +public: + TAstListNode(TPosition pos); + virtual ~TAstListNode(); + + TAstNode* Translate(TContext& ctx) const override; + +protected: + explicit TAstListNode(const TAstListNode& node); + explicit TAstListNode(TPosition pos, TVector<TNodePtr>&& nodes); + TPtr ShallowCopy() const override; + bool DoInit(TContext& ctx, ISource* src) override; + void DoAdd(TNodePtr node) override; + void DoVisitChildren(const TVisitFunc& func, TVisitNodeSet& visited) const override; + + void DoUpdateState() const override; + + void UpdateStateByListNodes(const TVector<TNodePtr>& Nodes) const; + +protected: + TVector<TNodePtr> Nodes_; + mutable TMaybe<bool> CacheGroupKey_; +}; + +class TAstListNodeImpl final: public TAstListNode { +public: + TAstListNodeImpl(TPosition pos); + TAstListNodeImpl(TPosition pos, TVector<TNodePtr> nodes); + void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs) override; + +protected: + TNodePtr DoClone() const final; +}; + +class TCallNode: public TAstListNode { +public: + TCallNode(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); + TCallNode(TPosition pos, const TString& opName, const TVector<TNodePtr>& args) + : TCallNode(pos, opName, args.size(), args.size(), args) + { + } - TString Name_; - TString Func_; - const EAggregateMode AggMode_; - TString DistinctKey_; - bool IsGeneratedKeyColumn_ = false; - }; + TString GetOpName() const override; + const TString* GetSourceName() const override; - enum class EExprSeat: int { - Open = 0, - FlattenByExpr, - FlattenBy, - GroupBy, - DistinctAggr, - WindowPartitionBy, - Max - }; + const TVector<TNodePtr>& GetArgs() const; + TCallNode* GetCallNode() override; + const TCallNode* GetCallNode() const override; - enum class EExprType: int { - WithExpression, - ColumnOnly, - }; +protected: + bool DoInit(TContext& ctx, ISource* src) override; + bool ValidateArguments(TContext& ctx) const; + TString GetCallExplain() const; + void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs) override; - enum class EOrderKind: int { - None, - Sort, - Assume, - Passthrough - }; +protected: + TString OpName_; + i32 MinArgs_; + i32 MaxArgs_; + TVector<TNodePtr> Args_; + mutable TMaybe<bool> CacheGroupKey_; - class TListOfNamedNodes final: public INode { - public: - TListOfNamedNodes(TPosition pos, TVector<TNodePtr>&& exprs); - - TVector<TNodePtr>* ContentListPtr() override; - TAstNode* Translate(TContext& ctx) const override; - TPtr DoClone() const final; - void DoVisitChildren(const TVisitFunc& func, TVisitNodeSet& visited) const final; - private: - TVector<TNodePtr> Exprs_; - TString Meaning_; - }; + void DoUpdateState() const override; +}; - class TLiteralNode: public TAstListNode { - public: - TLiteralNode(TPosition pos, bool isNull); - TLiteralNode(TPosition pos, const TString& type, const TString& value); - TLiteralNode(TPosition pos, const TString& value, ui32 nodeFlags); - TLiteralNode(TPosition pos, const TString& value, ui32 nodeFlags, const TString& type); - bool IsNull() const override; - const TString* GetLiteral(const TString& type) const override; - void DoUpdateState() const override; - TPtr DoClone() const override; - bool IsLiteral() const override; - TString GetLiteralType() const override; - TString GetLiteralValue() const override; - protected: - bool Null_; - bool Void_; - TString Type_; - TString Value_; - }; +class TCallNodeImpl final: public TCallNode { + TPtr DoClone() const final; - class TAsteriskNode: public INode { - public: - TAsteriskNode(TPosition pos); - bool IsAsterisk() const override; - TPtr DoClone() const override; - TAstNode* Translate(TContext& ctx) const override; - }; +public: + TCallNodeImpl(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); + TCallNodeImpl(TPosition pos, const TString& opName, const TVector<TNodePtr>& args); +}; - template<typename T> - class TLiteralNumberNode: public TLiteralNode { - public: - TLiteralNumberNode(TPosition pos, const TString& type, const TString& value, bool implicitType = false); - TPtr DoClone() const override final; - bool DoInit(TContext& ctx, ISource* src) override; - bool IsIntegerLiteral() const override; - TPtr ApplyUnaryOp(TContext& ctx, TPosition pos, const TString& opName) const override; - private: - const bool ImplicitType_; - }; +class TFuncNodeImpl final: public TCallNode { + TPtr DoClone() const final; - struct TTableArg { - bool HasAt = false; - TNodePtr Expr; - TDeferredAtom Id; - TViewDescription View; - }; +public: + TFuncNodeImpl(TPosition pos, const TString& opName); + const TString* FuncName() const override; +}; - class TTableRows final : public INode { - public: - TTableRows(TPosition pos, const TVector<TNodePtr>& args); - TTableRows(TPosition pos, ui32 argsCount); +class TCallNodeDepArgs final: public TCallNode { + TPtr DoClone() const final; - bool DoInit(TContext& ctx, ISource* src) override; +public: + TCallNodeDepArgs(ui32 reqArgsCount, TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); + TCallNodeDepArgs(ui32 reqArgsCount, TPosition pos, const TString& opName, const TVector<TNodePtr>& args); - void DoUpdateState() const override; +protected: + bool DoInit(TContext& ctx, ISource* src) override; - TNodePtr DoClone() const final; - TAstNode* Translate(TContext& ctx) const override; +private: + const ui32 ReqArgsCount_; +}; - private: - ui32 ArgsCount_; - TNodePtr Node_; - }; +class TCallDirectRow final: public TCallNode { + TPtr DoClone() const final; - struct TStringContent { - TString Content; - NYql::NUdf::EDataSlot Type = NYql::NUdf::EDataSlot::String; - TMaybe<TString> PgType; - ui32 Flags = NYql::TNodeFlags::Default; - }; +public: + TCallDirectRow(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); + TCallDirectRow(TPosition pos, const TString& opName, const TVector<TNodePtr>& args); - TMaybe<TStringContent> StringContent(TContext& ctx, TPosition pos, const TString& input); - TMaybe<TStringContent> StringContentOrIdContent(TContext& ctx, TPosition pos, const TString& input); +protected: + bool DoInit(TContext& ctx, ISource* src) override; + void DoUpdateState() const override; +}; - struct TTtlSettings { - enum class EUnit { - Seconds /* "seconds" */, - Milliseconds /* "milliseconds" */, - Microseconds /* "microseconds" */, - Nanoseconds /* "nanoseconds" */, - }; +class TWinAggrEmulation: public TCallNode { +protected: + void DoUpdateState() const override; + bool DoInit(TContext& ctx, ISource* src) override; + TPtr WindowSpecFunc(const TNodePtr& type) const override; - struct TTierSettings { - TNodePtr EvictionDelay; - std::optional<TIdentifier> StorageName; +public: + TWinAggrEmulation(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - TTierSettings(const TNodePtr& evictionDelay, const std::optional<TIdentifier>& storageName = std::nullopt); - }; +protected: + template <class TNodeType> + TPtr CallNodeClone() const { + return new TNodeType(GetPos(), OpName_, MinArgs_, MaxArgs_, CloneContainer(Args_)); + } + TString FuncAlias_; +}; - TIdentifier ColumnName; - std::vector<TTierSettings> Tiers; - TMaybe<EUnit> ColumnUnit; +using TFunctionConfig = TMap<TString, TNodePtr>; - TTtlSettings(const TIdentifier& columnName, const std::vector<TTierSettings>& tiers, const TMaybe<EUnit>& columnUnit = {}); - }; +class TExternalFunctionConfig final: public TAstListNode { +public: + TExternalFunctionConfig(TPosition pos, const TFunctionConfig& config) + : TAstListNode(pos) + , Config_(config) + { + } - struct TTableSettings { - TNodePtr CompactionPolicy; - TMaybe<TIdentifier> AutoPartitioningBySize; - TNodePtr PartitionSizeMb; - TMaybe<TIdentifier> AutoPartitioningByLoad; - TNodePtr MinPartitions; - TNodePtr MaxPartitions; - TNodePtr PartitionCount; - TNodePtr UniformPartitions; - TVector<TVector<TNodePtr>> PartitionAtKeys; - TMaybe<TIdentifier> KeyBloomFilter; - TNodePtr ReadReplicasSettings; - NYql::TResetableSetting<TTtlSettings, void> TtlSettings; - NYql::TResetableSetting<TNodePtr, void> Tiering; - TMaybe<TIdentifier> StoreType; - TNodePtr PartitionByHashFunction; - TMaybe<TIdentifier> StoreExternalBlobs; - TNodePtr ExternalDataChannelsCount; - - TNodePtr DataSourcePath; - NYql::TResetableSetting<TNodePtr, void> Location; - TVector<NYql::TResetableSetting<std::pair<TIdentifier, TNodePtr>, TIdentifier>> ExternalSourceParameters; - - bool IsSet() const { - return CompactionPolicy || AutoPartitioningBySize || PartitionSizeMb || AutoPartitioningByLoad - || MinPartitions || MaxPartitions || UniformPartitions || PartitionAtKeys || KeyBloomFilter - || ReadReplicasSettings || TtlSettings || Tiering || StoreType || PartitionByHashFunction - || StoreExternalBlobs || DataSourcePath || Location || ExternalSourceParameters || ExternalDataChannelsCount; - } - }; + bool DoInit(TContext& ctx, ISource* src) override; + TPtr DoClone() const final; - struct TFamilyEntry { - TFamilyEntry(const TIdentifier& name) - :Name(name) - {} +private: + TFunctionConfig Config_; +}; - TIdentifier Name; - TNodePtr Data; - TNodePtr Compression; - TNodePtr CompressionLevel; - TNodePtr CacheMode; - }; +class TWinRowNumber final: public TWinAggrEmulation { + TPtr DoClone() const final { + return CallNodeClone<TWinRowNumber>(); + } - struct TIndexDescription { - enum class EType { - GlobalSync, - GlobalAsync, - GlobalSyncUnique, - GlobalVectorKmeansTree, - GlobalFulltext - }; - - struct TIndexSetting { - TString Name; - TPosition NamePosition; - TString Value; - TPosition ValuePosition; - }; - - TIndexDescription(const TIdentifier& name, EType type = EType::GlobalSync) - : Name(name) - , Type(type) - {} +public: + TWinRowNumber(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); +}; - TIdentifier Name; - EType Type; - TVector<TIdentifier> IndexColumns; - TVector<TIdentifier> DataColumns; - TTableSettings TableSettings; +class TWinCumeDist final: public TWinAggrEmulation { + TPtr DoClone() const final { + return CallNodeClone<TWinCumeDist>(); + } - using TIndexSettings = TMap<TString, TIndexSetting>; - TIndexSettings IndexSettings; - }; + bool DoInit(TContext& ctx, ISource* src) override; - struct TChangefeedSettings { - struct TLocalSinkSettings { - // no special settings - }; - - TNodePtr Mode; - TNodePtr Format; - TNodePtr InitialScan; - TNodePtr VirtualTimestamps; - TNodePtr BarriersInterval; - TNodePtr SchemaChanges; - TNodePtr RetentionPeriod; - TNodePtr TopicAutoPartitioning; - TNodePtr TopicPartitions; - TNodePtr TopicMaxActivePartitions; - TNodePtr AwsRegion; - std::optional<std::variant<TLocalSinkSettings>> SinkSettings; - }; +public: + TWinCumeDist(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); +}; - struct TChangefeedDescription { - TChangefeedDescription(const TIdentifier& name) - : Name(name) - , Disable(false) - {} +class TWinNTile final: public TWinAggrEmulation { + TPtr DoClone() const final { + return CallNodeClone<TWinNTile>(); + } + bool DoInit(TContext& ctx, ISource* src) override; - TIdentifier Name; - TChangefeedSettings Settings; - bool Disable; - }; +public: + TWinNTile(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); - struct TCreateTableParameters { - TVector<TColumnSchema> Columns; - TVector<TIdentifier> PkColumns; - TVector<TIdentifier> PartitionByColumns; - TVector<std::pair<TIdentifier, bool>> OrderByColumns; - TVector<TIndexDescription> Indexes; - TVector<TFamilyEntry> ColumnFamilies; - TVector<TChangefeedDescription> Changefeeds; - TTableSettings TableSettings; - ETableType TableType = ETableType::Table; - bool Temporary = false; - }; +private: + TSourcePtr FakeSource_; +}; - struct TAlterDatabaseParameters { - TDeferredAtom DbPath; - std::optional<TDeferredAtom> Owner; - THashMap<TString, TNodePtr> DatabaseSettings; - }; +class TWinLeadLag final: public TWinAggrEmulation { + TPtr DoClone() const final { + return CallNodeClone<TWinLeadLag>(); + } + bool DoInit(TContext& ctx, ISource* src) override; - struct TTableRef; - struct TAnalyzeParams { - std::shared_ptr<TTableRef> Table; - TVector<TString> Columns; - }; +public: + TWinLeadLag(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); +}; - struct TAlterTableParameters { - TVector<TColumnSchema> AddColumns; - TVector<TString> DropColumns; - TVector<TColumnSchema> AlterColumns; - TVector<TFamilyEntry> AddColumnFamilies; - TVector<TFamilyEntry> AlterColumnFamilies; - TTableSettings TableSettings; - TVector<TIndexDescription> AddIndexes; - TVector<TIndexDescription> AlterIndexes; - TVector<TIdentifier> DropIndexes; - TMaybe<std::pair<TIdentifier, TIdentifier>> RenameIndexTo; - TMaybe<TIdentifier> RenameTo; - TVector<TChangefeedDescription> AddChangefeeds; - TVector<TChangefeedDescription> AlterChangefeeds; - TVector<TIdentifier> DropChangefeeds; - ETableType TableType = ETableType::Table; - - bool IsEmpty() const { - return AddColumns.empty() && DropColumns.empty() && AlterColumns.empty() - && AddColumnFamilies.empty() && AlterColumnFamilies.empty() - && !TableSettings.IsSet() - && AddIndexes.empty() && AlterIndexes.empty() && DropIndexes.empty() && !RenameIndexTo.Defined() - && !RenameTo.Defined() - && AddChangefeeds.empty() && AlterChangefeeds.empty() && DropChangefeeds.empty(); - } - }; +class TWinRank final: public TWinAggrEmulation { + TPtr DoClone() const final { + return CallNodeClone<TWinRank>(); + } + bool DoInit(TContext& ctx, ISource* src) override; - struct TRoleParameters { - protected: - TRoleParameters() {} - public: - TVector<TDeferredAtom> Roles; - }; +public: + TWinRank(TPosition pos, const TString& opName, i32 minArgs, i32 maxArgs, const TVector<TNodePtr>& args); +}; - struct TUserParameters : TRoleParameters { - TMaybe<TDeferredAtom> Password; - bool IsPasswordNull = false; - bool IsPasswordEncrypted = false; - std::optional<bool> CanLogin; - TMaybe<TDeferredAtom> Hash; - }; +struct TViewDescription { + TString ViewName = ""; + bool PrimaryFlag = false; - struct TCreateGroupParameters : TRoleParameters {}; + bool empty() const { + return *this == TViewDescription(); + } + bool operator==(const TViewDescription&) const = default; +}; - struct TSequenceParameters { - bool MissingOk = false; - TMaybe<TDeferredAtom> StartValue; - bool IsRestart = false; - TMaybe<TDeferredAtom> RestartValue; - TMaybe<TDeferredAtom> Increment; +class ITableKeys: public INode { +public: + enum class EBuildKeysMode { + CREATE, + DROP, + INPUT, + WRITE }; - class TSecretParameters { - public: - enum class TOperationMode { - Create, - Alter, - }; + ITableKeys(TPosition pos); + virtual const TString* GetTableName() const; + virtual TNodePtr BuildKeys(TContext& ctx, EBuildKeysMode mode) = 0; - TMaybe<TDeferredAtom> Value; - TMaybe<TDeferredAtom> InheritPermissions; +protected: + TNodePtr AddView(TNodePtr key, const TViewDescription& view); - public: - bool ValidateParameters(TContext& ctx, const TPosition stmBeginPos, const TSecretParameters::TOperationMode mode); - }; +private: + /// all TableKeys no clonnable + TPtr DoClone() const final { + return {}; + } - struct TTopicConsumerSettings { - struct TLocalSinkSettings { - // no special settings - }; + ITableKeys* GetTableKeys() override; + TAstNode* Translate(TContext& ctx) const override; +}; + +enum class ESampleClause { + TableSample, // from SQL standard, percantage rate (0..100) + Sample // simplified (implied Bernulli mode), fraction (0..1) +}; + +enum class ESampleMode { + Bernoulli, + System +}; + +class TDeferredAtom { +public: + TDeferredAtom(); + TDeferredAtom(TPosition pos, const TString& str); + TDeferredAtom(TNodePtr node, TContext& ctx); + const TString* GetLiteral() const; + bool GetLiteral(TString& value, TContext& ctx) const; + TNodePtr Build() const; + TString GetRepr() const; + bool Empty() const; + bool HasNode() const; + +private: + TMaybe<TString> Explicit_; + TNodePtr Node_; // atom or evaluation node + TString Repr_; +}; + +struct TTopicRef { + TString RefName; + TDeferredAtom Cluster; + TNodePtr Consumers; + TNodePtr Settings; + TNodePtr Keys; + + TTopicRef() = default; + TTopicRef(const TString& refName, const TDeferredAtom& cluster, TNodePtr keys); + TTopicRef(const TTopicRef&) = default; + TTopicRef& operator=(const TTopicRef&) = default; +}; + +struct TIdentifier { + TPosition Pos; + TString Name; + + TIdentifier(TPosition pos, const TString& name) + : Pos(pos) + , Name(name) + { + } +}; + +struct TColumnOptions { + TNodePtr DefaultExpr; + bool Nullable = true; + TVector<TIdentifier> Families; +}; + +struct TColumnSchema { + enum class ETypeOfChange { + Nothing, + DropNotNullConstraint, + SetNotNullConstraint, + SetFamily + }; + + TPosition Pos; + TString Name; + TNodePtr Type; + bool Nullable; + TVector<TIdentifier> Families; + bool Serial; + TNodePtr DefaultExpr; + const ETypeOfChange TypeOfChange; + + TColumnSchema(TPosition pos, const TString& name, const TNodePtr& type, bool nullable, + TVector<TIdentifier> families, bool serial, TNodePtr defaultExpr, ETypeOfChange typeOfChange = ETypeOfChange::Nothing); +}; + +struct TColumns: public TSimpleRefCount<TColumns> { + TSet<TString> Real; + TSet<TString> Artificial; + TVector<TString> List; + TVector<bool> NamedColumns; + bool All = false; + bool QualifiedAll = false; + bool HasUnreliable = false; + bool HasUnnamed = false; + + bool Add(const TString* column, bool countHint, bool isArtificial = false, bool isReliable = true); + TString AddUnnamed(); + void Merge(const TColumns& columns); + void SetPrefix(const TString& prefix); + void SetAll(); + bool IsColumnPossible(TContext& ctx, const TString& column) const; +}; + +class TSortSpecification: public TSimpleRefCount<TSortSpecification> { +public: + TSortSpecification(const TNodePtr& orderExpr, bool ascending); + const TNodePtr OrderExpr; + const bool Ascending; + TIntrusivePtr<TSortSpecification> Clone() const; + ~TSortSpecification() { + } - TNodePtr Important; - NYql::TResetableSetting<TNodePtr, void> AvailabilityPeriod; - NYql::TResetableSetting<TNodePtr, void> ReadFromTs; - NYql::TResetableSetting<TNodePtr, void> SupportedCodecs; - }; +private: + const TNodePtr CleanOrderExpr_; +}; +typedef TIntrusivePtr<TSortSpecification> TSortSpecificationPtr; + +enum EFrameType { + FrameByRows, + FrameByRange, + FrameByGroups, +}; +enum EFrameExclusions { + FrameExclNone, // same as EXCLUDE NO OTHERS + FrameExclCurRow, + FrameExclGroup, + FrameExclTies, +}; +enum EFrameSettings { + // keep order + FrameUndefined, + FramePreceding, + FrameCurrentRow, + FrameFollowing, +}; + +struct TFrameBound: public TSimpleRefCount<TFrameBound> { + TPosition Pos; + TNodePtr Bound; + EFrameSettings Settings = FrameUndefined; + + TIntrusivePtr<TFrameBound> Clone() const; + ~TFrameBound() { + } +}; +typedef TIntrusivePtr<TFrameBound> TFrameBoundPtr; - struct TTopicConsumerDescription { - TTopicConsumerDescription(const TIdentifier& name) - : Name(name) - {} +struct TFrameSpecification: public TSimpleRefCount<TFrameSpecification> { + EFrameType FrameType = FrameByRows; + TFrameBoundPtr FrameBegin; + TFrameBoundPtr FrameEnd; + EFrameExclusions FrameExclusion = FrameExclNone; - TIdentifier Name; - TTopicConsumerSettings Settings; - }; - struct TTopicSettings { - NYql::TResetableSetting<TNodePtr, void> MinPartitions; - NYql::TResetableSetting<TNodePtr, void> MaxPartitions; - NYql::TResetableSetting<TNodePtr, void> RetentionPeriod; - NYql::TResetableSetting<TNodePtr, void> RetentionStorage; - NYql::TResetableSetting<TNodePtr, void> SupportedCodecs; - NYql::TResetableSetting<TNodePtr, void> PartitionWriteSpeed; - NYql::TResetableSetting<TNodePtr, void> PartitionWriteBurstSpeed; - NYql::TResetableSetting<TNodePtr, void> MeteringMode; - NYql::TResetableSetting<TNodePtr, void> AutoPartitioningStabilizationWindow; - NYql::TResetableSetting<TNodePtr, void> AutoPartitioningUpUtilizationPercent; - NYql::TResetableSetting<TNodePtr, void> AutoPartitioningDownUtilizationPercent; - NYql::TResetableSetting<TNodePtr, void> AutoPartitioningStrategy; - - bool IsSet() const { - return MinPartitions || - MaxPartitions || - RetentionPeriod || - RetentionStorage || - SupportedCodecs || - PartitionWriteSpeed || - PartitionWriteBurstSpeed || - MeteringMode || - AutoPartitioningStabilizationWindow || - AutoPartitioningUpUtilizationPercent || - AutoPartitioningDownUtilizationPercent || - AutoPartitioningStrategy - ; - } - }; + TIntrusivePtr<TFrameSpecification> Clone() const; + ~TFrameSpecification() { + } +}; +typedef TIntrusivePtr<TFrameSpecification> TFrameSpecificationPtr; + +struct TLegacyHoppingWindowSpec: public TSimpleRefCount<TLegacyHoppingWindowSpec> { + TNodePtr TimeExtractor; + TNodePtr Hop; + TNodePtr Interval; + TNodePtr Delay; + bool DataWatermarks; + + TIntrusivePtr<TLegacyHoppingWindowSpec> Clone() const; + ~TLegacyHoppingWindowSpec() { + } +}; +typedef TIntrusivePtr<TLegacyHoppingWindowSpec> TLegacyHoppingWindowSpecPtr; + +struct TWindowSpecification: public TSimpleRefCount<TWindowSpecification> { + TMaybe<TString> ExistingWindowName; + TVector<TNodePtr> Partitions; + bool IsCompact = false; + TVector<TSortSpecificationPtr> OrderBy; + TNodePtr Session; + TFrameSpecificationPtr Frame; + + TIntrusivePtr<TWindowSpecification> Clone() const; + ~TWindowSpecification() { + } +}; +typedef TIntrusivePtr<TWindowSpecification> TWindowSpecificationPtr; +typedef TMap<TString, TWindowSpecificationPtr> TWinSpecs; + +TWinSpecs CloneContainer(const TWinSpecs& specs); + +bool WarnIfAliasFromSelectIsUsedInGroupBy(TContext& ctx, const TVector<TNodePtr>& selectTerms, const TVector<TNodePtr>& groupByTerms, + const TVector<TNodePtr>& groupByExprTerms); +bool ValidateAllNodesForAggregation(TContext& ctx, const TVector<TNodePtr>& nodes); + +struct TWriteSettings { + bool Discard = false; + TDeferredAtom Label; +}; + +class TColumnNode final: public INode { +public: + TColumnNode(TPosition pos, const TString& column, const TString& source, bool maybeType); + TColumnNode(TPosition pos, const TNodePtr& column, const TString& source); + + virtual ~TColumnNode(); + bool IsAsterisk() const override; + virtual bool IsArtificial() const; + const TString* GetColumnName() const override; + const TString* GetSourceName() const override; + TColumnNode* GetColumnNode() override; + const TColumnNode* GetColumnNode() const override; + TAstNode* Translate(TContext& ctx) const override; + void ResetColumn(const TString& column, const TString& source); + void ResetColumn(const TNodePtr& column, const TString& source); + + void SetUseSourceAsColumn(); + void SetUseSource(); + void ResetAsReliable(); + void SetAsNotReliable(); + bool IsReliable() const; + bool IsUseSourceAsColumn() const; + bool IsUseSource() const; + bool CanBeType() const; + +private: + bool DoInit(TContext& ctx, ISource* src) override; + TPtr DoClone() const final; + + void DoUpdateState() const override; + +private: + static const TString Empty; + TNodePtr Node_; + TString ColumnName_; + TNodePtr ColumnExpr_; + TString Source_; + bool GroupKey_ = false; + bool Artificial_ = false; + bool Reliable_ = true; + bool UseSource_ = false; + bool UseSourceAsColumn_ = false; + bool MaybeType_ = false; +}; + +class TArgPlaceholderNode final: public INode { +public: + TArgPlaceholderNode(TPosition pos, const TString& name); + + TAstNode* Translate(TContext& ctx) const override; + + TString GetName() const; + TNodePtr DoClone() const final; + +protected: + bool DoInit(TContext& ctx, ISource* src) override; + +private: + TString Name_; +}; + +enum class EAggregateMode { + Normal, + Distinct, + OverWindow, + OverWindowDistinct, +}; + +class TTupleNode: public TAstListNode { +public: + TTupleNode(TPosition pos, const TVector<TNodePtr>& exprs); + + bool IsEmpty() const; + const TVector<TNodePtr>& Elements() const; + TTupleNode* GetTupleNode() override; + const TTupleNode* GetTupleNode() const override; + bool DoInit(TContext& ctx, ISource* src) override; + size_t GetTupleSize() const override; + TPtr GetTupleElement(size_t index) const override; + TNodePtr DoClone() const final; + +private: + void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs) override; + const TString* GetSourceName() const override; + + const TVector<TNodePtr> Exprs_; +}; + +class TStructNode: public TAstListNode { +public: + TStructNode(TPosition pos, const TVector<TNodePtr>& exprs, const TVector<TNodePtr>& labels, bool ordered); + + bool DoInit(TContext& ctx, ISource* src) override; + TNodePtr DoClone() const final; + const TVector<TNodePtr>& GetExprs() { + return Exprs_; + } + TStructNode* GetStructNode() override; + const TStructNode* GetStructNode() const override; + +private: + void CollectPreaggregateExprs(TContext& ctx, ISource& src, TVector<INode::TPtr>& exprs) override; + const TString* GetSourceName() const override; + + const TVector<TNodePtr> Exprs_; + const TVector<TNodePtr> Labels_; + const bool Ordered_; +}; + +class TUdfNode: public INode { +public: + TUdfNode(TPosition pos, const TVector<TNodePtr>& args); + bool DoInit(TContext& ctx, ISource* src) override final; + TNodePtr DoClone() const override final; + TAstNode* Translate(TContext& ctx) const override; + const TNodePtr GetExternalTypes() const; + const TString& GetFunction() const; + const TString& GetModule() const; + TNodePtr GetRunConfig() const; + const TDeferredAtom& GetTypeConfig() const; + TUdfNode* GetUdfNode() override; + const TUdfNode* GetUdfNode() const override; + bool IsScript() const override; + const TVector<TNodePtr>& GetScriptArgs() const; + const TVector<TNodePtr>& GetDepends() const; + TNodePtr BuildOptions() const; + +private: + TVector<TNodePtr> Args_; + const TString* FunctionName_; + const TString* ModuleName_; + TNodePtr ExternalTypesTuple_ = nullptr; + TNodePtr RunConfig_; + TDeferredAtom TypeConfig_; + TDeferredAtom Cpu_; + TDeferredAtom ExtraMem_; + bool ScriptUdf_ = false; + TVector<TNodePtr> ScriptArgs_; + TVector<TNodePtr> Depends_; +}; + +class IAggregation: public INode { +public: + bool IsDistinct() const; + + void DoUpdateState() const override; + + virtual TMaybe<TString> GetGenericKey() const; + + virtual bool InitAggr(TContext& ctx, bool isFactory, ISource* src, TAstListNode& node, const TVector<TNodePtr>& exprs) = 0; + + virtual std::pair<TNodePtr, bool> AggregationTraits(const TNodePtr& type, bool overState, bool many, bool allowAggApply, TContext& ctx) const; + + virtual TNodePtr AggregationTraitsFactory() const = 0; + + virtual std::vector<ui32> GetFactoryColumnIndices() const; + + virtual void AddFactoryArguments(TNodePtr& apply) const; + + virtual TNodePtr WindowTraits(const TNodePtr& type, TContext& ctx) const; + + const TString& GetName() const; + + EAggregateMode GetAggregationMode() const; + void MarkKeyColumnAsGenerated(); + + virtual void Join(IAggregation* aggr); + +private: + virtual TNodePtr GetApply(const TNodePtr& type, bool many, bool allowAggApply, TContext& ctx) const = 0; + +protected: + IAggregation(TPosition pos, const TString& name, const TString& func, EAggregateMode mode); + TAstNode* Translate(TContext& ctx) const override; + TNodePtr WrapIfOverState(const TNodePtr& input, bool overState, bool many, TContext& ctx) const; + virtual TNodePtr GetExtractor(bool many, TContext& ctx) const = 0; + + TString Name_; + TString Func_; + const EAggregateMode AggMode_; + TString DistinctKey_; + bool IsGeneratedKeyColumn_ = false; +}; + +enum class EExprSeat: int { + Open = 0, + FlattenByExpr, + FlattenBy, + GroupBy, + DistinctAggr, + WindowPartitionBy, + Max +}; + +enum class EExprType: int { + WithExpression, + ColumnOnly, +}; + +enum class EOrderKind: int { + None, + Sort, + Assume, + Passthrough +}; + +class TListOfNamedNodes final: public INode { +public: + TListOfNamedNodes(TPosition pos, TVector<TNodePtr>&& exprs); + + TVector<TNodePtr>* ContentListPtr() override; + TAstNode* Translate(TContext& ctx) const override; + TPtr DoClone() const final; + void DoVisitChildren(const TVisitFunc& func, TVisitNodeSet& visited) const final; + +private: + TVector<TNodePtr> Exprs_; + TString Meaning_; +}; + +class TLiteralNode: public TAstListNode { +public: + TLiteralNode(TPosition pos, bool isNull); + TLiteralNode(TPosition pos, const TString& type, const TString& value); + TLiteralNode(TPosition pos, const TString& value, ui32 nodeFlags); + TLiteralNode(TPosition pos, const TString& value, ui32 nodeFlags, const TString& type); + bool IsNull() const override; + const TString* GetLiteral(const TString& type) const override; + void DoUpdateState() const override; + TPtr DoClone() const override; + bool IsLiteral() const override; + TString GetLiteralType() const override; + TString GetLiteralValue() const override; + +protected: + bool Null_; + bool Void_; + TString Type_; + TString Value_; +}; + +class TAsteriskNode: public INode { +public: + TAsteriskNode(TPosition pos); + bool IsAsterisk() const override; + TPtr DoClone() const override; + TAstNode* Translate(TContext& ctx) const override; +}; + +template <typename T> +class TLiteralNumberNode: public TLiteralNode { +public: + TLiteralNumberNode(TPosition pos, const TString& type, const TString& value, bool implicitType = false); + TPtr DoClone() const override final; + bool DoInit(TContext& ctx, ISource* src) override; + bool IsIntegerLiteral() const override; + TPtr ApplyUnaryOp(TContext& ctx, TPosition pos, const TString& opName) const override; + +private: + const bool ImplicitType_; +}; + +struct TTableArg { + bool HasAt = false; + TNodePtr Expr; + TDeferredAtom Id; + TViewDescription View; +}; + +class TTableRows final: public INode { +public: + TTableRows(TPosition pos, const TVector<TNodePtr>& args); + TTableRows(TPosition pos, ui32 argsCount); + + bool DoInit(TContext& ctx, ISource* src) override; + + void DoUpdateState() const override; + + TNodePtr DoClone() const final; + TAstNode* Translate(TContext& ctx) const override; + +private: + ui32 ArgsCount_; + TNodePtr Node_; +}; + +struct TStringContent { + TString Content; + NYql::NUdf::EDataSlot Type = NYql::NUdf::EDataSlot::String; + TMaybe<TString> PgType; + ui32 Flags = NYql::TNodeFlags::Default; +}; + +TMaybe<TStringContent> StringContent(TContext& ctx, TPosition pos, const TString& input); +TMaybe<TStringContent> StringContentOrIdContent(TContext& ctx, TPosition pos, const TString& input); + +struct TTtlSettings { + enum class EUnit { + Seconds /* "seconds" */, + Milliseconds /* "milliseconds" */, + Microseconds /* "microseconds" */, + Nanoseconds /* "nanoseconds" */, + }; + + struct TTierSettings { + TNodePtr EvictionDelay; + std::optional<TIdentifier> StorageName; + + TTierSettings(const TNodePtr& evictionDelay, const std::optional<TIdentifier>& storageName = std::nullopt); + }; + + TIdentifier ColumnName; + std::vector<TTierSettings> Tiers; + TMaybe<EUnit> ColumnUnit; + + TTtlSettings(const TIdentifier& columnName, const std::vector<TTierSettings>& tiers, const TMaybe<EUnit>& columnUnit = {}); +}; + +struct TTableSettings { + TNodePtr CompactionPolicy; + TMaybe<TIdentifier> AutoPartitioningBySize; + TNodePtr PartitionSizeMb; + TMaybe<TIdentifier> AutoPartitioningByLoad; + TNodePtr MinPartitions; + TNodePtr MaxPartitions; + TNodePtr PartitionCount; + TNodePtr UniformPartitions; + TVector<TVector<TNodePtr>> PartitionAtKeys; + TMaybe<TIdentifier> KeyBloomFilter; + TNodePtr ReadReplicasSettings; + NYql::TResetableSetting<TTtlSettings, void> TtlSettings; + NYql::TResetableSetting<TNodePtr, void> Tiering; + TMaybe<TIdentifier> StoreType; + TNodePtr PartitionByHashFunction; + TMaybe<TIdentifier> StoreExternalBlobs; + TNodePtr ExternalDataChannelsCount; + + TNodePtr DataSourcePath; + NYql::TResetableSetting<TNodePtr, void> Location; + TVector<NYql::TResetableSetting<std::pair<TIdentifier, TNodePtr>, TIdentifier>> ExternalSourceParameters; + + bool IsSet() const { + return CompactionPolicy || AutoPartitioningBySize || PartitionSizeMb || AutoPartitioningByLoad || MinPartitions || MaxPartitions || UniformPartitions || PartitionAtKeys || KeyBloomFilter || ReadReplicasSettings || TtlSettings || Tiering || StoreType || PartitionByHashFunction || StoreExternalBlobs || DataSourcePath || Location || ExternalSourceParameters || ExternalDataChannelsCount; + } +}; +struct TFamilyEntry { + TFamilyEntry(const TIdentifier& name) + : Name(name) + { + } - struct TCreateTopicParameters { - TVector<TTopicConsumerDescription> Consumers; - TTopicSettings TopicSettings; - bool ExistingOk; - }; + TIdentifier Name; + TNodePtr Data; + TNodePtr Compression; + TNodePtr CompressionLevel; + TNodePtr CacheMode; +}; - struct TAlterTopicParameters { - TVector<TTopicConsumerDescription> AddConsumers; - THashMap<TString, TTopicConsumerDescription> AlterConsumers; - TVector<TIdentifier> DropConsumers; - TTopicSettings TopicSettings; - bool MissingOk; +struct TIndexDescription { + enum class EType { + GlobalSync, + GlobalAsync, + GlobalSyncUnique, + GlobalVectorKmeansTree, + GlobalFulltext }; - struct TDropTopicParameters { - bool MissingOk; + struct TIndexSetting { + TString Name; + TPosition NamePosition; + TString Value; + TPosition ValuePosition; }; - struct TCreateBackupCollectionParameters { - std::map<TString, TDeferredAtom> Settings; + TIndexDescription(const TIdentifier& name, EType type = EType::GlobalSync) + : Name(name) + , Type(type) + { + } - bool Database; - TVector<TDeferredAtom> Tables; + TIdentifier Name; + EType Type; + TVector<TIdentifier> IndexColumns; + TVector<TIdentifier> DataColumns; + TTableSettings TableSettings; + + using TIndexSettings = TMap<TString, TIndexSetting>; + TIndexSettings IndexSettings; +}; + +struct TChangefeedSettings { + struct TLocalSinkSettings { + // no special settings + }; + + TNodePtr Mode; + TNodePtr Format; + TNodePtr InitialScan; + TNodePtr VirtualTimestamps; + TNodePtr BarriersInterval; + TNodePtr SchemaChanges; + TNodePtr RetentionPeriod; + TNodePtr TopicAutoPartitioning; + TNodePtr TopicPartitions; + TNodePtr TopicMaxActivePartitions; + TNodePtr AwsRegion; + std::optional<std::variant<TLocalSinkSettings>> SinkSettings; +}; + +struct TChangefeedDescription { + TChangefeedDescription(const TIdentifier& name) + : Name(name) + , Disable(false) + { + } - bool ExistingOk; - }; + TIdentifier Name; + TChangefeedSettings Settings; + bool Disable; +}; + +struct TCreateTableParameters { + TVector<TColumnSchema> Columns; + TVector<TIdentifier> PkColumns; + TVector<TIdentifier> PartitionByColumns; + TVector<std::pair<TIdentifier, bool>> OrderByColumns; + TVector<TIndexDescription> Indexes; + TVector<TFamilyEntry> ColumnFamilies; + TVector<TChangefeedDescription> Changefeeds; + TTableSettings TableSettings; + ETableType TableType = ETableType::Table; + bool Temporary = false; +}; + +struct TAlterDatabaseParameters { + TDeferredAtom DbPath; + std::optional<TDeferredAtom> Owner; + THashMap<TString, TNodePtr> DatabaseSettings; +}; + +struct TTableRef; +struct TAnalyzeParams { + std::shared_ptr<TTableRef> Table; + TVector<TString> Columns; +}; + +struct TAlterTableParameters { + TVector<TColumnSchema> AddColumns; + TVector<TString> DropColumns; + TVector<TColumnSchema> AlterColumns; + TVector<TFamilyEntry> AddColumnFamilies; + TVector<TFamilyEntry> AlterColumnFamilies; + TTableSettings TableSettings; + TVector<TIndexDescription> AddIndexes; + TVector<TIndexDescription> AlterIndexes; + TVector<TIdentifier> DropIndexes; + TMaybe<std::pair<TIdentifier, TIdentifier>> RenameIndexTo; + TMaybe<TIdentifier> RenameTo; + TVector<TChangefeedDescription> AddChangefeeds; + TVector<TChangefeedDescription> AlterChangefeeds; + TVector<TIdentifier> DropChangefeeds; + ETableType TableType = ETableType::Table; + + bool IsEmpty() const { + return AddColumns.empty() && DropColumns.empty() && AlterColumns.empty() && AddColumnFamilies.empty() && AlterColumnFamilies.empty() && !TableSettings.IsSet() && AddIndexes.empty() && AlterIndexes.empty() && DropIndexes.empty() && !RenameIndexTo.Defined() && !RenameTo.Defined() && AddChangefeeds.empty() && AlterChangefeeds.empty() && DropChangefeeds.empty(); + } +}; - struct TAlterBackupCollectionParameters { - enum class EDatabase { - Unchanged, - Add, - Drop, - }; +struct TRoleParameters { +protected: + TRoleParameters() { + } - std::map<TString, TDeferredAtom> Settings; - std::set<TString> SettingsToReset; +public: + TVector<TDeferredAtom> Roles; +}; - EDatabase Database = EDatabase::Unchanged; - TVector<TDeferredAtom> TablesToAdd; - TVector<TDeferredAtom> TablesToDrop; +struct TUserParameters: TRoleParameters { + TMaybe<TDeferredAtom> Password; + bool IsPasswordNull = false; + bool IsPasswordEncrypted = false; + std::optional<bool> CanLogin; + TMaybe<TDeferredAtom> Hash; +}; - bool MissingOk; - }; +struct TCreateGroupParameters: TRoleParameters {}; - struct TDropBackupCollectionParameters { - bool MissingOk; - }; +struct TSequenceParameters { + bool MissingOk = false; + TMaybe<TDeferredAtom> StartValue; + bool IsRestart = false; + TMaybe<TDeferredAtom> RestartValue; + TMaybe<TDeferredAtom> Increment; +}; - struct TBackupParameters { - bool Incremental = false; +class TSecretParameters { +public: + enum class TOperationMode { + Create, + Alter, }; - struct TRestoreParameters { - TString At; - }; + TMaybe<TDeferredAtom> Value; + TMaybe<TDeferredAtom> InheritPermissions; - struct TStreamingQuerySettings { - inline static constexpr char RESERVED_FEATURE_PREFIX[] = "__"; - inline static constexpr char QUERY_TEXT_FEATURE[] = "__query_text"; - inline static constexpr char QUERY_AST_FEATURE[] = "__query_ast"; +public: + bool ValidateParameters(TContext& ctx, const TPosition stmBeginPos, const TSecretParameters::TOperationMode mode); +}; - std::map<TString, TDeferredAtom> Features; +struct TTopicConsumerSettings { + struct TLocalSinkSettings { + // no special settings }; - TString IdContent(TContext& ctx, const TString& str); - TString IdContentFromString(TContext& ctx, const TString& str); - TTableHints GetContextHints(TContext& ctx); + TNodePtr Important; + NYql::TResetableSetting<TNodePtr, void> AvailabilityPeriod; + NYql::TResetableSetting<TNodePtr, void> ReadFromTs; + NYql::TResetableSetting<TNodePtr, void> SupportedCodecs; +}; - TString TypeByAlias(const TString& alias, bool normalize = true); +struct TTopicConsumerDescription { + TTopicConsumerDescription(const TIdentifier& name) + : Name(name) + { + } - TNodePtr BuildList(TPosition pos, TVector<TNodePtr> nodes = {}); - TNodePtr BuildQuote(TPosition pos, TNodePtr expr); - TNodePtr BuildAtom(TPosition pos, const TString& content, ui32 flags = NYql::TNodeFlags::ArbitraryContent, - bool isOptionalArg = false); - TNodePtr BuildQuotedAtom(TPosition pos, const TString& content, ui32 flags = NYql::TNodeFlags::ArbitraryContent); + TIdentifier Name; + TTopicConsumerSettings Settings; +}; +struct TTopicSettings { + NYql::TResetableSetting<TNodePtr, void> MinPartitions; + NYql::TResetableSetting<TNodePtr, void> MaxPartitions; + NYql::TResetableSetting<TNodePtr, void> RetentionPeriod; + NYql::TResetableSetting<TNodePtr, void> RetentionStorage; + NYql::TResetableSetting<TNodePtr, void> SupportedCodecs; + NYql::TResetableSetting<TNodePtr, void> PartitionWriteSpeed; + NYql::TResetableSetting<TNodePtr, void> PartitionWriteBurstSpeed; + NYql::TResetableSetting<TNodePtr, void> MeteringMode; + NYql::TResetableSetting<TNodePtr, void> AutoPartitioningStabilizationWindow; + NYql::TResetableSetting<TNodePtr, void> AutoPartitioningUpUtilizationPercent; + NYql::TResetableSetting<TNodePtr, void> AutoPartitioningDownUtilizationPercent; + NYql::TResetableSetting<TNodePtr, void> AutoPartitioningStrategy; + + bool IsSet() const { + return MinPartitions || + MaxPartitions || + RetentionPeriod || + RetentionStorage || + SupportedCodecs || + PartitionWriteSpeed || + PartitionWriteBurstSpeed || + MeteringMode || + AutoPartitioningStabilizationWindow || + AutoPartitioningUpUtilizationPercent || + AutoPartitioningDownUtilizationPercent || + AutoPartitioningStrategy; + } +}; - TNodePtr BuildLiteralNull(TPosition pos); - TNodePtr BuildLiteralVoid(TPosition pos); - /// String is checked as quotable, support escaping and multiline - TNodePtr BuildLiteralSmartString(TContext& ctx, const TString& value); +struct TCreateTopicParameters { + TVector<TTopicConsumerDescription> Consumers; + TTopicSettings TopicSettings; + bool ExistingOk; +}; - struct TExprOrIdent { - TNodePtr Expr; - TString Ident; - }; - TMaybe<TExprOrIdent> BuildLiteralTypedSmartStringOrId(TContext& ctx, const TString& value); - - TNodePtr BuildLiteralRawString(TPosition pos, const TString& value, bool isUtf8 = false); - TNodePtr BuildLiteralBool(TPosition pos, bool value); - TNodePtr BuildEmptyAction(TPosition pos); - - TNodePtr BuildTuple(TPosition pos, const TVector<TNodePtr>& exprs); - - TNodePtr BuildStructure(TPosition pos, const TVector<TNodePtr>& exprs); - TNodePtr BuildStructure(TPosition pos, const TVector<TNodePtr>& exprsUnlabeled, const TVector<TNodePtr>& labels); - TNodePtr BuildOrderedStructure(TPosition pos, const TVector<TNodePtr>& exprsUnlabeled, const TVector<TNodePtr>& labels); - - TNodePtr BuildListOfNamedNodes(TPosition pos, TVector<TNodePtr>&& exprs); - - TNodePtr BuildArgPlaceholder(TPosition pos, const TString& name); - - TNodePtr BuildColumn(TPosition pos, const TString& column = TString(), const TString& source = TString()); - TNodePtr BuildColumn(TPosition pos, const TNodePtr& column, const TString& source = TString()); - TNodePtr BuildColumn(TPosition pos, const TDeferredAtom& column, const TString& source = TString()); - TNodePtr BuildColumnOrType(TPosition pos, const TString& column = TString()); - TNodePtr BuildAccess(TPosition pos, const TVector<INode::TIdPart>& ids, bool isLookup); - TNodePtr BuildBind(TPosition pos, const TString& module, const TString& alias); - TNodePtr BuildLambda(TPosition pos, TNodePtr params, TNodePtr body, const TString& resName = TString()); - TNodePtr BuildLambda(TPosition pos, TNodePtr params, const TVector<TNodePtr>& bodies); - TNodePtr BuildDataType(TPosition pos, const TString& typeName); - TMaybe<TString> LookupSimpleType(const TStringBuf& alias, bool flexibleTypes, bool isPgType); - TNodePtr BuildSimpleType(TContext& ctx, TPosition pos, const TString& typeName, bool dataOnly); - TNodePtr BuildIsNullOp(TPosition pos, TNodePtr a); - TNodePtr BuildBinaryOp(TContext& ctx, TPosition pos, const TString& opName, TNodePtr a, TNodePtr b); - TNodePtr BuildBinaryOpRaw(TPosition pos, const TString& opName, TNodePtr a, TNodePtr b); - - TNodePtr BuildCalcOverWindow(TPosition pos, const TString& windowName, TNodePtr call); - TNodePtr BuildYsonOptionsNode(TPosition pos, bool autoConvert, bool strict, bool fastYson); - - TNodePtr BuildDoCall(TPosition pos, const TNodePtr& node); - TNodePtr BuildTupleResult(TNodePtr tuple, size_t ensureTupleSize); - TNodePtr BuildNamedExprReference(TNodePtr parent, const TString& name, TMaybe<size_t> tupleIndex); - TNodePtr BuildNamedExpr(TNodePtr parent); - - // Implemented in aggregation.cpp - TAggregationPtr BuildFactoryAggregation(TPosition pos, const TString& name, const TString& func, EAggregateMode aggMode, bool multi = false); - TAggregationPtr BuildKeyPayloadFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - TAggregationPtr BuildPayloadPredicateFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - TAggregationPtr BuildTwoArgsFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - TAggregationPtr BuildHistogramFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - TAggregationPtr BuildLinearHistogramFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - template <bool HasKey> - TAggregationPtr BuildTopFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - TAggregationPtr BuildTopFreqFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - TAggregationPtr BuildCountDistinctEstimateFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - TAggregationPtr BuildListFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - TAggregationPtr BuildPercentileFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - TAggregationPtr BuildCountAggregation(TPosition pos, const TString& name, const TString& func, EAggregateMode aggMode); - TAggregationPtr BuildUserDefinedFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - TAggregationPtr BuildPGFactoryAggregation(TPosition pos, const TString& name, EAggregateMode aggMode); - TAggregationPtr BuildNthFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); - - - // Implemented in builtin.cpp - TNodePtr BuildSqlCall(TContext& ctx, TPosition pos, const TString& module, const TString& name, const TVector<TNodePtr>& args, - TNodePtr positionalArgs, TNodePtr namedArgs, TNodePtr externalTypes, const TDeferredAtom& typeConfig, TNodePtr runConfig, - TNodePtr options, const TVector<TNodePtr>& depends); - TNodePtr BuildScriptUdf(TPosition pos, const TString& moduleName, const TString& funcName, const TVector<TNodePtr>& args, - TNodePtr options); - - TNodePtr BuildCallable(TPosition pos, const TString& module, const TString& name, const TVector<TNodePtr>& args, bool forReduce = false); - TNodePtr BuildUdf(TContext& ctx, TPosition pos, const TString& module, const TString& name, const TVector<TNodePtr>& args); - TNodePtr BuildBuiltinFunc( - TContext& ctx, - TPosition pos, - TString name, - const TVector<TNodePtr>& args, - const TString& nameSpace = TString(), - EAggregateMode aggMode = EAggregateMode::Normal, - bool* mustUseNamed = nullptr, - bool warnOnYqlNameSpace = true - ); - - // Implemented in query.cpp - TNodePtr BuildCreateGroup(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TMaybe<TCreateGroupParameters>& params, TScopedStatePtr scoped); - TNodePtr BuildControlUser(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, - const TMaybe<TUserParameters>& params, TScopedStatePtr scoped, bool isCreateUser); - TNodePtr BuildRenameUser(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TDeferredAtom& newName, TScopedStatePtr scoped); - TNodePtr BuildAlterGroup(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TVector<TDeferredAtom>& toChange, bool isDrop, - TScopedStatePtr scoped); - TNodePtr BuildRenameGroup(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TDeferredAtom& newName, TScopedStatePtr scoped); - TNodePtr BuildDropRoles(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TVector<TDeferredAtom>& toDrop, bool isUser, bool missingOk, TScopedStatePtr scoped); - TNodePtr BuildGrantPermissions(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TVector<TDeferredAtom>& permissions, const TVector<TDeferredAtom>& schemaPaths, const TVector<TDeferredAtom>& roleName, TScopedStatePtr scoped); - TNodePtr BuildRevokePermissions(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TVector<TDeferredAtom>& permissions, const TVector<TDeferredAtom>& schemaPaths, const TVector<TDeferredAtom>& roleName, TScopedStatePtr scoped); - TNodePtr BuildUpsertObjectOperation(TPosition pos, const TString& objectId, const TString& typeId, - std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context); - TNodePtr BuildCreateObjectOperation(TPosition pos, const TString& objectId, const TString& typeId, - bool existingOk, bool replaceIfExists, std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context); - TNodePtr BuildAlterObjectOperation(TPosition pos, const TString& secretId, const TString& typeId, - bool missingOk, std::map<TString, TDeferredAtom>&& features, std::set<TString>&& featuresToReset, const TObjectOperatorContext& context); - TNodePtr BuildDropObjectOperation(TPosition pos, const TString& secretId, const TString& typeId, - bool missingOk, std::map<TString, TDeferredAtom>&& options, const TObjectOperatorContext& context); - TNodePtr BuildCreateAsyncReplication(TPosition pos, const TString& id, - std::vector<std::pair<TString, TString>>&& targets, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context); - TNodePtr BuildAlterAsyncReplication(TPosition pos, const TString& id, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context); - TNodePtr BuildDropAsyncReplication(TPosition pos, const TString& id, bool cascade, const TObjectOperatorContext& context); - TNodePtr BuildCreateTransfer(TPosition pos, const TString& id, const TString&& source, const TString&& target, - const TString&& transformLambda, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context); - TNodePtr BuildAlterTransfer(TPosition pos, const TString& id, std::optional<TString>&& transformLambda, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context); - TNodePtr BuildDropTransfer(TPosition pos, const TString& id, bool cascade, const TObjectOperatorContext& context); - TNodePtr BuildWriteResult(TPosition pos, const TString& label, TNodePtr settings); - TNodePtr BuildCommitClusters(TPosition pos); - TNodePtr BuildRollbackClusters(TPosition pos); - TNodePtr BuildQuery(TPosition pos, const TVector<TNodePtr>& blocks, bool topLevel, TScopedStatePtr scoped, bool useSeq); - TNodePtr BuildPragma(TPosition pos, const TString& prefix, const TString& name, const TVector<TDeferredAtom>& values, bool valueDefault); - TNodePtr BuildSqlLambda(TPosition pos, TVector<TString>&& args, TVector<TNodePtr>&& exprSeq); - TNodePtr BuildWorldIfNode(TPosition pos, TNodePtr predicate, TNodePtr thenNode, TNodePtr elseNode, bool isEvaluate); - TNodePtr BuildWorldForNode(TPosition pos, TNodePtr list, TNodePtr bodyNode, TNodePtr elseNode, bool isEvaluate, bool isParallel); - - TNodePtr BuildCreateTopic(TPosition pos, const TTopicRef& tr, const TCreateTopicParameters& params, - TScopedStatePtr scoped); - TNodePtr BuildAlterTopic(TPosition pos, const TTopicRef& tr, const TAlterTopicParameters& params, - TScopedStatePtr scoped); - TNodePtr BuildDropTopic(TPosition pos, const TTopicRef& topic, const TDropTopicParameters& params, - TScopedStatePtr scoped); - - TNodePtr BuildCreateBackupCollection( - TPosition pos, - const TString& prefix, - const TString& id, - const TCreateBackupCollectionParameters& params, - const TObjectOperatorContext& context); - TNodePtr BuildAlterBackupCollection( - TPosition pos, - const TString& prefix, - const TString& id, - const TAlterBackupCollectionParameters& params, - const TObjectOperatorContext& context); - TNodePtr BuildDropBackupCollection( - TPosition pos, - const TString& prefix, - const TString& id, - const TDropBackupCollectionParameters& params, - const TObjectOperatorContext& context); - - TNodePtr BuildBackup( - TPosition pos, - const TString& prefix, - const TString& id, - const TBackupParameters& params, - const TObjectOperatorContext& context); - TNodePtr BuildRestore( - TPosition pos, - const TString& prefix, - const TString& id, - const TRestoreParameters& params, - const TObjectOperatorContext& context); - - TNodePtr BuildCreateSecret( - TPosition pos, - const TString& objectId, - const TSecretParameters& secretParams, - const TObjectOperatorContext& context, - TScopedStatePtr scoped); - TNodePtr BuildAlterSecret( - TPosition pos, - const TString& objectId, - const TSecretParameters& secretParams, - const TObjectOperatorContext& context, - TScopedStatePtr scoped); - TNodePtr BuildDropSecret( - TPosition pos, - const TString& objectId, - const TObjectOperatorContext& context, - TScopedStatePtr scoped); - - template<class TContainer> - TMaybe<TString> FindMistypeIn(const TContainer& container, const TString& name) { - for (auto& item: container) { - if (NLevenshtein::Distance(name, item) < NYql::DefaultMistypeDistance) { - return item; - } +struct TAlterTopicParameters { + TVector<TTopicConsumerDescription> AddConsumers; + THashMap<TString, TTopicConsumerDescription> AlterConsumers; + TVector<TIdentifier> DropConsumers; + TTopicSettings TopicSettings; + bool MissingOk; +}; + +struct TDropTopicParameters { + bool MissingOk; +}; + +struct TCreateBackupCollectionParameters { + std::map<TString, TDeferredAtom> Settings; + + bool Database; + TVector<TDeferredAtom> Tables; + + bool ExistingOk; +}; + +struct TAlterBackupCollectionParameters { + enum class EDatabase { + Unchanged, + Add, + Drop, + }; + + std::map<TString, TDeferredAtom> Settings; + std::set<TString> SettingsToReset; + + EDatabase Database = EDatabase::Unchanged; + TVector<TDeferredAtom> TablesToAdd; + TVector<TDeferredAtom> TablesToDrop; + + bool MissingOk; +}; + +struct TDropBackupCollectionParameters { + bool MissingOk; +}; + +struct TBackupParameters { + bool Incremental = false; +}; + +struct TRestoreParameters { + TString At; +}; + +struct TStreamingQuerySettings { + inline static constexpr char RESERVED_FEATURE_PREFIX[] = "__"; + inline static constexpr char QUERY_TEXT_FEATURE[] = "__query_text"; + inline static constexpr char QUERY_AST_FEATURE[] = "__query_ast"; + + std::map<TString, TDeferredAtom> Features; +}; + +TString IdContent(TContext& ctx, const TString& str); +TString IdContentFromString(TContext& ctx, const TString& str); +TTableHints GetContextHints(TContext& ctx); + +TString TypeByAlias(const TString& alias, bool normalize = true); + +TNodePtr BuildList(TPosition pos, TVector<TNodePtr> nodes = {}); +TNodePtr BuildQuote(TPosition pos, TNodePtr expr); +TNodePtr BuildAtom(TPosition pos, const TString& content, ui32 flags = NYql::TNodeFlags::ArbitraryContent, + bool isOptionalArg = false); +TNodePtr BuildQuotedAtom(TPosition pos, const TString& content, ui32 flags = NYql::TNodeFlags::ArbitraryContent); + +TNodePtr BuildLiteralNull(TPosition pos); +TNodePtr BuildLiteralVoid(TPosition pos); +/// String is checked as quotable, support escaping and multiline +TNodePtr BuildLiteralSmartString(TContext& ctx, const TString& value); + +struct TExprOrIdent { + TNodePtr Expr; + TString Ident; +}; +TMaybe<TExprOrIdent> BuildLiteralTypedSmartStringOrId(TContext& ctx, const TString& value); + +TNodePtr BuildLiteralRawString(TPosition pos, const TString& value, bool isUtf8 = false); +TNodePtr BuildLiteralBool(TPosition pos, bool value); +TNodePtr BuildEmptyAction(TPosition pos); + +TNodePtr BuildTuple(TPosition pos, const TVector<TNodePtr>& exprs); + +TNodePtr BuildStructure(TPosition pos, const TVector<TNodePtr>& exprs); +TNodePtr BuildStructure(TPosition pos, const TVector<TNodePtr>& exprsUnlabeled, const TVector<TNodePtr>& labels); +TNodePtr BuildOrderedStructure(TPosition pos, const TVector<TNodePtr>& exprsUnlabeled, const TVector<TNodePtr>& labels); + +TNodePtr BuildListOfNamedNodes(TPosition pos, TVector<TNodePtr>&& exprs); + +TNodePtr BuildArgPlaceholder(TPosition pos, const TString& name); + +TNodePtr BuildColumn(TPosition pos, const TString& column = TString(), const TString& source = TString()); +TNodePtr BuildColumn(TPosition pos, const TNodePtr& column, const TString& source = TString()); +TNodePtr BuildColumn(TPosition pos, const TDeferredAtom& column, const TString& source = TString()); +TNodePtr BuildColumnOrType(TPosition pos, const TString& column = TString()); +TNodePtr BuildAccess(TPosition pos, const TVector<INode::TIdPart>& ids, bool isLookup); +TNodePtr BuildBind(TPosition pos, const TString& module, const TString& alias); +TNodePtr BuildLambda(TPosition pos, TNodePtr params, TNodePtr body, const TString& resName = TString()); +TNodePtr BuildLambda(TPosition pos, TNodePtr params, const TVector<TNodePtr>& bodies); +TNodePtr BuildDataType(TPosition pos, const TString& typeName); +TMaybe<TString> LookupSimpleType(const TStringBuf& alias, bool flexibleTypes, bool isPgType); +TNodePtr BuildSimpleType(TContext& ctx, TPosition pos, const TString& typeName, bool dataOnly); +TNodePtr BuildIsNullOp(TPosition pos, TNodePtr a); +TNodePtr BuildBinaryOp(TContext& ctx, TPosition pos, const TString& opName, TNodePtr a, TNodePtr b); +TNodePtr BuildBinaryOpRaw(TPosition pos, const TString& opName, TNodePtr a, TNodePtr b); + +TNodePtr BuildCalcOverWindow(TPosition pos, const TString& windowName, TNodePtr call); +TNodePtr BuildYsonOptionsNode(TPosition pos, bool autoConvert, bool strict, bool fastYson); + +TNodePtr BuildDoCall(TPosition pos, const TNodePtr& node); +TNodePtr BuildTupleResult(TNodePtr tuple, size_t ensureTupleSize); +TNodePtr BuildNamedExprReference(TNodePtr parent, const TString& name, TMaybe<size_t> tupleIndex); +TNodePtr BuildNamedExpr(TNodePtr parent); + +// Implemented in aggregation.cpp +TAggregationPtr BuildFactoryAggregation(TPosition pos, const TString& name, const TString& func, EAggregateMode aggMode, bool multi = false); +TAggregationPtr BuildKeyPayloadFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +TAggregationPtr BuildPayloadPredicateFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +TAggregationPtr BuildTwoArgsFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +TAggregationPtr BuildHistogramFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +TAggregationPtr BuildLinearHistogramFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +template <bool HasKey> +TAggregationPtr BuildTopFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +TAggregationPtr BuildTopFreqFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +TAggregationPtr BuildCountDistinctEstimateFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +TAggregationPtr BuildListFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +TAggregationPtr BuildPercentileFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +TAggregationPtr BuildCountAggregation(TPosition pos, const TString& name, const TString& func, EAggregateMode aggMode); +TAggregationPtr BuildUserDefinedFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); +TAggregationPtr BuildPGFactoryAggregation(TPosition pos, const TString& name, EAggregateMode aggMode); +TAggregationPtr BuildNthFactoryAggregation(TPosition pos, const TString& name, const TString& factory, EAggregateMode aggMode); + +// Implemented in builtin.cpp +TNodePtr BuildSqlCall(TContext& ctx, TPosition pos, const TString& module, const TString& name, const TVector<TNodePtr>& args, + TNodePtr positionalArgs, TNodePtr namedArgs, TNodePtr externalTypes, const TDeferredAtom& typeConfig, TNodePtr runConfig, + TNodePtr options, const TVector<TNodePtr>& depends); +TNodePtr BuildScriptUdf(TPosition pos, const TString& moduleName, const TString& funcName, const TVector<TNodePtr>& args, + TNodePtr options); + +TNodePtr BuildCallable(TPosition pos, const TString& module, const TString& name, const TVector<TNodePtr>& args, bool forReduce = false); +TNodePtr BuildUdf(TContext& ctx, TPosition pos, const TString& module, const TString& name, const TVector<TNodePtr>& args); +TNodePtr BuildBuiltinFunc( + TContext& ctx, + TPosition pos, + TString name, + const TVector<TNodePtr>& args, + const TString& nameSpace = TString(), + EAggregateMode aggMode = EAggregateMode::Normal, + bool* mustUseNamed = nullptr, + bool warnOnYqlNameSpace = true); + +// Implemented in query.cpp +TNodePtr BuildCreateGroup(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TMaybe<TCreateGroupParameters>& params, TScopedStatePtr scoped); +TNodePtr BuildControlUser(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, + const TMaybe<TUserParameters>& params, TScopedStatePtr scoped, bool isCreateUser); +TNodePtr BuildRenameUser(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TDeferredAtom& newName, TScopedStatePtr scoped); +TNodePtr BuildAlterGroup(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TVector<TDeferredAtom>& toChange, bool isDrop, + TScopedStatePtr scoped); +TNodePtr BuildRenameGroup(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TDeferredAtom& newName, TScopedStatePtr scoped); +TNodePtr BuildDropRoles(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TVector<TDeferredAtom>& toDrop, bool isUser, bool missingOk, TScopedStatePtr scoped); +TNodePtr BuildGrantPermissions(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TVector<TDeferredAtom>& permissions, const TVector<TDeferredAtom>& schemaPaths, const TVector<TDeferredAtom>& roleName, TScopedStatePtr scoped); +TNodePtr BuildRevokePermissions(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TVector<TDeferredAtom>& permissions, const TVector<TDeferredAtom>& schemaPaths, const TVector<TDeferredAtom>& roleName, TScopedStatePtr scoped); +TNodePtr BuildUpsertObjectOperation(TPosition pos, const TString& objectId, const TString& typeId, + std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context); +TNodePtr BuildCreateObjectOperation(TPosition pos, const TString& objectId, const TString& typeId, + bool existingOk, bool replaceIfExists, std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context); +TNodePtr BuildAlterObjectOperation(TPosition pos, const TString& secretId, const TString& typeId, + bool missingOk, std::map<TString, TDeferredAtom>&& features, std::set<TString>&& featuresToReset, const TObjectOperatorContext& context); +TNodePtr BuildDropObjectOperation(TPosition pos, const TString& secretId, const TString& typeId, + bool missingOk, std::map<TString, TDeferredAtom>&& options, const TObjectOperatorContext& context); +TNodePtr BuildCreateAsyncReplication(TPosition pos, const TString& id, + std::vector<std::pair<TString, TString>>&& targets, + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context); +TNodePtr BuildAlterAsyncReplication(TPosition pos, const TString& id, + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context); +TNodePtr BuildDropAsyncReplication(TPosition pos, const TString& id, bool cascade, const TObjectOperatorContext& context); +TNodePtr BuildCreateTransfer(TPosition pos, const TString& id, const TString&& source, const TString&& target, + const TString&& transformLambda, + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context); +TNodePtr BuildAlterTransfer(TPosition pos, const TString& id, std::optional<TString>&& transformLambda, + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context); +TNodePtr BuildDropTransfer(TPosition pos, const TString& id, bool cascade, const TObjectOperatorContext& context); +TNodePtr BuildWriteResult(TPosition pos, const TString& label, TNodePtr settings); +TNodePtr BuildCommitClusters(TPosition pos); +TNodePtr BuildRollbackClusters(TPosition pos); +TNodePtr BuildQuery(TPosition pos, const TVector<TNodePtr>& blocks, bool topLevel, TScopedStatePtr scoped, bool useSeq); +TNodePtr BuildPragma(TPosition pos, const TString& prefix, const TString& name, const TVector<TDeferredAtom>& values, bool valueDefault); +TNodePtr BuildSqlLambda(TPosition pos, TVector<TString>&& args, TVector<TNodePtr>&& exprSeq); +TNodePtr BuildWorldIfNode(TPosition pos, TNodePtr predicate, TNodePtr thenNode, TNodePtr elseNode, bool isEvaluate); +TNodePtr BuildWorldForNode(TPosition pos, TNodePtr list, TNodePtr bodyNode, TNodePtr elseNode, bool isEvaluate, bool isParallel); + +TNodePtr BuildCreateTopic(TPosition pos, const TTopicRef& tr, const TCreateTopicParameters& params, + TScopedStatePtr scoped); +TNodePtr BuildAlterTopic(TPosition pos, const TTopicRef& tr, const TAlterTopicParameters& params, + TScopedStatePtr scoped); +TNodePtr BuildDropTopic(TPosition pos, const TTopicRef& topic, const TDropTopicParameters& params, + TScopedStatePtr scoped); + +TNodePtr BuildCreateBackupCollection( + TPosition pos, + const TString& prefix, + const TString& id, + const TCreateBackupCollectionParameters& params, + const TObjectOperatorContext& context); +TNodePtr BuildAlterBackupCollection( + TPosition pos, + const TString& prefix, + const TString& id, + const TAlterBackupCollectionParameters& params, + const TObjectOperatorContext& context); +TNodePtr BuildDropBackupCollection( + TPosition pos, + const TString& prefix, + const TString& id, + const TDropBackupCollectionParameters& params, + const TObjectOperatorContext& context); + +TNodePtr BuildBackup( + TPosition pos, + const TString& prefix, + const TString& id, + const TBackupParameters& params, + const TObjectOperatorContext& context); +TNodePtr BuildRestore( + TPosition pos, + const TString& prefix, + const TString& id, + const TRestoreParameters& params, + const TObjectOperatorContext& context); + +TNodePtr BuildCreateSecret( + TPosition pos, + const TString& objectId, + const TSecretParameters& secretParams, + const TObjectOperatorContext& context, + TScopedStatePtr scoped); +TNodePtr BuildAlterSecret( + TPosition pos, + const TString& objectId, + const TSecretParameters& secretParams, + const TObjectOperatorContext& context, + TScopedStatePtr scoped); +TNodePtr BuildDropSecret( + TPosition pos, + const TString& objectId, + const TObjectOperatorContext& context, + TScopedStatePtr scoped); + +template <class TContainer> +TMaybe<TString> FindMistypeIn(const TContainer& container, const TString& name) { + for (auto& item : container) { + if (NLevenshtein::Distance(name, item) < NYql::DefaultMistypeDistance) { + return item; } - return {}; } - - void EnumerateBuiltins(const std::function<void(std::string_view name, std::string_view kind)>& callback); - bool Parseui32(TNodePtr from, ui32& to); - TNodePtr GroundWithExpr(const TNodePtr& ground, const TNodePtr& expr); - const TString* DeriveCommonSourceName(const TVector<TNodePtr> &nodes); -} // namespace NSQLTranslationV1 + return {}; +} + +void EnumerateBuiltins(const std::function<void(std::string_view name, std::string_view kind)>& callback); +bool Parseui32(TNodePtr from, ui32& to); +TNodePtr GroundWithExpr(const TNodePtr& ground, const TNodePtr& expr); +const TString* DeriveCommonSourceName(const TVector<TNodePtr>& nodes); +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/object_processing.cpp b/yql/essentials/sql/v1/object_processing.cpp index f9028b01b84..9e53fd1032a 100644 --- a/yql/essentials/sql/v1/object_processing.cpp +++ b/yql/essentials/sql/v1/object_processing.cpp @@ -18,13 +18,14 @@ bool InitFeatures(TContext& ctx, ISource* src, const std::map<TString, TDeferred return true; } -} // anonymous namespace +} // anonymous namespace TObjectOperatorContext::TObjectOperatorContext(TScopedStatePtr scoped) : Scoped_(scoped) , ServiceId(Scoped_->CurrService) , Cluster(Scoped_->CurrCluster) -{} +{ +} INode::TPtr TObjectProcessorImpl::BuildKeys() const { auto keys = Y("Key"); @@ -38,7 +39,8 @@ TObjectProcessorImpl::TObjectProcessorImpl(TPosition pos, const TString& objectI , TObjectOperatorContext(context) , ObjectId_(objectId) , TypeId_(typeId) -{} +{ +} bool TObjectProcessorImpl::DoInit(TContext& ctx, ISource* src) { Scoped_->UseCluster(ServiceId, Cluster); @@ -46,10 +48,9 @@ bool TObjectProcessorImpl::DoInit(TContext& ctx, ISource* src) { auto keys = BuildKeys(); Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } @@ -58,10 +59,11 @@ TObjectProcessorImpl::TPtr TObjectProcessorImpl::DoClone() const { } TObjectProcessorWithFeatures::TObjectProcessorWithFeatures(TPosition pos, const TString& objectId, const TString& typeId, const TObjectOperatorContext& context, - TFeatureMap&& features) + TFeatureMap&& features) : TBase(pos, objectId, typeId, context) , Features_(std::move(features)) -{} +{ +} INode::TPtr TObjectProcessorWithFeatures::FillFeatures(INode::TPtr options) const { if (!Features_.empty()) { @@ -102,22 +104,24 @@ INode::TPtr TCreateObject::BuildOptions() const { } TCreateObject::TCreateObject(TPosition pos, const TString& objectId, const TString& typeId, const TObjectOperatorContext& context, - TFeatureMap&& features, bool existingOk, bool replaceIfExists) + TFeatureMap&& features, bool existingOk, bool replaceIfExists) : TBase(pos, objectId, typeId, context, std::move(features)) , ExistingOk_(existingOk) , ReplaceIfExists_(replaceIfExists) -{} +{ +} INode::TPtr TUpsertObject::BuildOptions() const { return Y(Q(Y(Q("mode"), Q("upsertObject")))); } TAlterObject::TAlterObject(TPosition pos, const TString& objectId, const TString& typeId, const TObjectOperatorContext& context, - TFeatureMap&& features, std::set<TString>&& featuresToReset, bool missingOk) + TFeatureMap&& features, std::set<TString>&& featuresToReset, bool missingOk) : TBase(pos, objectId, typeId, context, std::move(features)) , FeaturesToReset_(std::move(featuresToReset)) , MissingOk_(missingOk) -{} +{ +} INode::TPtr TAlterObject::FillFeatures(INode::TPtr options) const { options = TBase::FillFeatures(options); @@ -137,13 +141,14 @@ INode::TPtr TAlterObject::BuildOptions() const { } TDropObject::TDropObject(TPosition pos, const TString& objectId, const TString& typeId, const TObjectOperatorContext& context, - TFeatureMap&& features, bool missingOk) + TFeatureMap&& features, bool missingOk) : TBase(pos, objectId, typeId, context, std::move(features)) , MissingOk_(missingOk) -{} +{ +} INode::TPtr TDropObject::BuildOptions() const { return Y(Q(Y(Q("mode"), Q(MissingOk_ ? "dropObjectIfExists" : "dropObject")))); } -} // NSQLTranslationV1 +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/object_processing.h b/yql/essentials/sql/v1/object_processing.h index e3ab60a4ab9..9df8686b250 100644 --- a/yql/essentials/sql/v1/object_processing.h +++ b/yql/essentials/sql/v1/object_processing.h @@ -55,7 +55,7 @@ public: bool DoInit(TContext& ctx, ISource* src) override; TObjectProcessorWithFeatures(TPosition pos, const TString& objectId, const TString& typeId, const TObjectOperatorContext& context, - TFeatureMap&& features); + TFeatureMap&& features); }; class TCreateObject final: public TObjectProcessorWithFeatures { @@ -69,7 +69,7 @@ protected: public: TCreateObject(TPosition pos, const TString& objectId, const TString& typeId, const TObjectOperatorContext& context, - TFeatureMap&& features, bool existingOk, bool replaceIfExists); + TFeatureMap&& features, bool existingOk, bool replaceIfExists); }; class TUpsertObject final: public TObjectProcessorWithFeatures { @@ -95,7 +95,7 @@ protected: public: TAlterObject(TPosition pos, const TString& objectId, const TString& typeId, const TObjectOperatorContext& context, - TFeatureMap&& features, std::set<TString>&& featuresToReset, bool missingOk); + TFeatureMap&& features, std::set<TString>&& featuresToReset, bool missingOk); }; class TDropObject final: public TObjectProcessorWithFeatures { @@ -108,7 +108,7 @@ protected: public: TDropObject(TPosition pos, const TString& objectId, const TString& typeId, const TObjectOperatorContext& context, - TFeatureMap&& features, bool missingOk); + TFeatureMap&& features, bool missingOk); }; -} // NSQLTranslationV1 +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/perf/parse.cpp b/yql/essentials/sql/v1/perf/parse.cpp index 0001b80ec4d..2eaec8361fb 100644 --- a/yql/essentials/sql/v1/perf/parse.cpp +++ b/yql/essentials/sql/v1/perf/parse.cpp @@ -65,12 +65,12 @@ int main(int, char**) { builder << "fld" << j; }; - builder << " FROM " << (i == 0? "Input" : "$query") << ";\n"; + builder << " FROM " << (i == 0 ? "Input" : "$query") << ";\n"; } builder << "SELECT * FROM $query;\n"; TString sql = builder; - //Cerr << sql; + // Cerr << sql; TSimpleTimer timer; for (ui32 i = 0; i < 100; ++i) { NYql::TAstParseResult res = SqlToYql(sql); diff --git a/yql/essentials/sql/v1/perf/ya.make b/yql/essentials/sql/v1/perf/ya.make index dad0eeaee68..d3a2b8a83aa 100644 --- a/yql/essentials/sql/v1/perf/ya.make +++ b/yql/essentials/sql/v1/perf/ya.make @@ -1,5 +1,7 @@ PROGRAM() +ENABLE(YQL_STYLE_CPP) + SRCS( parse.cpp ) diff --git a/yql/essentials/sql/v1/proto_parser/antlr3/proto_parser.cpp b/yql/essentials/sql/v1/proto_parser/antlr3/proto_parser.cpp index 2490ca449d1..10f9892d31c 100644 --- a/yql/essentials/sql/v1/proto_parser/antlr3/proto_parser.cpp +++ b/yql/essentials/sql/v1/proto_parser/antlr3/proto_parser.cpp @@ -8,10 +8,10 @@ namespace NSQLTranslationV1 { namespace { -class TParser : public NSQLTranslation::IParser { +class TParser: public NSQLTranslation::IParser { public: google::protobuf::Message* Parse( - const TString& query, const TString& queryName, NProtoAST::IErrorCollector& err, + const TString& query, const TString& queryName, NProtoAST::IErrorCollector& err, google::protobuf::Arena* arena) final { YQL_ENSURE(arena); NProtoAST::TProtoASTBuilder3<NALPDefault::SQLv1Parser, NALPDefault::SQLv1Lexer> builder(query, queryName, arena); @@ -26,10 +26,10 @@ public: } }; -} +} // namespace NSQLTranslation::TParserFactoryPtr MakeAntlr3ParserFactory() { return MakeIntrusive<TFactory>(); } -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/proto_parser/antlr3/proto_parser.h b/yql/essentials/sql/v1/proto_parser/antlr3/proto_parser.h index 5d40c2f1700..c72b0bb531f 100644 --- a/yql/essentials/sql/v1/proto_parser/antlr3/proto_parser.h +++ b/yql/essentials/sql/v1/proto_parser/antlr3/proto_parser.h @@ -5,4 +5,4 @@ namespace NSQLTranslationV1 { NSQLTranslation::TParserFactoryPtr MakeAntlr3ParserFactory(); -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/proto_parser/antlr3_ansi/proto_parser.cpp b/yql/essentials/sql/v1/proto_parser/antlr3_ansi/proto_parser.cpp index 102f5e187e1..50f8a676edf 100644 --- a/yql/essentials/sql/v1/proto_parser/antlr3_ansi/proto_parser.cpp +++ b/yql/essentials/sql/v1/proto_parser/antlr3_ansi/proto_parser.cpp @@ -8,10 +8,10 @@ namespace NSQLTranslationV1 { namespace { -class TParser : public NSQLTranslation::IParser { +class TParser: public NSQLTranslation::IParser { public: google::protobuf::Message* Parse( - const TString& query, const TString& queryName, NProtoAST::IErrorCollector& err, + const TString& query, const TString& queryName, NProtoAST::IErrorCollector& err, google::protobuf::Arena* arena) final { YQL_ENSURE(arena); NProtoAST::TProtoASTBuilder3<NALPAnsi::SQLv1Parser, NALPAnsi::SQLv1Lexer> builder(query, queryName, arena); @@ -26,10 +26,10 @@ public: } }; -} +} // namespace NSQLTranslation::TParserFactoryPtr MakeAntlr3AnsiParserFactory() { return MakeIntrusive<TFactory>(); } -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/proto_parser/antlr3_ansi/proto_parser.h b/yql/essentials/sql/v1/proto_parser/antlr3_ansi/proto_parser.h index f03f1ea0a72..f852e003ee9 100644 --- a/yql/essentials/sql/v1/proto_parser/antlr3_ansi/proto_parser.h +++ b/yql/essentials/sql/v1/proto_parser/antlr3_ansi/proto_parser.h @@ -5,4 +5,4 @@ namespace NSQLTranslationV1 { NSQLTranslation::TParserFactoryPtr MakeAntlr3AnsiParserFactory(); -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/proto_parser/antlr4/proto_parser.cpp b/yql/essentials/sql/v1/proto_parser/antlr4/proto_parser.cpp index 6cdf0c6d2fb..2d29d0a6ffd 100644 --- a/yql/essentials/sql/v1/proto_parser/antlr4/proto_parser.cpp +++ b/yql/essentials/sql/v1/proto_parser/antlr4/proto_parser.cpp @@ -8,7 +8,7 @@ namespace NSQLTranslationV1 { namespace { -class TParser : public NSQLTranslation::IParser { +class TParser: public NSQLTranslation::IParser { public: explicit TParser(bool isAmbuguityError, bool isAmbiguityDebugging) : IsAmbiguityError_(isAmbuguityError) @@ -17,13 +17,13 @@ public: } google::protobuf::Message* Parse( - const TString& query, const TString& queryName, NProtoAST::IErrorCollector& err, + const TString& query, const TString& queryName, NProtoAST::IErrorCollector& err, google::protobuf::Arena* arena) final { YQL_ENSURE(arena); NProtoAST::TProtoASTBuilder4< NALPDefaultAntlr4::SQLv1Antlr4Parser, NALPDefaultAntlr4::SQLv1Antlr4Lexer> - builder(query, queryName, arena, IsAmbiguityError_, IsAmbiguityDebugging_); + builder(query, queryName, arena, IsAmbiguityError_, IsAmbiguityDebugging_); return builder.BuildAST(err); } @@ -49,7 +49,7 @@ private: bool IsAmbiguityDebugging_; }; -} +} // namespace NSQLTranslation::TParserFactoryPtr MakeAntlr4ParserFactory( bool isAmbiguityError, @@ -58,4 +58,4 @@ NSQLTranslation::TParserFactoryPtr MakeAntlr4ParserFactory( return MakeIntrusive<TFactory>(isAmbiguityError, isAmbiguityDebugging); } -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/proto_parser/antlr4/proto_parser.h b/yql/essentials/sql/v1/proto_parser/antlr4/proto_parser.h index 5b33b43c0d3..146dcfff7aa 100644 --- a/yql/essentials/sql/v1/proto_parser/antlr4/proto_parser.h +++ b/yql/essentials/sql/v1/proto_parser/antlr4/proto_parser.h @@ -7,4 +7,4 @@ NSQLTranslation::TParserFactoryPtr MakeAntlr4ParserFactory( bool isAmbiguityError = false, bool isAmbiguityDebugging = false); -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/proto_parser/antlr4_ansi/proto_parser.cpp b/yql/essentials/sql/v1/proto_parser/antlr4_ansi/proto_parser.cpp index bf0160ade02..89eb7c5aa1a 100644 --- a/yql/essentials/sql/v1/proto_parser/antlr4_ansi/proto_parser.cpp +++ b/yql/essentials/sql/v1/proto_parser/antlr4_ansi/proto_parser.cpp @@ -8,7 +8,7 @@ namespace NSQLTranslationV1 { namespace { -class TParser : public NSQLTranslation::IParser { +class TParser: public NSQLTranslation::IParser { public: explicit TParser(bool isAmbuguityError, bool isAmbiguityDebugging) : IsAmbiguityError_(isAmbuguityError) @@ -17,13 +17,13 @@ public: } google::protobuf::Message* Parse( - const TString& query, const TString& queryName, NProtoAST::IErrorCollector& err, + const TString& query, const TString& queryName, NProtoAST::IErrorCollector& err, google::protobuf::Arena* arena) final { YQL_ENSURE(arena); NProtoAST::TProtoASTBuilder4< NALPAnsiAntlr4::SQLv1Antlr4Parser, NALPAnsiAntlr4::SQLv1Antlr4Lexer> - builder(query, queryName, arena, IsAmbiguityError_, IsAmbiguityDebugging_); + builder(query, queryName, arena, IsAmbiguityError_, IsAmbiguityDebugging_); return builder.BuildAST(err); } @@ -49,7 +49,7 @@ private: bool IsAmbiguityDebugging_; }; -} +} // namespace NSQLTranslation::TParserFactoryPtr MakeAntlr4AnsiParserFactory( bool isAmbiguityError, @@ -58,4 +58,4 @@ NSQLTranslation::TParserFactoryPtr MakeAntlr4AnsiParserFactory( return MakeIntrusive<TFactory>(isAmbiguityError, isAmbiguityDebugging); } -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/proto_parser/antlr4_ansi/proto_parser.h b/yql/essentials/sql/v1/proto_parser/antlr4_ansi/proto_parser.h index 395d89674d6..39ff5d6eba2 100644 --- a/yql/essentials/sql/v1/proto_parser/antlr4_ansi/proto_parser.h +++ b/yql/essentials/sql/v1/proto_parser/antlr4_ansi/proto_parser.h @@ -7,4 +7,4 @@ NSQLTranslation::TParserFactoryPtr MakeAntlr4AnsiParserFactory( bool isAmbiguityError = false, bool isAmbiguityDebugging = false); -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/proto_parser/parse_tree.cpp b/yql/essentials/sql/v1/proto_parser/parse_tree.cpp index a9318368436..17fca6359d6 100644 --- a/yql/essentials/sql/v1/proto_parser/parse_tree.cpp +++ b/yql/essentials/sql/v1/proto_parser/parse_tree.cpp @@ -2,109 +2,109 @@ namespace NSQLTranslationV1 { - const TRule_select_or_expr* GetSelectOrExpr(const TRule_smart_parenthesis& msg) { - if (!msg.GetBlock2().HasAlt1()) { - return nullptr; - } - - return &msg.GetBlock2() - .GetAlt1() - .GetRule_select_subexpr1() - .GetRule_select_subexpr_intersect1() - .GetRule_select_or_expr1(); +const TRule_select_or_expr* GetSelectOrExpr(const TRule_smart_parenthesis& msg) { + if (!msg.GetBlock2().HasAlt1()) { + return nullptr; } - const TRule_tuple_or_expr* GetTupleOrExpr(const TRule_smart_parenthesis& msg) { - const auto* select_or_expr = GetSelectOrExpr(msg); - if (!select_or_expr) { - return nullptr; - } + return &msg.GetBlock2() + .GetAlt1() + .GetRule_select_subexpr1() + .GetRule_select_subexpr_intersect1() + .GetRule_select_or_expr1(); +} + +const TRule_tuple_or_expr* GetTupleOrExpr(const TRule_smart_parenthesis& msg) { + const auto* select_or_expr = GetSelectOrExpr(msg); + if (!select_or_expr) { + return nullptr; + } + + if (!select_or_expr->HasAlt_select_or_expr2()) { + return nullptr; + } - if (!select_or_expr->HasAlt_select_or_expr2()) { - return nullptr; - } + return &select_or_expr + ->GetAlt_select_or_expr2() + .GetRule_tuple_or_expr1(); +} - return &select_or_expr - ->GetAlt_select_or_expr2() - .GetRule_tuple_or_expr1(); +const TRule_smart_parenthesis* GetParenthesis(const TRule_expr& msg) { + if (!msg.HasAlt_expr1()) { + return nullptr; } - const TRule_smart_parenthesis* GetParenthesis(const TRule_expr& msg) { - if (!msg.HasAlt_expr1()) { - return nullptr; - } - - const auto& con = msg.GetAlt_expr1() - .GetRule_or_subexpr1() - .GetRule_and_subexpr1() - .GetRule_xor_subexpr1() - .GetRule_eq_subexpr1() - .GetRule_neq_subexpr1() - .GetRule_bit_subexpr1() - .GetRule_add_subexpr1() - .GetRule_mul_subexpr1() - .GetRule_con_subexpr1(); - - if (!con.HasAlt_con_subexpr1()) { - return nullptr; - } - - const auto& unary_subexpr = con.GetAlt_con_subexpr1() - .GetRule_unary_subexpr1(); - - if (!unary_subexpr.HasAlt_unary_subexpr1()) { - return nullptr; - } - - const auto& block = unary_subexpr.GetAlt_unary_subexpr1() - .GetRule_unary_casual_subexpr1() - .GetBlock1(); - - if (!block.HasAlt2()) { - return nullptr; - } - - const auto& atom = block.GetAlt2() - .GetRule_atom_expr1(); - - if (!atom.HasAlt_atom_expr3()) { - return nullptr; - } - - return &atom.GetAlt_atom_expr3() - .GetRule_lambda1() - .GetRule_smart_parenthesis1(); + const auto& con = msg.GetAlt_expr1() + .GetRule_or_subexpr1() + .GetRule_and_subexpr1() + .GetRule_xor_subexpr1() + .GetRule_eq_subexpr1() + .GetRule_neq_subexpr1() + .GetRule_bit_subexpr1() + .GetRule_add_subexpr1() + .GetRule_mul_subexpr1() + .GetRule_con_subexpr1(); + + if (!con.HasAlt_con_subexpr1()) { + return nullptr; } - bool IsSelect(const TRule_smart_parenthesis& msg) { - const auto* select_or_expr = GetSelectOrExpr(msg); - if (!select_or_expr) { - return false; - } + const auto& unary_subexpr = con.GetAlt_con_subexpr1() + .GetRule_unary_subexpr1(); - if (select_or_expr->HasAlt_select_or_expr1()) { - return true; - } + if (!unary_subexpr.HasAlt_unary_subexpr1()) { + return nullptr; + } - return IsSelect( - select_or_expr - ->GetAlt_select_or_expr2() - .GetRule_tuple_or_expr1() - .GetRule_expr1()); + const auto& block = unary_subexpr.GetAlt_unary_subexpr1() + .GetRule_unary_casual_subexpr1() + .GetBlock1(); + + if (!block.HasAlt2()) { + return nullptr; } - bool IsSelect(const TRule_expr& msg) { - const auto* parenthesis = GetParenthesis(msg); - if (!parenthesis) { - return false; - } + const auto& atom = block.GetAlt2() + .GetRule_atom_expr1(); - return IsSelect(*parenthesis); + if (!atom.HasAlt_atom_expr3()) { + return nullptr; } - bool IsOnlySubExpr(const TRule_select_subexpr& node) { - return node.GetBlock2().size() == 0 && - node.GetRule_select_subexpr_intersect1().GetBlock2().size() == 0; + return &atom.GetAlt_atom_expr3() + .GetRule_lambda1() + .GetRule_smart_parenthesis1(); +} + +bool IsSelect(const TRule_smart_parenthesis& msg) { + const auto* select_or_expr = GetSelectOrExpr(msg); + if (!select_or_expr) { + return false; + } + + if (select_or_expr->HasAlt_select_or_expr1()) { + return true; } + return IsSelect( + select_or_expr + ->GetAlt_select_or_expr2() + .GetRule_tuple_or_expr1() + .GetRule_expr1()); +} + +bool IsSelect(const TRule_expr& msg) { + const auto* parenthesis = GetParenthesis(msg); + if (!parenthesis) { + return false; + } + + return IsSelect(*parenthesis); +} + +bool IsOnlySubExpr(const TRule_select_subexpr& node) { + return node.GetBlock2().size() == 0 && + node.GetRule_select_subexpr_intersect1().GetBlock2().size() == 0; +} + } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/proto_parser/parse_tree.h b/yql/essentials/sql/v1/proto_parser/parse_tree.h index 74936d90466..40ecdea8623 100644 --- a/yql/essentials/sql/v1/proto_parser/parse_tree.h +++ b/yql/essentials/sql/v1/proto_parser/parse_tree.h @@ -4,14 +4,14 @@ namespace NSQLTranslationV1 { - using namespace NSQLv1Generated; +using namespace NSQLv1Generated; - const TRule_tuple_or_expr* GetTupleOrExpr(const TRule_smart_parenthesis& msg); +const TRule_tuple_or_expr* GetTupleOrExpr(const TRule_smart_parenthesis& msg); - bool IsSelect(const TRule_smart_parenthesis& msg); +bool IsSelect(const TRule_smart_parenthesis& msg); - bool IsSelect(const TRule_expr& msg); +bool IsSelect(const TRule_expr& msg); - bool IsOnlySubExpr(const TRule_select_subexpr& msg); +bool IsOnlySubExpr(const TRule_select_subexpr& msg); } // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/proto_parser/proto_parser.cpp b/yql/essentials/sql/v1/proto_parser/proto_parser.cpp index 5fbef92ca52..bba5e729635 100644 --- a/yql/essentials/sql/v1/proto_parser/proto_parser.cpp +++ b/yql/essentials/sql/v1/proto_parser/proto_parser.cpp @@ -4,7 +4,6 @@ #include <yql/essentials/parser/proto_ast/collect_issues/collect_issues.h> - #include <yql/essentials/sql/v1/proto_parser/antlr3/proto_parser.h> #include <yql/essentials/sql/v1/proto_parser/antlr3_ansi/proto_parser.h> #include <yql/essentials/sql/v1/proto_parser/antlr4/proto_parser.h> @@ -13,16 +12,15 @@ #include <util/generic/algorithm.h> #if defined(_tsan_enabled_) -#include <util/system/mutex.h> + #include <util/system/mutex.h> #endif using namespace NYql; namespace NSQLTranslationV1 { - #if defined(_tsan_enabled_) - TMutex SanitizerSQLTranslationMutex; +TMutex SanitizerSQLTranslationMutex; #endif namespace { @@ -31,16 +29,16 @@ void ReportError(NAST::IErrorCollector& err, const TString& name) { err.Error(0, 0, TStringBuilder() << "Parser " << name << " is not supported"); } -} +} // namespace google::protobuf::Message* SqlAST(const TParsers& parsers, const TString& query, const TString& queryName, TIssues& err, - size_t maxErrors, bool ansiLexer, bool anlr4Parser, google::protobuf::Arena* arena) { + size_t maxErrors, bool ansiLexer, bool anlr4Parser, google::protobuf::Arena* arena) { NSQLTranslation::TErrorCollectorOverIssues collector(err, maxErrors, queryName); return SqlAST(parsers, query, queryName, collector, ansiLexer, anlr4Parser, arena); } google::protobuf::Message* SqlAST(const TParsers& parsers, const TString& query, const TString& queryName, NAST::IErrorCollector& err, - bool ansiLexer, bool anlr4Parser, google::protobuf::Arena* arena) { + bool ansiLexer, bool anlr4Parser, google::protobuf::Arena* arena) { YQL_ENSURE(arena); #if defined(_tsan_enabled_) TGuard<TMutex> grd(SanitizerSQLTranslationMutex); diff --git a/yql/essentials/sql/v1/proto_parser/proto_parser.h b/yql/essentials/sql/v1/proto_parser/proto_parser.h index 39c41771410..c4a3c663207 100644 --- a/yql/essentials/sql/v1/proto_parser/proto_parser.h +++ b/yql/essentials/sql/v1/proto_parser/proto_parser.h @@ -8,20 +8,20 @@ #include <google/protobuf/message.h> namespace NSQLTranslation { - struct TTranslationSettings; -} +struct TTranslationSettings; +} // namespace NSQLTranslation namespace NSQLTranslationV1 { - struct TParsers { - NSQLTranslation::TParserFactoryPtr Antlr3; - NSQLTranslation::TParserFactoryPtr Antlr3Ansi; - NSQLTranslation::TParserFactoryPtr Antlr4; - NSQLTranslation::TParserFactoryPtr Antlr4Ansi; - }; +struct TParsers { + NSQLTranslation::TParserFactoryPtr Antlr3; + NSQLTranslation::TParserFactoryPtr Antlr3Ansi; + NSQLTranslation::TParserFactoryPtr Antlr4; + NSQLTranslation::TParserFactoryPtr Antlr4Ansi; +}; - google::protobuf::Message* SqlAST(const TParsers& parsers, const TString& query, const TString& queryName, - NYql::TIssues& err, size_t maxErrors, bool ansiLexer, bool antlr4Parser, google::protobuf::Arena* arena); - google::protobuf::Message* SqlAST(const TParsers& parsers, const TString& query, const TString& queryName, - NAST::IErrorCollector& err, bool ansiLexer, bool antlr4Parser, google::protobuf::Arena* arena); -} // namespace NSQLTranslationV1 +google::protobuf::Message* SqlAST(const TParsers& parsers, const TString& query, const TString& queryName, + NYql::TIssues& err, size_t maxErrors, bool ansiLexer, bool antlr4Parser, google::protobuf::Arena* arena); +google::protobuf::Message* SqlAST(const TParsers& parsers, const TString& query, const TString& queryName, + NAST::IErrorCollector& err, bool ansiLexer, bool antlr4Parser, google::protobuf::Arena* arena); +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/proto_parser/ya.make b/yql/essentials/sql/v1/proto_parser/ya.make index 0fbe9f45469..256a3091aec 100644 --- a/yql/essentials/sql/v1/proto_parser/ya.make +++ b/yql/essentials/sql/v1/proto_parser/ya.make @@ -1,5 +1,7 @@ LIBRARY() +ENABLE(YQL_STYLE_CPP) + PEERDIR( yql/essentials/utils yql/essentials/parser/proto_ast/collect_issues diff --git a/yql/essentials/sql/v1/query.cpp b/yql/essentials/sql/v1/query.cpp index 0b2461180b5..2127f8a210a 100644 --- a/yql/essentials/sql/v1/query.cpp +++ b/yql/essentials/sql/v1/query.cpp @@ -26,7 +26,7 @@ bool ValidateView(TPosition pos, TContext& ctx, TStringBuf service, TViewDescrip class TUniqueTableKey: public ITableKeys { public: TUniqueTableKey(TPosition pos, const TString& service, const TDeferredAtom& cluster, - const TDeferredAtom& name, const TViewDescription& view) + const TDeferredAtom& name, const TViewDescription& view) : ITableKeys(pos) , Service_(service) , Cluster_(cluster) @@ -87,7 +87,6 @@ public: Service_ != KikimrProviderName && Service_ != RtmrProviderName && Service_ != YdbProviderName) { - key = Y("MrTableConcat", key); } return key; @@ -102,7 +101,7 @@ private: }; TNodePtr BuildTableKey(TPosition pos, const TString& service, const TDeferredAtom& cluster, - const TDeferredAtom& name, const TViewDescription& view) { + const TDeferredAtom& name, const TViewDescription& view) { return new TUniqueTableKey(pos, service, cluster, name, view); } @@ -187,8 +186,7 @@ static INode::TPtr CreateTableSettings(const TTableSettings& tableSettings, ETab settings = L(settings, Q(Y(Q(id.Name), value))); } else { Y_ENSURE(parsingMode != ETableSettingsParsingMode::Create, - "Can't reset " << resetableParam.GetValueReset().Name << " in create mode" - ); + "Can't reset " << resetableParam.GetValueReset().Name << " in create mode"); settings = L(settings, Q(Y(Q(resetableParam.GetValueReset().Name)))); } } @@ -301,8 +299,8 @@ static INode::TPtr CreateIndexSettings(const TIndexDescription::TIndexSettings& for (const auto& [_, indexSetting] : indexSettings) { settings = L(settings, Q(Y( - BuildQuotedAtom(indexSetting.NamePosition, indexSetting.Name), - BuildQuotedAtom(indexSetting.ValuePosition, indexSetting.Value)))); + BuildQuotedAtom(indexSetting.NamePosition, indexSetting.Name), + BuildQuotedAtom(indexSetting.ValuePosition, indexSetting.Value)))); } return settings; @@ -323,13 +321,11 @@ static INode::TPtr CreateIndexDesc(const TIndexDescription& index, ETableSetting node.Q(indexName), node.Q(indexType), node.Q(node.Y(node.Q("indexColumns"), node.Q(indexColumns))), - node.Q(node.Y(node.Q("dataColumns"), node.Q(dataColumns))) - ); + node.Q(node.Y(node.Q("dataColumns"), node.Q(dataColumns)))); if (index.TableSettings.IsSet()) { const auto& tableSettings = node.Q(node.Y( node.Q("tableSettings"), - node.Q(CreateTableSettings(index.TableSettings, parsingMode, node)) - )); + node.Q(CreateTableSettings(index.TableSettings, parsingMode, node)))); indexNode = node.L(indexNode, tableSettings); } if (index.IndexSettings) { @@ -345,12 +341,10 @@ static INode::TPtr CreateAlterIndex(const TIndexDescription& index, const INode& const auto& indexName = node.Y(node.Q("indexName"), BuildQuotedAtom(index.Name.Pos, index.Name.Name)); const auto& tableSettings = node.Y( node.Q("tableSettings"), - node.Q(CreateTableSettings(index.TableSettings, ETableSettingsParsingMode::Alter, node)) - ); + node.Q(CreateTableSettings(index.TableSettings, ETableSettingsParsingMode::Alter, node))); return node.Y( node.Q(indexName), - node.Q(tableSettings) - ); + node.Q(tableSettings)); } static INode::TPtr CreateChangefeedDesc(const TChangefeedDescription& desc, const INode& node) { @@ -406,14 +400,13 @@ static INode::TPtr CreateChangefeedDesc(const TChangefeedDescription& desc, cons return node.Y( node.Q(node.Y(node.Q("name"), BuildQuotedAtom(desc.Name.Pos, desc.Name.Name))), node.Q(node.Y(node.Q("settings"), node.Q(settings))), - node.Q(node.Y(node.Q("state"), node.Q(state))) - ); + node.Q(node.Y(node.Q("state"), node.Q(state)))); } class TPrepTableKeys: public ITableKeys { public: TPrepTableKeys(TPosition pos, const TString& service, const TDeferredAtom& cluster, - const TString& func, const TVector<TTableArg>& args) + const TString& func, const TVector<TTableArg>& args) : ITableKeys(pos) , Service_(service) , Cluster_(cluster) @@ -422,7 +415,7 @@ public: { } - void ExtractTableName(TContext&ctx, TTableArg& arg) { + void ExtractTableName(TContext& ctx, TTableArg& arg) { MakeTableFromExpression(Pos_, ctx, arg.Expr, arg.Id); } @@ -441,7 +434,7 @@ public: } if (func != "object" && func != "walkfolders") { - for (auto& arg: Args_) { + for (auto& arg : Args_) { if (arg.Expr->GetLabel()) { ctx.Error(Pos_) << "Named arguments are not supported for table function " << to_upper(Func_); return nullptr; @@ -450,7 +443,7 @@ public: } if (func == "concatstrict") { auto tuple = Y(); - for (auto& arg: Args_) { + for (auto& arg : Args_) { ExtractTableName(ctx, arg); TNodePtr key; if (arg.HasAt) { @@ -471,8 +464,7 @@ public: tuple = L(tuple, key); } return Q(tuple); - } - else if (func == "concat") { + } else if (func == "concat") { auto concat = Y("MrTableConcat"); for (auto& arg : Args_) { ExtractTableName(ctx, arg); @@ -499,7 +491,7 @@ public: } else if (func == "range" || func == "rangestrict" || func == "like" || func == "likestrict" || - func == "regexp" || func == "regexpstrict" || func == "filter" || func == "filterstrict") { + func == "regexp" || func == "regexpstrict" || func == "filter" || func == "filterstrict") { bool isRange = func.StartsWith("range"); bool isFilter = func.StartsWith("filter"); size_t minArgs = isRange ? 1 : 2; @@ -513,7 +505,7 @@ public: return nullptr; } - for (ui32 index=0; index < Args_.size(); ++index) { + for (ui32 index = 0; index < Args_.size(); ++index) { auto& arg = Args_[index]; if (arg.HasAt) { ctx.Error(Pos_) << "Temporary tables are not supported here"; @@ -565,8 +557,7 @@ public: if (min.Empty() && max.Empty()) { predicate = BuildLambda(Pos_, Y("item"), Y("Bool", Q("true"))); - } - else { + } else { auto minPred = !min.Empty() ? Y(">=", "item", Y("String", min.Build())) : nullptr; auto maxPred = !max.Empty() ? Y("<=", "item", Y("String", max.Build())) : nullptr; if (!minPred) { @@ -585,22 +576,20 @@ public: if (func.StartsWith("regexp")) { if (!ctx.PragmaRegexUseRe2) { if (!ctx.Warning(Pos_, TIssuesIds::CORE_LEGACY_REGEX_ENGINE, [&](auto& out) { - out << "Legacy regex engine works incorrectly with unicode. " - << "Use PRAGMA RegexUseRe2='true';"; - })) { + out << "Legacy regex engine works incorrectly with unicode. " + << "Use PRAGMA RegexUseRe2='true';"; + })) { return nullptr; } } auto pattern = Args_[1].Id; - auto udf = ctx.PragmaRegexUseRe2 ? - Y("Udf", Q("Re2.Grep"), Q(Y(Y("String", pattern.Build()), Y("Null")))): - Y("Udf", Q("Pcre.BacktrackingGrep"), Y("String", pattern.Build())); + auto udf = ctx.PragmaRegexUseRe2 ? Y("Udf", Q("Re2.Grep"), Q(Y(Y("String", pattern.Build()), Y("Null")))) : Y("Udf", Q("Pcre.BacktrackingGrep"), Y("String", pattern.Build())); predicate = BuildLambda(Pos_, Y("item"), Y("Apply", udf, "item")); } else if (func.StartsWith("like")) { auto pattern = Args_[1].Id; auto convertedPattern = Y("Apply", Y("Udf", Q("Re2.PatternFromLike")), - Y("String", pattern.Build())); + Y("String", pattern.Build())); auto udf = Y("Udf", Q("Re2.Match"), Q(Y(convertedPattern, Y("Null")))); predicate = BuildLambda(Pos_, Y("item"), Y("Apply", udf, "item")); } else { @@ -634,8 +623,8 @@ public: auto type = Y("ListType", Y("DataType", Q("String"))); auto key = Y("Key", Q(Y(Q("table"), Y("EvaluateExpr", - Y("EnsureType", Y("Coalesce", arg.Expr, - Y("List", type)), type))))); + Y("EnsureType", Y("Coalesce", arg.Expr, + Y("List", type)), type))))); key = AddView(key, arg.View); if (!ValidateView(GetPos(), ctx, Service_, arg.View)) { @@ -650,8 +639,7 @@ public: } } return each; - } - else if (func == "folder") { + } else if (func == "folder") { size_t minArgs = 1; size_t maxArgs = 2; if (Args_.size() < minArgs || Args_.size() > maxArgs) { @@ -683,8 +671,7 @@ public: folder = L(folder, Args_[0].Id.Build()); folder = L(folder, Args_.size() > 1 ? Args_[1].Id.Build() : BuildQuotedAtom(Pos_, "")); return folder; - } - else if (func == "walkfolders") { + } else if (func == "walkfolders") { const size_t minPositionalArgs = 1; const size_t maxPositionalArgs = 2; @@ -698,8 +685,8 @@ public: } if (positionalArgsCnt < minPositionalArgs || positionalArgsCnt > maxPositionalArgs) { ctx.Error(Pos_) << Func_ << " requires from " << minPositionalArgs - << " to " << maxPositionalArgs - << " positional arguments, but got: " << positionalArgsCnt; + << " to " << maxPositionalArgs + << " positional arguments, but got: " << positionalArgsCnt; return nullptr; } @@ -733,24 +720,19 @@ public: if (label == "RootAttributes") { ExtractTableName(ctx, arg); rootAttributes = arg.Id.Build(); - } - else if (label == "PreHandler") { + } else if (label == "PreHandler") { preHandler = arg.Expr; - } - else if (label == "ResolveHandler") { + } else if (label == "ResolveHandler") { resolveHandler = arg.Expr; - } - else if (label == "DiveHandler") { + } else if (label == "DiveHandler") { diveHandler = arg.Expr; - } - else if (label == "PostHandler") { + } else if (label == "PostHandler") { postHandler = arg.Expr; - } - else { + } else { if (!ctx.Warning(Pos_, DEFAULT_ERROR, [&](auto& out) { - out << "Unsupported named argument: " - << label << " in " << Func_; - })) { + out << "Unsupported named argument: " + << label << " in " << Func_; + })) { return nullptr; } } @@ -795,21 +777,19 @@ public: const auto initPath = rootFolderArg.Id.Build(); return Y("MrWalkFolders", initPath, rootAttributes, pickledInitState, initStateType, - preHandler, resolveHandler, diveHandler, postHandler); - } - else if (func == "tables") { + preHandler, resolveHandler, diveHandler, postHandler); + } else if (func == "tables") { if (!Args_.empty()) { ctx.Error(Pos_) << Func_ << " doesn't accept arguments"; return nullptr; } return L(Y("DataTables")); - } - else if (func == "object") { + } else if (func == "object") { const size_t positionalArgs = 2; auto result = Y("MrObject"); auto settings = Y(); - //TVector<TNodePtr> settings; + // TVector<TNodePtr> settings; size_t argc = 0; for (ui32 index = 0; index < Args_.size(); ++index) { auto& arg = Args_[index]; @@ -839,8 +819,7 @@ public: result = L(result, Q(settings)); return result; - } - else if (func == "partitionlist" || func == "partitionliststrict") { + } else if (func == "partitionlist" || func == "partitionliststrict") { auto requiredLangVer = MakeLangVersion(2025, 4); if (!IsBackwardCompatibleFeatureAvailable(ctx.Settings.LangVer, requiredLangVer, ctx.Settings.BackportMode)) { auto str = FormatLangVersion(requiredLangVer); @@ -884,11 +863,11 @@ private: }; TNodePtr BuildTableKeys(TPosition pos, const TString& service, const TDeferredAtom& cluster, - const TString& func, const TVector<TTableArg>& args) { + const TString& func, const TVector<TTableArg>& args) { return new TPrepTableKeys(pos, service, cluster, func, args); } -class TInputOptions final : public TAstListNode { +class TInputOptions final: public TAstListNode { public: TInputOptions(TPosition pos, const TTableHints& hints) : TAstListNode(pos) @@ -897,7 +876,7 @@ public: } bool DoInit(TContext& ctx, ISource* src) override { - for (auto& hint: Hints_) { + for (auto& hint : Hints_) { TString hintName = hint.first; TMaybe<TIssue> normalizeError = NormalizeName(Pos_, hintName); if (!normalizeError.Empty()) { @@ -949,7 +928,7 @@ TNodePtr BuildInputOptions(TPosition pos, const TTableHints& hints) { return new TInputOptions(pos, hints); } -class TIntoTableOptions : public TAstListNode { +class TIntoTableOptions: public TAstListNode { public: TIntoTableOptions(TPosition pos, const TVector<TString>& columns, const TTableHints& hints) : TAstListNode(pos) @@ -963,7 +942,7 @@ public: Y_UNUSED(src); TNodePtr options = Y(); - for (const auto& column: Columns_) { + for (const auto& column : Columns_) { options->Add(Q(column)); } if (Columns_) { @@ -1004,7 +983,7 @@ TNodePtr BuildIntoTableOptions(TPosition pos, const TVector<TString>& eraseColum return new TIntoTableOptions(pos, eraseColumns, hints); } -class TInputTablesNode final : public TAstListNode { +class TInputTablesNode final: public TAstListNode { public: TInputTablesNode(TPosition pos, const TTableList& tables, bool inSubquery, TScopedStatePtr scoped) : TAstListNode(pos) @@ -1016,7 +995,7 @@ public: bool DoInit(TContext& ctx, ISource* src) override { THashSet<TString> processedTables; - for (auto& tr: Tables_) { + for (auto& tr : Tables_) { if (!processedTables.insert(tr.RefName).second) { continue; } @@ -1060,7 +1039,7 @@ TNodePtr BuildInputTables(TPosition pos, const TTableList& tables, bool inSubque return new TInputTablesNode(pos, tables, inSubquery, scoped); } -class TCreateTableNode final : public TAstListNode { +class TCreateTableNode final: public TAstListNode { public: TCreateTableNode(TPosition pos, const TTableRef& tr, bool existingOk, bool replaceIfExists, const TCreateTableParameters& params, TSourcePtr values, TScopedStatePtr scoped) : TAstListNode(pos) @@ -1080,11 +1059,7 @@ public: return false; } - if (!Params_.PkColumns.empty() - || !Params_.PartitionByColumns.empty() - || !Params_.OrderByColumns.empty() - || !Params_.Indexes.empty() - || !Params_.Changefeeds.empty()) + if (!Params_.PkColumns.empty() || !Params_.PartitionByColumns.empty() || !Params_.OrderByColumns.empty() || !Params_.Indexes.empty() || !Params_.Changefeeds.empty()) { THashSet<TString> columnsSet; for (auto& col : Params_.Columns) { @@ -1157,11 +1132,11 @@ public: } if (ExistingOk_) { - opts = L(opts, Q(Y(Q("mode"), Q("create_if_not_exists")))); + opts = L(opts, Q(Y(Q("mode"), Q("create_if_not_exists")))); } else if (ReplaceIfExists_) { - opts = L(opts, Q(Y(Q("mode"), Q("create_or_replace")))); + opts = L(opts, Q(Y(Q("mode"), Q("create_or_replace")))); } else { - opts = L(opts, Q(Y(Q("mode"), Q("create")))); + opts = L(opts, Q(Y(Q("mode"), Q("create")))); } THashSet<TString> columnFamilyNames; @@ -1303,8 +1278,7 @@ public: if (Params_.TableSettings.IsSet()) { opts = L(opts, Q(Y(Q("tableSettings"), Q( - CreateTableSettings(Params_.TableSettings, ETableSettingsParsingMode::Create, *this) - )))); + CreateTableSettings(Params_.TableSettings, ETableSettingsParsingMode::Create, *this))))); } switch (Params_.TableType) { @@ -1349,8 +1323,7 @@ public: auto write = Y( Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Table_.Service), Scoped_->WrapCluster(Table_.Cluster, ctx))), Y("let", "world", Y(TString(WriteName), "world", "sink", keys, "values", Q(opts))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ); + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))); node = L(node, Y("let", "world", Y("block", Q(write)))); node = L(node, Y("return", "world")); @@ -1363,6 +1336,7 @@ public: TPtr DoClone() const final { return {}; } + private: const TTableRef Table_; const TCreateTableParameters Params_; @@ -1388,22 +1362,21 @@ bool InitDatabaseSettings(TContext& ctx, ISource* src, const THashMap<TString, T return true; } -} +} // namespace -class TAlterDatabaseNode final : public TAstListNode { +class TAlterDatabaseNode final: public TAstListNode { public: TAlterDatabaseNode( TPosition pos, const TString& service, const TDeferredAtom& cluster, const TAlterDatabaseParameters& params, - TScopedStatePtr scoped - ) - : TAstListNode(pos) - , Params_(params) - , Scoped_(scoped) - , Cluster_(cluster) - , Service_(service) + TScopedStatePtr scoped) + : TAstListNode(pos) + , Params_(params) + , Scoped_(scoped) + , Cluster_(cluster) + , Service_(service) { scoped->UseCluster(service, cluster); } @@ -1422,10 +1395,9 @@ public: AddDatabaseSettings(options, Params_.DatabaseSettings); Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), cluster)), - Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("databasePath"), Y("String", Params_.DbPath.Build())))), Y("Void"), Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), cluster)), + Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("databasePath"), Y("String", Params_.DbPath.Build())))), Y("Void"), Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } @@ -1445,7 +1417,6 @@ private: options = L(options, Q(Y(BuildQuotedAtom(Pos_, setting), value))); } } - }; TNodePtr BuildAlterDatabase( @@ -1453,19 +1424,16 @@ TNodePtr BuildAlterDatabase( const TString& service, const TDeferredAtom& cluster, const TAlterDatabaseParameters& params, - TScopedStatePtr scoped -) { + TScopedStatePtr scoped) { return new TAlterDatabaseNode( pos, service, cluster, params, - scoped - ); + scoped); } - -class TAlterTableNode final : public TAstListNode { +class TAlterTableNode final: public TAstListNode { public: TAlterTableNode(TPosition pos, const TTableRef& tr, const TAlterTableParameters& params, TScopedStatePtr scoped) : TAstListNode(pos) @@ -1623,8 +1591,7 @@ public: if (Params_.TableSettings.IsSet()) { actions = L(actions, Q(Y(Q("setTableSettings"), Q( - CreateTableSettings(Params_.TableSettings, ETableSettingsParsingMode::Alter, *this) - )))); + CreateTableSettings(Params_.TableSettings, ETableSettingsParsingMode::Alter, *this))))); } for (const auto& index : Params_.AddIndexes) { @@ -1692,16 +1659,16 @@ public: } Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Table_.Service), Scoped_->WrapCluster(Table_.Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Table_.Service), Scoped_->WrapCluster(Table_.Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } TPtr DoClone() const final { return {}; } + private: TTableRef Table_; const TAlterTableParameters Params_; @@ -1713,7 +1680,7 @@ TNodePtr BuildAlterTable(TPosition pos, const TTableRef& tr, const TAlterTablePa return new TAlterTableNode(pos, tr, params, scoped); } -class TDropTableNode final : public TAstListNode { +class TDropTableNode final: public TAstListNode { public: TDropTableNode(TPosition pos, const TTableRef& tr, bool missingOk, ETableType tableType, TScopedStatePtr scoped) : TAstListNode(pos) @@ -1749,10 +1716,9 @@ public: } Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Table_.Service), Scoped_->WrapCluster(Table_.Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Table_.Service), Scoped_->WrapCluster(Table_.Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, FakeSource_.Get()); } @@ -1760,6 +1726,7 @@ public: TPtr DoClone() const final { return {}; } + private: TTableRef Table_; ETableType TableType_; @@ -1772,7 +1739,6 @@ TNodePtr BuildDropTable(TPosition pos, const TTableRef& tr, bool missingOk, ETab return new TDropTableNode(pos, tr, missingOk, tableType, scoped); } - static INode::TPtr CreateConsumerDesc(const TTopicConsumerDescription& desc, const INode& node, bool alter) { auto settings = node.Y(); if (desc.Settings.Important) { @@ -1789,7 +1755,7 @@ static INode::TPtr CreateConsumerDesc(const TTopicConsumerDescription& desc, con if (const auto& readFromTs = desc.Settings.ReadFromTs) { if (readFromTs.IsSet()) { settings = node.L(settings, node.Q(node.Y(node.Q("setReadFromTs"), readFromTs.GetValueSet()))); - } else { + } else { YQL_ENSURE(alter, "Cannot reset on create"); settings = node.L(settings, node.Q(node.Y(node.Q("resetReadFromTs"), node.Q(node.Y())))); } @@ -1803,12 +1769,11 @@ static INode::TPtr CreateConsumerDesc(const TTopicConsumerDescription& desc, con } } return node.Y( - node.Q(node.Y(node.Q("name"), BuildQuotedAtom(desc.Name.Pos, desc.Name.Name))), - node.Q(node.Y(node.Q("settings"), node.Q(settings))) - ); + node.Q(node.Y(node.Q("name"), BuildQuotedAtom(desc.Name.Pos, desc.Name.Name))), + node.Q(node.Y(node.Q("settings"), node.Q(settings)))); } -class TCreateTopicNode final : public TAstListNode { +class TCreateTopicNode final: public TAstListNode { public: TCreateTopicNode(TPosition pos, const TTopicRef& tr, const TCreateTopicParameters& params, TScopedStatePtr scoped) : TAstListNode(pos) @@ -1848,13 +1813,13 @@ public: if (Params_.TopicSettings.IsSet()) { auto settings = Y(); -#define INSERT_TOPIC_SETTING(NAME) \ - if (const auto& NAME##Val = Params_.TopicSettings.NAME) { \ - if (NAME##Val.IsSet()) { \ - settings = L(settings, Q(Y(Q(Y_STRINGIZE(set##NAME)), NAME##Val.GetValueSet()))); \ - } else { \ - YQL_ENSURE(false, "Can't reset on create"); \ - } \ +#define INSERT_TOPIC_SETTING(NAME) \ + if (const auto& NAME##Val = Params_.TopicSettings.NAME) { \ + if (NAME##Val.IsSet()) { \ + settings = L(settings, Q(Y(Q(Y_STRINGIZE(set##NAME)), NAME##Val.GetValueSet()))); \ + } else { \ + YQL_ENSURE(false, "Can't reset on create"); \ + } \ } INSERT_TOPIC_SETTING(MaxPartitions) @@ -1874,13 +1839,11 @@ public: opts = L(opts, Q(Y(Q("topicSettings"), Q(settings)))); } - Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, TString(KikimrProviderName)), - Scoped_->WrapCluster(Topic_.Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, TString(KikimrProviderName)), + Scoped_->WrapCluster(Topic_.Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } @@ -1888,6 +1851,7 @@ public: TPtr DoClone() const final { return {}; } + private: const TTopicRef Topic_; const TCreateTopicParameters Params_; @@ -1895,12 +1859,11 @@ private: }; TNodePtr BuildCreateTopic( - TPosition pos, const TTopicRef& tr, const TCreateTopicParameters& params, TScopedStatePtr scoped -){ + TPosition pos, const TTopicRef& tr, const TCreateTopicParameters& params, TScopedStatePtr scoped) { return new TCreateTopicNode(pos, tr, params, scoped); } -class TAlterTopicNode final : public TAstListNode { +class TAlterTopicNode final: public TAstListNode { public: TAlterTopicNode(TPosition pos, const TTopicRef& tr, const TAlterTopicParameters& params, TScopedStatePtr scoped) : TAstListNode(pos) @@ -1970,13 +1933,13 @@ public: if (Params_.TopicSettings.IsSet()) { auto settings = Y(); -#define INSERT_TOPIC_SETTING(NAME) \ - if (const auto& NAME##Val = Params_.TopicSettings.NAME) { \ - if (NAME##Val.IsSet()) { \ - settings = L(settings, Q(Y(Q(Y_STRINGIZE(set##NAME)), NAME##Val.GetValueSet()))); \ - } else { \ - settings = L(settings, Q(Y(Q(Y_STRINGIZE(reset##NAME)), Y()))); \ - } \ +#define INSERT_TOPIC_SETTING(NAME) \ + if (const auto& NAME##Val = Params_.TopicSettings.NAME) { \ + if (NAME##Val.IsSet()) { \ + settings = L(settings, Q(Y(Q(Y_STRINGIZE(set##NAME)), NAME##Val.GetValueSet()))); \ + } else { \ + settings = L(settings, Q(Y(Q(Y_STRINGIZE(reset##NAME)), Y()))); \ + } \ } INSERT_TOPIC_SETTING(MaxPartitions) @@ -1996,13 +1959,11 @@ public: opts = L(opts, Q(Y(Q("topicSettings"), Q(settings)))); } - Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, TString(KikimrProviderName)), - Scoped_->WrapCluster(Topic_.Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, TString(KikimrProviderName)), + Scoped_->WrapCluster(Topic_.Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } @@ -2010,6 +1971,7 @@ public: TPtr DoClone() const final { return {}; } + private: const TTopicRef Topic_; const TAlterTopicParameters Params_; @@ -2017,12 +1979,11 @@ private: }; TNodePtr BuildAlterTopic( - TPosition pos, const TTopicRef& tr, const TAlterTopicParameters& params, TScopedStatePtr scoped -){ + TPosition pos, const TTopicRef& tr, const TAlterTopicParameters& params, TScopedStatePtr scoped) { return new TAlterTopicNode(pos, tr, params, scoped); } -class TDropTopicNode final : public TAstListNode { +class TDropTopicNode final: public TAstListNode { public: TDropTopicNode(TPosition pos, const TTopicRef& tr, const TDropTopicParameters& params, TScopedStatePtr scoped) : TAstListNode(pos) @@ -2045,13 +2006,11 @@ public: TString mode = Params_.MissingOk ? "drop_if_exists" : "drop"; opts = L(opts, Q(Y(Q("mode"), Q(mode)))); - Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, TString(KikimrProviderName)), - Scoped_->WrapCluster(Topic_.Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, TString(KikimrProviderName)), + Scoped_->WrapCluster(Topic_.Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, FakeSource_.Get()); } @@ -2059,6 +2018,7 @@ public: TPtr DoClone() const final { return {}; } + private: TTopicRef Topic_; TDropTopicParameters Params_; @@ -2070,7 +2030,7 @@ TNodePtr BuildDropTopic(TPosition pos, const TTopicRef& tr, const TDropTopicPara return new TDropTopicNode(pos, tr, params, scoped); } -class TControlUser final : public TAstListNode { +class TControlUser final: public TAstListNode { public: TControlUser(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TMaybe<TUserParameters>& params, TScopedStatePtr scoped, bool IsCreateUser) : TAstListNode(pos) @@ -2100,16 +2060,15 @@ public: TNodePtr cluster = Scoped_->WrapCluster(Cluster_, ctx); - if (!name->Init(ctx, FakeSource_.Get()) - || !cluster->Init(ctx, FakeSource_.Get()) - || password && !password->Init(ctx, FakeSource_.Get()) - || hash && !hash->Init(ctx, FakeSource_.Get()) - ) + if (!name->Init(ctx, FakeSource_.Get()) || + !cluster->Init(ctx, FakeSource_.Get()) || + (password && !password->Init(ctx, FakeSource_.Get())) || + (hash && !hash->Init(ctx, FakeSource_.Get()))) { return false; } - auto options = Y(Q(Y(Q("mode"), Q(IsCreateUser_ ? "createUser" : "alterUser")))) ; + auto options = Y(Q(Y(Q("mode"), Q(IsCreateUser_ ? "createUser" : "alterUser")))); TVector<TNodePtr> roles; if (Params_ && !Params_->Roles.empty()) { @@ -2142,10 +2101,9 @@ public: } Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), cluster)), - Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("role"), Y("String", name)))), Y("Void"), Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), cluster)), + Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("role"), Y("String", name)))), Y("Void"), Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, FakeSource_.Get()); } @@ -2164,18 +2122,18 @@ private: bool IsCreateUser_; }; -TNodePtr BuildControlUser( TPosition pos, - const TString& service, - const TDeferredAtom& cluster, - const TDeferredAtom& name, - const TMaybe<TUserParameters>& params, - TScopedStatePtr scoped, - bool isCreateUser) +TNodePtr BuildControlUser(TPosition pos, + const TString& service, + const TDeferredAtom& cluster, + const TDeferredAtom& name, + const TMaybe<TUserParameters>& params, + TScopedStatePtr scoped, + bool isCreateUser) { return new TControlUser(pos, service, cluster, name, params, scoped, isCreateUser); } -class TCreateGroup final : public TAstListNode { +class TCreateGroup final: public TAstListNode { public: TCreateGroup(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TMaybe<TCreateGroupParameters>& params, TScopedStatePtr scoped) : TAstListNode(pos) @@ -2207,10 +2165,9 @@ public: TNodePtr cluster = Scoped_->WrapCluster(Cluster_, ctx); Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), cluster)), - Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("role"), Y("String", Name_.Build())))), Y("Void"), Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), cluster)), + Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("role"), Y("String", Name_.Build())))), Y("Void"), Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, FakeSource_.Get()); } @@ -2232,7 +2189,7 @@ TNodePtr BuildCreateGroup(TPosition pos, const TString& service, const TDeferred return new TCreateGroup(pos, service, cluster, name, params, scoped); } -class TAlterSequence final : public TAstListNode { +class TAlterSequence final: public TAstListNode { public: TAlterSequence(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TString& id, const TSequenceParameters& params, TScopedStatePtr scoped) : TAstListNode(pos) @@ -2310,11 +2267,10 @@ public: } Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, TString(KikimrProviderName)), - Scoped_->WrapCluster(Cluster_, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("sequence"), Y("String", BuildQuotedAtom(Pos_, Id_))))), Y("Void"), Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, TString(KikimrProviderName)), + Scoped_->WrapCluster(Cluster_, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("sequence"), Y("String", BuildQuotedAtom(Pos_, Id_))))), Y("Void"), Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } @@ -2322,6 +2278,7 @@ public: TPtr DoClone() const final { return {}; } + private: const TString Service_; TDeferredAtom Cluster_; @@ -2336,7 +2293,7 @@ TNodePtr BuildAlterSequence(TPosition pos, const TString& service, const TDeferr return new TAlterSequence(pos, service, cluster, id, params, scoped); } -class TRenameRole final : public TAstListNode { +class TRenameRole final: public TAstListNode { public: TRenameRole(TPosition pos, bool isUser, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TDeferredAtom& newName, TScopedStatePtr scoped) : TAstListNode(pos) @@ -2368,10 +2325,9 @@ public: options = L(options, Q(Y(Q("newName"), newName))); Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), cluster)), - Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("role"), Y("String", name)))), Y("Void"), Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), cluster)), + Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("role"), Y("String", name)))), Y("Void"), Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, FakeSource_.Get()); } @@ -2379,6 +2335,7 @@ public: TPtr DoClone() const final { return {}; } + private: const bool IsUser_; const TString Service_; @@ -2399,7 +2356,7 @@ TNodePtr BuildRenameGroup(TPosition pos, const TString& service, const TDeferred return new TRenameRole(pos, isUser, service, cluster, name, newName, scoped); } -class TAlterGroup final : public TAstListNode { +class TAlterGroup final: public TAstListNode { public: TAlterGroup(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TVector<TDeferredAtom>& toChange, bool isDrop, TScopedStatePtr scoped) : TAstListNode(pos) @@ -2435,10 +2392,9 @@ public: options = L(options, Q(Y(Q("roles"), Q(new TAstListNodeImpl(Pos_, std::move(toChange)))))); Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), cluster)), - Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("role"), Y("String", name)))), Y("Void"), Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), cluster)), + Y("let", "world", Y(TString(WriteName), "world", "sink", Y("Key", Q(Y(Q("role"), Y("String", name)))), Y("Void"), Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, FakeSource_.Get()); } @@ -2446,6 +2402,7 @@ public: TPtr DoClone() const final { return {}; } + private: const TString Service_; TDeferredAtom Cluster_; @@ -2457,12 +2414,12 @@ private: }; TNodePtr BuildAlterGroup(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TVector<TDeferredAtom>& toChange, bool isDrop, - TScopedStatePtr scoped) + TScopedStatePtr scoped) { return new TAlterGroup(pos, service, cluster, name, toChange, isDrop, scoped); } -class TDropRoles final : public TAstListNode { +class TDropRoles final: public TAstListNode { public: TDropRoles(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TVector<TDeferredAtom>& toDrop, bool isUser, bool missingOk, TScopedStatePtr scoped) : TAstListNode(pos) @@ -2485,9 +2442,9 @@ public: return false; } - const char* mode = IsUser_ ? - (MissingOk_ ? "dropUserIfExists" : "dropUser") : - (MissingOk_ ? "dropGroupIfExists" : "dropGroup"); + const char* mode = IsUser_ + ? (MissingOk_ ? "dropUserIfExists" : "dropUser") + : (MissingOk_ ? "dropGroupIfExists" : "dropGroup"); auto options = Y(Q(Y(Q("mode"), Q(mode)))); @@ -2509,6 +2466,7 @@ public: TPtr DoClone() const final { return {}; } + private: const TString Service_; TDeferredAtom Cluster_; @@ -2520,22 +2478,22 @@ private: }; TNodePtr BuildUpsertObjectOperation(TPosition pos, const TString& objectId, const TString& typeId, - std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context) { + std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context) { return new TUpsertObject(pos, objectId, typeId, context, std::move(features)); } TNodePtr BuildCreateObjectOperation(TPosition pos, const TString& objectId, const TString& typeId, - bool existingOk, bool replaceIfExists, std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context) { + bool existingOk, bool replaceIfExists, std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context) { return new TCreateObject(pos, objectId, typeId, context, std::move(features), existingOk, replaceIfExists); } TNodePtr BuildAlterObjectOperation(TPosition pos, const TString& secretId, const TString& typeId, - bool missingOk, std::map<TString, TDeferredAtom>&& features, std::set<TString>&& featuresToReset, const TObjectOperatorContext& context) { + bool missingOk, std::map<TString, TDeferredAtom>&& features, std::set<TString>&& featuresToReset, const TObjectOperatorContext& context) { return new TAlterObject(pos, secretId, typeId, context, std::move(features), std::move(featuresToReset), missingOk); } TNodePtr BuildDropObjectOperation(TPosition pos, const TString& secretId, const TString& typeId, - bool missingOk, std::map<TString, TDeferredAtom>&& options, const TObjectOperatorContext& context) { + bool missingOk, std::map<TString, TDeferredAtom>&& options, const TObjectOperatorContext& context) { return new TDropObject(pos, secretId, typeId, context, std::move(options), missingOk); } @@ -2543,7 +2501,7 @@ TNodePtr BuildDropRoles(TPosition pos, const TString& service, const TDeferredAt return new TDropRoles(pos, service, cluster, toDrop, isUser, missingOk, scoped); } -class TPermissionsAction final : public TAstListNode { +class TPermissionsAction final: public TAstListNode { public: struct TPermissionParameters { TString PermissionAction; @@ -2629,9 +2587,9 @@ TNodePtr BuildGrantPermissions(TPosition pos, const TString& service, const TDef service, cluster, {.PermissionAction = "grant", - .Permissions = permissions, - .SchemaPaths = schemaPaths, - .RoleNames = roleNames}, + .Permissions = permissions, + .SchemaPaths = schemaPaths, + .RoleNames = roleNames}, scoped); } @@ -2640,16 +2598,15 @@ TNodePtr BuildRevokePermissions(TPosition pos, const TString& service, const TDe service, cluster, {.PermissionAction = "revoke", - .Permissions = permissions, - .SchemaPaths = schemaPaths, - .RoleNames = roleNames}, + .Permissions = permissions, + .SchemaPaths = schemaPaths, + .RoleNames = roleNames}, scoped); } class TAsyncReplication - : public TAstListNode - , protected TObjectOperatorContext -{ + : public TAstListNode, + protected TObjectOperatorContext { protected: virtual INode::TPtr FillOptions(INode::TPtr options) const = 0; @@ -2669,10 +2626,9 @@ public: auto options = FillOptions(Y(Q(Y(Q("mode"), Q(Mode_))))); Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } @@ -2687,12 +2643,12 @@ private: }; // TAsyncReplication -class TCreateAsyncReplication final : public TAsyncReplication { +class TCreateAsyncReplication final: public TAsyncReplication { public: explicit TCreateAsyncReplication(TPosition pos, const TString& id, - std::vector<std::pair<TString, TString>>&& targets, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context) + std::vector<std::pair<TString, TString>>&& targets, + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context) : TAsyncReplication(pos, id, "create", context) , Targets_(std::move(targets)) , Settings_(std::move(settings)) @@ -2734,14 +2690,14 @@ private: }; // TCreateAsyncReplication TNodePtr BuildCreateAsyncReplication(TPosition pos, const TString& id, - std::vector<std::pair<TString, TString>>&& targets, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context) + std::vector<std::pair<TString, TString>>&& targets, + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context) { return new TCreateAsyncReplication(pos, id, std::move(targets), std::move(settings), context); } -class TDropAsyncReplication final : public TAsyncReplication { +class TDropAsyncReplication final: public TAsyncReplication { public: explicit TDropAsyncReplication(TPosition pos, const TString& id, bool cascade, const TObjectOperatorContext& context) : TAsyncReplication(pos, id, cascade ? "dropCascade" : "drop", context) @@ -2759,11 +2715,11 @@ TNodePtr BuildDropAsyncReplication(TPosition pos, const TString& id, bool cascad return new TDropAsyncReplication(pos, id, cascade, context); } -class TAlterAsyncReplication final : public TAsyncReplication { +class TAlterAsyncReplication final: public TAsyncReplication { public: explicit TAlterAsyncReplication(TPosition pos, const TString& id, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context) + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context) : TAsyncReplication(pos, id, "alter", context) , Settings_(std::move(settings)) { @@ -2792,16 +2748,15 @@ private: }; // TAlterAsyncReplication TNodePtr BuildAlterAsyncReplication(TPosition pos, const TString& id, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context) + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context) { return new TAlterAsyncReplication(pos, id, std::move(settings), context); } class TTransfer - : public TAstListNode - , protected TObjectOperatorContext -{ + : public TAstListNode, + protected TObjectOperatorContext { protected: virtual INode::TPtr FillOptions(INode::TPtr options) const = 0; @@ -2821,10 +2776,9 @@ public: auto options = FillOptions(Y(Q(Y(Q("mode"), Q(Mode_))))); Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } @@ -2842,9 +2796,9 @@ private: class TCreateTransfer final: public TTransfer { public: explicit TCreateTransfer(TPosition pos, const TString& id, const TString&& source, const TString&& target, - const TString&& transformLambda, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context) + const TString&& transformLambda, + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context) : TTransfer(pos, id, "create", context) , Source_(std::move(source)) , Target_(std::move(target)) @@ -2883,9 +2837,9 @@ private: }; // TCreateTransfer TNodePtr BuildCreateTransfer(TPosition pos, const TString& id, const TString&& source, const TString&& target, - const TString&& transformLambda, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context) + const TString&& transformLambda, + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context) { return new TCreateTransfer(pos, id, std::move(source), std::move(target), std::move(transformLambda), std::move(settings), context); } @@ -2911,8 +2865,8 @@ TNodePtr BuildDropTransfer(TPosition pos, const TString& id, bool cascade, const class TAlterTransfer final: public TTransfer { public: explicit TAlterTransfer(TPosition pos, const TString& id, std::optional<TString>&& transformLambda, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context) + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context) : TTransfer(pos, id, "alter", context) , TransformLambda_(std::move(transformLambda)) , Settings_(std::move(settings)) @@ -2945,23 +2899,21 @@ private: }; // TAlterTransfer TNodePtr BuildAlterTransfer(TPosition pos, const TString& id, std::optional<TString>&& transformLambda, - std::map<TString, TNodePtr>&& settings, - const TObjectOperatorContext& context) + std::map<TString, TNodePtr>&& settings, + const TObjectOperatorContext& context) { return new TAlterTransfer(pos, id, std::move(transformLambda), std::move(settings), context); } -static const TMap<EWriteColumnMode, TString> columnModeToStrMapMR { +static const TMap<EWriteColumnMode, TString> columnModeToStrMapMR{ {EWriteColumnMode::Default, ""}, {EWriteColumnMode::Insert, "append"}, - {EWriteColumnMode::Renew, "renew"} -}; + {EWriteColumnMode::Renew, "renew"}}; -static const TMap<EWriteColumnMode, TString> columnModeToStrMapStat { - {EWriteColumnMode::Upsert, "upsert"} -}; +static const TMap<EWriteColumnMode, TString> columnModeToStrMapStat{ + {EWriteColumnMode::Upsert, "upsert"}}; -static const TMap<EWriteColumnMode, TString> columnModeToStrMapKikimr { +static const TMap<EWriteColumnMode, TString> columnModeToStrMapKikimr{ {EWriteColumnMode::Default, ""}, {EWriteColumnMode::Insert, "insert_abort"}, {EWriteColumnMode::InsertOrAbort, "insert_abort"}, @@ -2975,10 +2927,10 @@ static const TMap<EWriteColumnMode, TString> columnModeToStrMapKikimr { {EWriteColumnMode::DeleteOn, "delete_on"}, }; -class TWriteTableNode final : public TAstListNode { +class TWriteTableNode final: public TAstListNode { public: TWriteTableNode(TPosition pos, const TString& label, const TTableRef& table, EWriteColumnMode mode, - TNodePtr options, TScopedStatePtr scoped) + TNodePtr options, TScopedStatePtr scoped) : TAstListNode(pos) , Label_(label) , Table_(table) @@ -2995,7 +2947,7 @@ public: return false; } - auto getModesMap = [] (const TString& serviceName) -> const TMap<EWriteColumnMode, TString>& { + auto getModesMap = [](const TString& serviceName) -> const TMap<EWriteColumnMode, TString>& { if (serviceName == KikimrProviderName || serviceName == YdbProviderName) { return columnModeToStrMapKikimr; } else if (serviceName == StatProviderName) { @@ -3021,10 +2973,9 @@ public: } Add("block", Q((Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Table_.Service), Scoped_->WrapCluster(Table_.Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Label_, Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - )))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Table_.Service), Scoped_->WrapCluster(Table_.Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Label_, Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")))))); return TAstListNode::DoInit(ctx, src); } @@ -3032,6 +2983,7 @@ public: TPtr DoClone() const final { return {}; } + private: TString Label_; TTableRef Table_; @@ -3041,16 +2993,17 @@ private: }; TNodePtr BuildWriteTable(TPosition pos, const TString& label, const TTableRef& table, EWriteColumnMode mode, TNodePtr options, - TScopedStatePtr scoped) + TScopedStatePtr scoped) { return new TWriteTableNode(pos, label, table, mode, std::move(options), scoped); } -class TClustersSinkOperationBase : public TAstListNode { +class TClustersSinkOperationBase: public TAstListNode { protected: TClustersSinkOperationBase(TPosition pos) : TAstListNode(pos) - {} + { + } virtual TPtr ProduceOperation() = 0; @@ -3067,7 +3020,7 @@ protected: Add("block", Q(block)); return TAstListNode::DoInit(ctx, src); - } + } TPtr DoClone() const final { return {}; @@ -3106,20 +3059,20 @@ TNodePtr BuildRollbackClusters(TPosition pos) { return new TRollbackClustersNode(pos); } -class TWriteResultNode final : public TAstListNode { +class TWriteResultNode final: public TAstListNode { public: TWriteResultNode(TPosition pos, const TString& label, TNodePtr settings) : TAstListNode(pos) , Label_(label) , Settings_(settings) , CommitClusters_(BuildCommitClusters(Pos_)) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { auto block(Y( Y("let", "result_sink", Y("DataSink", Q(TString(ResultProviderName)))), - Y("let", "world", Y(TString(WriteName), "world", "result_sink", Y("Key"), Label_, Q(Settings_))) - )); + Y("let", "world", Y(TString(WriteName), "world", "result_sink", Y("Key"), Label_, Q(Settings_))))); if (ctx.PragmaAutoCommit) { block = L(block, Y("let", "world", CommitClusters_)); } @@ -3132,6 +3085,7 @@ public: TPtr DoClone() const final { return {}; } + private: TString Label_; TNodePtr Settings_; @@ -3142,7 +3096,7 @@ TNodePtr BuildWriteResult(TPosition pos, const TString& label, TNodePtr settings return new TWriteResultNode(pos, label, settings); } -class TYqlProgramNode : public TAstListNode { +class TYqlProgramNode: public TAstListNode { public: TYqlProgramNode(TPosition pos, const TVector<TNodePtr>& blocks, bool topLevel, TScopedStatePtr scoped, bool useSeq) : TAstListNode(pos) @@ -3150,7 +3104,8 @@ public: , TopLevel_(topLevel) , Scoped_(scoped) , UseSeq_(useSeq) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { bool hasError = false; @@ -3159,12 +3114,12 @@ public: if (UseSeq_) { currentWorldsHolder = new TAstListNodeImpl(GetPos()); seqNode = new TAstListNodeImpl(GetPos()); - seqNode->Add("Seq!","world"); + seqNode->Add("Seq!", "world"); } INode* currentWorlds = UseSeq_ ? currentWorldsHolder.Get() : this; auto flushCurrentWorlds = [&](bool changeSeq, bool finish) { - currentWorldsHolder->Add(Y("return","world")); + currentWorldsHolder->Add(Y("return", "world")); auto lambda = BuildLambda(GetPos(), Y("world"), Y("block", Q(currentWorldsHolder))); seqNode->Add(lambda); @@ -3178,12 +3133,12 @@ public: if (changeSeq) { Add(Y("let", "world", seqNode)); seqNode = new TAstListNodeImpl(GetPos()); - seqNode->Add("Seq!","world"); + seqNode->Add("Seq!", "world"); } }; if (TopLevel_) { - for (auto& var: ctx.Variables) { + for (auto& var : ctx.Variables) { if (!var.second.second->Init(ctx, src)) { hasError = true; continue; @@ -3194,26 +3149,24 @@ public: var.second.second)); } - for (const auto& overrideLibrary: ctx.OverrideLibraries) { + for (const auto& overrideLibrary : ctx.OverrideLibraries) { auto node = Y( "override_library", new TAstAtomNodeImpl( std::get<TPosition>(overrideLibrary.second), - overrideLibrary.first, TNodeFlags::ArbitraryContent - )); + overrideLibrary.first, TNodeFlags::ArbitraryContent)); Add(node); } - for (const auto& package: ctx.Packages) { + for (const auto& package : ctx.Packages) { const auto& [url, urlPosition] = std::get<1U>(package.second); auto node = Y( "package", new TAstAtomNodeImpl( std::get<TPosition>(package.second), package.first, - TNodeFlags::ArbitraryContent - ), + TNodeFlags::ArbitraryContent), new TAstAtomNodeImpl(urlPosition, url, TNodeFlags::ArbitraryContent)); if (const auto& tokenWithPosition = std::get<2U>(package.second)) { @@ -3257,7 +3210,7 @@ public: } if (!ctx.CompactNamedExprs) { - for (auto& nodes: Scoped_->NamedNodes) { + for (auto& nodes : Scoped_->NamedNodes) { if (src || ctx.Exports.contains(nodes.first)) { auto& item = nodes.second.front(); if (!item->Node->Init(ctx, src)) { @@ -3279,38 +3232,38 @@ public: for (const auto& warningPragma : ctx.WarningPolicy.GetRules()) { currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "Warning"), BuildQuotedAtom(Pos_, warningPragma.GetPattern()), - BuildQuotedAtom(Pos_, to_lower(ToString(warningPragma.GetAction())))))); + BuildQuotedAtom(Pos_, "Warning"), BuildQuotedAtom(Pos_, warningPragma.GetPattern()), + BuildQuotedAtom(Pos_, to_lower(ToString(warningPragma.GetAction())))))); } if (ctx.RuntimeLogLevel) { currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "RuntimeLogLevel"), BuildQuotedAtom(Pos_, ctx.RuntimeLogLevel)))); + BuildQuotedAtom(Pos_, "RuntimeLogLevel"), BuildQuotedAtom(Pos_, ctx.RuntimeLogLevel)))); } if (ctx.ResultSizeLimit > 0) { currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", resultSink, - BuildQuotedAtom(Pos_, "SizeLimit"), BuildQuotedAtom(Pos_, ToString(ctx.ResultSizeLimit))))); + BuildQuotedAtom(Pos_, "SizeLimit"), BuildQuotedAtom(Pos_, ToString(ctx.ResultSizeLimit))))); } if (!ctx.PragmaPullUpFlatMapOverJoin) { currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "DisablePullUpFlatMapOverJoin")))); + BuildQuotedAtom(Pos_, "DisablePullUpFlatMapOverJoin")))); } if (ctx.FilterPushdownOverJoinOptionalSide) { currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "FilterPushdownOverJoinOptionalSide")))); + BuildQuotedAtom(Pos_, "FilterPushdownOverJoinOptionalSide")))); } if (!ctx.RotateJoinTree) { currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "RotateJoinTree"), BuildQuotedAtom(Pos_, "false")))); + BuildQuotedAtom(Pos_, "RotateJoinTree"), BuildQuotedAtom(Pos_, "false")))); } if (ctx.DiscoveryMode) { currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "DiscoveryMode")))); + BuildQuotedAtom(Pos_, "DiscoveryMode")))); } if (ctx.DqEngineEnable) { @@ -3321,12 +3274,12 @@ public: mode = "force"; } currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "DqEngine"), BuildQuotedAtom(Pos_, mode)))); + BuildQuotedAtom(Pos_, "DqEngine"), BuildQuotedAtom(Pos_, mode)))); } if (ctx.CostBasedOptimizer) { currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "CostBasedOptimizer"), BuildQuotedAtom(Pos_, ctx.CostBasedOptimizer)))); + BuildQuotedAtom(Pos_, "CostBasedOptimizer"), BuildQuotedAtom(Pos_, ctx.CostBasedOptimizer)))); } if (ctx.JsonQueryReturnsJsonDocument.Defined()) { @@ -3340,28 +3293,28 @@ public: if (ctx.OrderedColumns) { currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "OrderedColumns")))); + BuildQuotedAtom(Pos_, "OrderedColumns")))); } if (ctx.DeriveColumnOrder) { currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "DeriveColumnOrder")))); + BuildQuotedAtom(Pos_, "DeriveColumnOrder")))); } if (ctx.PqReadByRtmrCluster) { auto pqSourceAll = Y("DataSource", BuildQuotedAtom(Pos_, TString(PqProviderName)), BuildQuotedAtom(Pos_, "$all")); currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", pqSourceAll, - BuildQuotedAtom(Pos_, "Attr"), BuildQuotedAtom(Pos_, "PqReadByRtmrCluster_"), BuildQuotedAtom(Pos_, ctx.PqReadByRtmrCluster)))); + BuildQuotedAtom(Pos_, "Attr"), BuildQuotedAtom(Pos_, "PqReadByRtmrCluster_"), BuildQuotedAtom(Pos_, ctx.PqReadByRtmrCluster)))); auto rtmrSourceAll = Y("DataSource", BuildQuotedAtom(Pos_, TString(RtmrProviderName)), BuildQuotedAtom(Pos_, "$all")); currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", rtmrSourceAll, - BuildQuotedAtom(Pos_, "Attr"), BuildQuotedAtom(Pos_, "PqReadByRtmrCluster_"), BuildQuotedAtom(Pos_, ctx.PqReadByRtmrCluster)))); + BuildQuotedAtom(Pos_, "Attr"), BuildQuotedAtom(Pos_, "PqReadByRtmrCluster_"), BuildQuotedAtom(Pos_, ctx.PqReadByRtmrCluster)))); if (ctx.PqReadByRtmrCluster != "dq") { // set any dynamic settings for particular RTMR cluster for CommitAll! auto rtmrSource = Y("DataSource", BuildQuotedAtom(Pos_, TString(RtmrProviderName)), BuildQuotedAtom(Pos_, ctx.PqReadByRtmrCluster)); currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", rtmrSource, - BuildQuotedAtom(Pos_, "Attr"), BuildQuotedAtom(Pos_, "Dummy_"), BuildQuotedAtom(Pos_, "1")))); + BuildQuotedAtom(Pos_, "Attr"), BuildQuotedAtom(Pos_, "Dummy_"), BuildQuotedAtom(Pos_, "1")))); } } @@ -3377,17 +3330,17 @@ public: if (ctx.BlockEngineEnable) { TString mode = ctx.BlockEngineForce ? "force" : "auto"; currentWorlds->Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "BlockEngine"), BuildQuotedAtom(Pos_, mode)))); + BuildQuotedAtom(Pos_, "BlockEngine"), BuildQuotedAtom(Pos_, mode)))); } if (ctx.Engine) { Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "Engine"), BuildQuotedAtom(Pos_, *ctx.Engine)))); + BuildQuotedAtom(Pos_, "Engine"), BuildQuotedAtom(Pos_, *ctx.Engine)))); } if (ctx.DebugPositions) { Add(Y("let", "world", Y(TString(ConfigureName), "world", configSource, - BuildQuotedAtom(Pos_, "DebugPositions")))); + BuildQuotedAtom(Pos_, "DebugPositions")))); } if (ctx.DirectRowDependsOn.Defined()) { @@ -3397,7 +3350,7 @@ public: } } - for (auto& block: Blocks_) { + for (auto& block : Blocks_) { if (block->SubqueryAlias()) { continue; } @@ -3423,7 +3376,7 @@ public: flushCurrentWorlds(false, false); } - for (auto& block: Blocks_) { + for (auto& block : Blocks_) { const auto subqueryAliasPtr = block->SubqueryAlias(); if (subqueryAliasPtr) { if (block->UsedSubquery()) { @@ -3465,12 +3418,12 @@ public: } decltype(Nodes_) imports; - for (const auto& [alias, path]: ctx.RequiredModules) { + for (const auto& [alias, path] : ctx.RequiredModules) { imports.push_back(Y("import", alias, BuildQuotedAtom(Pos_, path))); } Nodes_.insert(Nodes_.begin(), std::make_move_iterator(imports.begin()), std::make_move_iterator(imports.end())); - for (const auto& symbol: ctx.Exports) { + for (const auto& symbol : ctx.Exports) { if (ctx.CompactNamedExprs) { auto node = Scoped_->LookupNode(symbol); YQL_ENSURE(node); @@ -3494,6 +3447,7 @@ public: TPtr DoClone() const final { return {}; } + private: TVector<TNodePtr> Blocks_; const bool TopLevel_; @@ -3505,7 +3459,7 @@ TNodePtr BuildQuery(TPosition pos, const TVector<TNodePtr>& blocks, bool topLeve return new TYqlProgramNode(pos, blocks, topLevel, scoped, useSeq); } -class TPragmaNode final : public INode { +class TPragmaNode final: public INode { public: TPragmaNode(TPosition pos, const TString& prefix, const TString& name, const TVector<TDeferredAtom>& values, bool valueDefault) : INode(pos) @@ -3542,18 +3496,15 @@ public: for (ui32 i = 0; i < Values_.size(); ++i) { Node_ = L(Node_, Values_[i].Build()); } - } - else if (Name_ == TStringBuf("AddFileByUrl") || Name_ == TStringBuf("SetFileOption") || Name_ == TStringBuf("AddFolderByUrl") || Name_ == TStringBuf("ImportUdfs") || Name_ == TStringBuf("SetPackageVersion")) { + } else if (Name_ == TStringBuf("AddFileByUrl") || Name_ == TStringBuf("SetFileOption") || Name_ == TStringBuf("AddFolderByUrl") || Name_ == TStringBuf("ImportUdfs") || Name_ == TStringBuf("SetPackageVersion")) { Node_ = L(Node_, BuildQuotedAtom(Pos_, Name_)); for (ui32 i = 0; i < Values_.size(); ++i) { Node_ = L(Node_, Values_[i].Build()); } - } - else if (Name_ == TStringBuf("auth")) { + } else if (Name_ == TStringBuf("auth")) { Node_ = L(Node_, BuildQuotedAtom(Pos_, "Auth")); Node_ = L(Node_, Values_.empty() ? BuildQuotedAtom(Pos_, TString()) : Values_.front().Build()); - } - else { + } else { Node_ = L(Node_, BuildQuotedAtom(Pos_, "Attr")); Node_ = L(Node_, BuildQuotedAtom(Pos_, Name_)); if (!ValueDefault_) { @@ -3589,7 +3540,7 @@ TNodePtr BuildPragma(TPosition pos, const TString& prefix, const TString& name, return new TPragmaNode(pos, prefix, name, values, valueDefault); } -class TSqlLambda final : public TAstListNode { +class TSqlLambda final: public TAstListNode { public: TSqlLambda(TPosition pos, TVector<TString>&& args, TVector<TNodePtr>&& exprSeq) : TAstListNode(pos) @@ -3601,7 +3552,7 @@ public: bool DoInit(TContext& ctx, ISource* src) override { Y_UNUSED(src); - for (auto& exprPtr: ExprSeq_) { + for (auto& exprPtr : ExprSeq_) { if (!exprPtr->Init(ctx, FakeSource_.Get())) { return {}; } @@ -3617,7 +3568,7 @@ public: } body = Y("block", Q(L(body, Y("return", *end)))); auto args = Y(); - for (const auto& arg: Args_) { + for (const auto& arg : Args_) { args = L(args, BuildAtom(GetPos(), arg)); } Add("lambda", Q(args), body); @@ -3642,7 +3593,7 @@ TNodePtr BuildSqlLambda(TPosition pos, TVector<TString>&& args, TVector<TNodePtr return new TSqlLambda(pos, std::move(args), std::move(exprSeq)); } -class TWorldIf final : public TAstListNode { +class TWorldIf final: public TAstListNode { public: TWorldIf(TPosition pos, TNodePtr predicate, TNodePtr thenNode, TNodePtr elseNode, bool isEvaluate) : TAstListNode(pos) @@ -3656,7 +3607,7 @@ public: bool DoInit(TContext& ctx, ISource* src) override { if (!Predicate_->Init(ctx, FakeSource_.Get())) { - return{}; + return {}; } Add(IsEvaluate_ ? "EvaluateIf!" : "If!"); Add("world"); @@ -3664,13 +3615,13 @@ public: Add(IsEvaluate_ ? Y("EvaluateExpr", Y("EnsureType", coalesced, Y("DataType", Q("Bool")))) : coalesced); if (!ThenNode_->Init(ctx, FakeSource_.Get())) { - return{}; + return {}; } Add(ThenNode_); if (ElseNode_) { if (!ElseNode_->Init(ctx, FakeSource_.Get())) { - return{}; + return {}; } Add(ElseNode_); @@ -3695,7 +3646,7 @@ TNodePtr BuildWorldIfNode(TPosition pos, TNodePtr predicate, TNodePtr thenNode, return new TWorldIf(pos, predicate, thenNode, elseNode, isEvaluate); } -class TWorldFor final : public TAstListNode { +class TWorldFor final: public TAstListNode { public: TWorldFor(TPosition pos, TNodePtr list, TNodePtr bodyNode, TNodePtr elseNode, bool isEvaluate, bool isParallel) : TAstListNode(pos) @@ -3710,20 +3661,20 @@ public: bool DoInit(TContext& ctx, ISource* src) override { if (!List_->Init(ctx, FakeSource_.Get())) { - return{}; + return {}; } - Add(TStringBuilder() << (IsEvaluate_ ? "Evaluate": "") << (IsParallel_ ? "Parallel" : "") << "For!"); + Add(TStringBuilder() << (IsEvaluate_ ? "Evaluate" : "") << (IsParallel_ ? "Parallel" : "") << "For!"); Add("world"); Add(IsEvaluate_ ? Y("EvaluateExpr", List_) : List_); if (!BodyNode_->Init(ctx, FakeSource_.Get())) { - return{}; + return {}; } Add(BodyNode_); if (ElseNode_) { if (!ElseNode_->Init(ctx, FakeSource_.Get())) { - return{}; + return {}; } Add(ElseNode_); } @@ -3748,7 +3699,7 @@ TNodePtr BuildWorldForNode(TPosition pos, TNodePtr list, TNodePtr bodyNode, TNod return new TWorldFor(pos, list, bodyNode, elseNode, isEvaluate, isParallel); } -class TAnalyzeNode final : public TAstListNode { +class TAnalyzeNode final: public TAstListNode { public: TAnalyzeNode(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TAnalyzeParams& params, TScopedStatePtr scoped) : TAstListNode(pos) @@ -3771,17 +3722,16 @@ public: auto opts = Y(); auto columns = Y(); - for (const auto& column: Params_.Columns) { + for (const auto& column : Params_.Columns) { columns->Add(Q(column)); } opts->Add(Q(Y(Q("columns"), Q(columns)))); opts->Add(Q(Y(Q("mode"), Q("analyze")))); Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), Scoped_->WrapCluster(Cluster_, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Service_), Scoped_->WrapCluster(Cluster_, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, FakeSource_.Get()); } @@ -3789,6 +3739,7 @@ public: TPtr DoClone() const final { return {}; } + private: TString Service_; TDeferredAtom Cluster_; @@ -3802,7 +3753,7 @@ TNodePtr BuildAnalyze(TPosition pos, const TString& service, const TDeferredAtom return new TAnalyzeNode(pos, service, cluster, params, scoped); } -class TShowCreateNode final : public TAstListNode { +class TShowCreateNode final: public TAstListNode { public: TShowCreateNode(TPosition pos, const TTableRef& tr, const TString& type, TScopedStatePtr scoped) : TAstListNode(pos) @@ -3867,6 +3818,7 @@ public: TPtr DoClone() const final { return {}; } + private: TTableRef Table_; // showCreateTable, showCreateView, ... @@ -3880,21 +3832,22 @@ TNodePtr BuildShowCreate(TPosition pos, const TTableRef& tr, const TString& type } class TBaseBackupCollectionNode - : public TAstListNode - , public TObjectOperatorContext -{ + : public TAstListNode, + public TObjectOperatorContext { using TBase = TAstListNode; + public: TBaseBackupCollectionNode( TPosition pos, const TString& prefix, const TString& objectId, const TObjectOperatorContext& context) - : TBase(pos) - , TObjectOperatorContext(context) - , Prefix_(prefix) - , Id_(objectId) - {} + : TBase(pos) + , TObjectOperatorContext(context) + , Prefix_(prefix) + , Id_(objectId) + { + } bool DoInit(TContext& ctx, ISource* src) final { auto keys = Y("Key"); @@ -3902,10 +3855,9 @@ public: auto options = this->FillOptions(ctx, Y()); Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } @@ -3918,9 +3870,9 @@ protected: }; class TCreateBackupCollectionNode - : public TBaseBackupCollectionNode -{ + : public TBaseBackupCollectionNode { using TBase = TBaseBackupCollectionNode; + public: TCreateBackupCollectionNode( TPosition pos, @@ -3928,9 +3880,10 @@ public: const TString& objectId, const TCreateBackupCollectionParameters& params, const TObjectOperatorContext& context) - : TBase(pos, prefix, objectId, context) - , Params_(params) - {} + : TBase(pos, prefix, objectId, context) + , Params_(params) + { + } virtual INode::TPtr FillOptions(TContext& ctx, INode::TPtr options) const final { options->Add(Q(Y(Q("mode"), Q("create")))); @@ -3963,9 +3916,9 @@ private: }; class TAlterBackupCollectionNode - : public TBaseBackupCollectionNode -{ + : public TBaseBackupCollectionNode { using TBase = TBaseBackupCollectionNode; + public: TAlterBackupCollectionNode( TPosition pos, @@ -3973,9 +3926,10 @@ public: const TString& objectId, const TAlterBackupCollectionParameters& params, const TObjectOperatorContext& context) - : TBase(pos, prefix, objectId, context) - , Params_(params) - {} + : TBase(pos, prefix, objectId, context) + , Params_(params) + { + } virtual INode::TPtr FillOptions(TContext& ctx, INode::TPtr options) const final { options->Add(Q(Y(Q("mode"), Q("alter")))); @@ -4018,9 +3972,9 @@ private: }; class TDropBackupCollectionNode - : public TBaseBackupCollectionNode -{ + : public TBaseBackupCollectionNode { using TBase = TBaseBackupCollectionNode; + public: TDropBackupCollectionNode( TPosition pos, @@ -4028,8 +3982,9 @@ public: const TString& objectId, const TDropBackupCollectionParameters&, const TObjectOperatorContext& context) - : TBase(pos, prefix, objectId, context) - {} + : TBase(pos, prefix, objectId, context) + { + } virtual INode::TPtr FillOptions(TContext&, INode::TPtr options) const final { options->Add(Q(Y(Q("mode"), Q("drop")))); @@ -4074,10 +4029,10 @@ TNodePtr BuildDropBackupCollection( } class TBackupNode final - : public TAstListNode - , public TObjectOperatorContext -{ + : public TAstListNode, + public TObjectOperatorContext { using TBase = TAstListNode; + public: TBackupNode( TPosition pos, @@ -4085,11 +4040,11 @@ public: const TString& id, const TBackupParameters& params, const TObjectOperatorContext& context) - : TBase(pos) - , TObjectOperatorContext(context) - , Prefix_(prefix) - , Id_(id) - , Params_(params) + : TBase(pos) + , TObjectOperatorContext(context) + , Prefix_(prefix) + , Id_(id) + , Params_(params) { Y_UNUSED(Params_); } @@ -4107,10 +4062,9 @@ public: } Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } @@ -4118,6 +4072,7 @@ public: TPtr DoClone() const final { return new TBackupNode(GetPos(), Prefix_, Id_, Params_, *this); } + private: TString Prefix_; TString Id_; @@ -4135,10 +4090,10 @@ TNodePtr BuildBackup( } class TRestoreNode final - : public TAstListNode - , public TObjectOperatorContext -{ + : public TAstListNode, + public TObjectOperatorContext { using TBase = TAstListNode; + public: TRestoreNode( TPosition pos, @@ -4146,11 +4101,11 @@ public: const TString& id, const TRestoreParameters& params, const TObjectOperatorContext& context) - : TBase(pos) - , TObjectOperatorContext(context) - , Prefix_(prefix) - , Id_(id) - , Params_(params) + : TBase(pos) + , TObjectOperatorContext(context) + , Prefix_(prefix) + , Id_(id) + , Params_(params) { Y_UNUSED(Params_); } @@ -4167,10 +4122,9 @@ public: } Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, ServiceId), Scoped_->WrapCluster(Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } @@ -4178,6 +4132,7 @@ public: TPtr DoClone() const final { return new TRestoreNode(GetPos(), Prefix_, Id_, Params_, *this); } + private: TString Prefix_; TString Id_; @@ -4194,22 +4149,22 @@ TNodePtr BuildRestore( return new TRestoreNode(pos, prefix, id, params, context); } -class TSecretNode : public TAstListNode { +class TSecretNode: public TAstListNode { using TBase = TAstListNode; + public: TSecretNode( TPosition pos, const TString& objectId, const TSecretParameters& params, const TObjectOperatorContext& context, - TScopedStatePtr scoped - ) + TScopedStatePtr scoped) : TBase(pos) , Pos_(pos) , ObjectId_(objectId) , Params_(params) , Context_(context) - , Scoped_ (scoped) + , Scoped_(scoped) { } @@ -4219,10 +4174,9 @@ public: const auto options = BuildOptions(); Add("block", Q(Y( - Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Context_.ServiceId), Scoped_->WrapCluster(Context_.Cluster, ctx))), - Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(options))), - Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world")) - ))); + Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos_, Context_.ServiceId), Scoped_->WrapCluster(Context_.Cluster, ctx))), + Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(options))), + Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))))); return TAstListNode::DoInit(ctx, src); } @@ -4259,15 +4213,16 @@ protected: TScopedStatePtr Scoped_; }; -class TCreateSecretNode : public TSecretNode { +class TCreateSecretNode: public TSecretNode { using TBase = TSecretNode; + public: TCreateSecretNode( - TPosition pos, - const TString& objectId, - const TSecretParameters& params, - const TObjectOperatorContext& context, - TScopedStatePtr scoped) + TPosition pos, + const TString& objectId, + const TSecretParameters& params, + const TObjectOperatorContext& context, + TScopedStatePtr scoped) : TBase(pos, objectId, params, context, scoped) { } @@ -4287,20 +4242,20 @@ TNodePtr BuildCreateSecret( const TString& objectId, const TSecretParameters& secretParams, const TObjectOperatorContext& context, - TScopedStatePtr scoped -) { + TScopedStatePtr scoped) { return new TCreateSecretNode(pos, objectId, secretParams, context, scoped); } -class TAlterSecretNode : public TSecretNode { +class TAlterSecretNode: public TSecretNode { using TBase = TSecretNode; + public: TAlterSecretNode( - TPosition pos, - const TString& objectId, - const TSecretParameters& params, - const TObjectOperatorContext& context, - TScopedStatePtr scoped) + TPosition pos, + const TString& objectId, + const TSecretParameters& params, + const TObjectOperatorContext& context, + TScopedStatePtr scoped) : TBase(pos, objectId, params, context, scoped) { } @@ -4320,19 +4275,19 @@ TNodePtr BuildAlterSecret( const TString& objectId, const TSecretParameters& secretParams, const TObjectOperatorContext& context, - TScopedStatePtr scoped -) { + TScopedStatePtr scoped) { return new TAlterSecretNode(pos, objectId, secretParams, context, scoped); } -class TDropSecretNode : public TSecretNode { +class TDropSecretNode: public TSecretNode { using TBase = TSecretNode; + public: TDropSecretNode( - TPosition pos, - const TString& objectId, - const TObjectOperatorContext& context, - TScopedStatePtr scoped) + TPosition pos, + const TString& objectId, + const TObjectOperatorContext& context, + TScopedStatePtr scoped) : TBase(pos, objectId, TSecretParameters{}, context, scoped) { } @@ -4351,8 +4306,7 @@ TNodePtr BuildDropSecret( TPosition pos, const TString& objectId, const TObjectOperatorContext& context, - TScopedStatePtr scoped -) { + TScopedStatePtr scoped) { return new TDropSecretNode(pos, objectId, context, scoped); } diff --git a/yql/essentials/sql/v1/reflect/sql_reflect.cpp b/yql/essentials/sql/v1/reflect/sql_reflect.cpp index 97988d7bb6a..40a8eb70bc6 100644 --- a/yql/essentials/sql/v1/reflect/sql_reflect.cpp +++ b/yql/essentials/sql/v1/reflect/sql_reflect.cpp @@ -9,186 +9,186 @@ namespace NSQLReflect { - const TStringBuf ReflectPrefix = "//!"; - const TStringBuf SectionPrefix = "//! section:"; - const TStringBuf SectionPunctuation = "//! section:punctuation"; - const TStringBuf SectionLetter = "//! section:letter"; - const TStringBuf SectionKeyword = "//! section:keyword"; - const TStringBuf SectionOther = "//! section:other"; - const TStringBuf FragmentPrefix = "fragment "; - - const TStringBuf TLexerGrammar::KeywordBlockByName(const TStringBuf name Y_LIFETIME_BOUND) { - if (name == "TSKIP") { - return "SKIP"; - } - return name; +const TStringBuf ReflectPrefix = "//!"; +const TStringBuf SectionPrefix = "//! section:"; +const TStringBuf SectionPunctuation = "//! section:punctuation"; +const TStringBuf SectionLetter = "//! section:letter"; +const TStringBuf SectionKeyword = "//! section:keyword"; +const TStringBuf SectionOther = "//! section:other"; +const TStringBuf FragmentPrefix = "fragment "; + +const TStringBuf TLexerGrammar::KeywordBlockByName(const TStringBuf name Y_LIFETIME_BOUND) { + if (name == "TSKIP") { + return "SKIP"; } + return name; +} - const TString TLexerGrammar::KeywordNameByBlock(const TStringBuf block) { - if (TCaseInsensitiveStringBuf(block) == "SKIP") { - return "TSKIP"; - } - return ToUpperUTF8(block); +const TString TLexerGrammar::KeywordNameByBlock(const TStringBuf block) { + if (TCaseInsensitiveStringBuf(block) == "SKIP") { + return "TSKIP"; } - - TVector<TString> GetResourceLines(const TStringBuf key) { - TString text; - Y_ENSURE(NResource::FindExact(key, &text)); - - TVector<TString> lines; - Split(text, "\n", lines); - for (auto& line : lines) { - if (!line.empty() && line.back() == '\r') { - line.pop_back(); - } + return ToUpperUTF8(block); +} + +TVector<TString> GetResourceLines(const TStringBuf key) { + TString text; + Y_ENSURE(NResource::FindExact(key, &text)); + + TVector<TString> lines; + Split(text, "\n", lines); + for (auto& line : lines) { + if (!line.empty() && line.back() == '\r') { + line.pop_back(); } - return lines; } + return lines; +} - void Format(TVector<TString>& lines) { - for (size_t i = 0; i < lines.size(); ++i) { - auto& line = lines[i]; +void Format(TVector<TString>& lines) { + for (size_t i = 0; i < lines.size(); ++i) { + auto& line = lines[i]; - StripInPlace(line); - - if (line.StartsWith("//") || (line.Contains(':') && line.Contains(';'))) { - continue; - } + StripInPlace(line); - size_t j = i + 1; - do { - line += lines.at(j); - } while (!lines.at(j++).Contains(';')); - - auto first = std::next(std::begin(lines), i + 1); - auto last = std::next(std::begin(lines), j); - lines.erase(first, last); + if (line.StartsWith("//") || (line.Contains(':') && line.Contains(';'))) { + continue; } - for (auto& line : lines) { - CollapseInPlace(line); - SubstGlobal(line, " ;", ";"); - SubstGlobal(line, " :", ":"); - SubstGlobal(line, " )", ")"); - SubstGlobal(line, "( ", "("); - } - } + size_t j = i + 1; + do { + line += lines.at(j); + } while (!lines.at(j++).Contains(';')); - void Purify(TVector<TString>& lines) { - const auto [first, last] = std::ranges::remove_if(lines, [](const TString& line) { - return (line.StartsWith("//") && !line.StartsWith(ReflectPrefix)) || line.empty(); - }); + auto first = std::next(std::begin(lines), i + 1); + auto last = std::next(std::begin(lines), j); lines.erase(first, last); } - THashMap<TStringBuf, TVector<TString>> GroupBySection(TVector<TString>&& lines) { - TVector<TStringBuf> sections = { - "", - SectionPunctuation, - SectionLetter, - SectionKeyword, - SectionOther, - }; + for (auto& line : lines) { + CollapseInPlace(line); + SubstGlobal(line, " ;", ";"); + SubstGlobal(line, " :", ":"); + SubstGlobal(line, " )", ")"); + SubstGlobal(line, "( ", "("); + } +} + +void Purify(TVector<TString>& lines) { + const auto [first, last] = std::ranges::remove_if(lines, [](const TString& line) { + return (line.StartsWith("//") && !line.StartsWith(ReflectPrefix)) || line.empty(); + }); + lines.erase(first, last); +} + +THashMap<TStringBuf, TVector<TString>> GroupBySection(TVector<TString>&& lines) { + TVector<TStringBuf> sections = { + "", + SectionPunctuation, + SectionLetter, + SectionKeyword, + SectionOther, + }; + + size_t section = 0; + + THashMap<TStringBuf, TVector<TString>> groups; + for (auto& line : lines) { + if (line.StartsWith(SectionPrefix)) { + Y_ENSURE(sections.at(section + 1) == line); + section += 1; + continue; + } - size_t section = 0; + groups[sections.at(section)].emplace_back(std::move(line)); + } - THashMap<TStringBuf, TVector<TString>> groups; - for (auto& line : lines) { - if (line.StartsWith(SectionPrefix)) { - Y_ENSURE(sections.at(section + 1) == line); - section += 1; - continue; - } + groups.erase(""); + groups.erase(SectionLetter); - groups[sections.at(section)].emplace_back(std::move(line)); - } + return groups; +} - groups.erase(""); - groups.erase(SectionLetter); +std::tuple<TString, TString> ParseLexerRule(TString&& line) { + size_t colonPos = line.find(':'); + size_t semiPos = line.rfind(';'); - return groups; - } + Y_ENSURE( + colonPos != TString::npos && + semiPos != TString::npos && + colonPos < semiPos); - std::tuple<TString, TString> ParseLexerRule(TString&& line) { - size_t colonPos = line.find(':'); - size_t semiPos = line.rfind(';'); + TString block = line.substr(colonPos + 2, semiPos - colonPos - 2); + SubstGlobal(block, "\\\\", "\\"); - Y_ENSURE( - colonPos != TString::npos && - semiPos != TString::npos && - colonPos < semiPos); + TString name = std::move(line); + name.resize(colonPos); - TString block = line.substr(colonPos + 2, semiPos - colonPos - 2); - SubstGlobal(block, "\\\\", "\\"); + return std::make_tuple(std::move(name), std::move(block)); +} - TString name = std::move(line); - name.resize(colonPos); +void ParsePunctuationLine(TString&& line, TLexerGrammar& grammar) { + auto [name, block] = ParseLexerRule(std::move(line)); + block = block.erase(std::begin(block)); + block.pop_back(); - return std::make_tuple(std::move(name), std::move(block)); - } + SubstGlobal(block, "\\\'", "\'"); - void ParsePunctuationLine(TString&& line, TLexerGrammar& grammar) { - auto [name, block] = ParseLexerRule(std::move(line)); - block = block.erase(std::begin(block)); - block.pop_back(); + if (!name.StartsWith(FragmentPrefix)) { + grammar.PunctuationNames.emplace(name); + } - SubstGlobal(block, "\\\'", "\'"); + SubstGlobal(name, FragmentPrefix, ""); + grammar.BlockByName.emplace(std::move(name), std::move(block)); +} - if (!name.StartsWith(FragmentPrefix)) { - grammar.PunctuationNames.emplace(name); - } +void ParseKeywordLine(TString&& line, TLexerGrammar& grammar) { + auto [name, block] = ParseLexerRule(std::move(line)); + SubstGlobal(block, "'", ""); + SubstGlobal(block, " ", ""); - SubstGlobal(name, FragmentPrefix, ""); - grammar.BlockByName.emplace(std::move(name), std::move(block)); - } + Y_ENSURE(name == block || (name == "TSKIP" && block == TLexerGrammar::KeywordBlockByName("TSKIP"))); + grammar.KeywordNames.emplace(std::move(name)); +} - void ParseKeywordLine(TString&& line, TLexerGrammar& grammar) { - auto [name, block] = ParseLexerRule(std::move(line)); - SubstGlobal(block, "'", ""); - SubstGlobal(block, " ", ""); +void ParseOtherLine(TString&& line, TLexerGrammar& grammar) { + auto [name, block] = ParseLexerRule(std::move(line)); - Y_ENSURE(name == block || (name == "TSKIP" && block == TLexerGrammar::KeywordBlockByName("TSKIP"))); - grammar.KeywordNames.emplace(std::move(name)); + if (!name.StartsWith(FragmentPrefix)) { + grammar.OtherNames.emplace_back(name); } - void ParseOtherLine(TString&& line, TLexerGrammar& grammar) { - auto [name, block] = ParseLexerRule(std::move(line)); + SubstGlobal(name, FragmentPrefix, ""); + SubstGlobal(block, " -> channel(HIDDEN)", ""); + grammar.BlockByName.emplace(std::move(name), std::move(block)); +} - if (!name.StartsWith(FragmentPrefix)) { - grammar.OtherNames.emplace_back(name); - } +TLexerGrammar LoadLexerGrammar() { + TVector<TString> lines = GetResourceLines("SQLv1Antlr4.g.in"); + Purify(lines); + Format(lines); + Purify(lines); - SubstGlobal(name, FragmentPrefix, ""); - SubstGlobal(block, " -> channel(HIDDEN)", ""); - grammar.BlockByName.emplace(std::move(name), std::move(block)); - } + THashMap<TStringBuf, TVector<TString>> sections; + sections = GroupBySection(std::move(lines)); + + TLexerGrammar grammar; - TLexerGrammar LoadLexerGrammar() { - TVector<TString> lines = GetResourceLines("SQLv1Antlr4.g.in"); - Purify(lines); - Format(lines); - Purify(lines); - - THashMap<TStringBuf, TVector<TString>> sections; - sections = GroupBySection(std::move(lines)); - - TLexerGrammar grammar; - - for (auto& [section, lines] : sections) { - for (auto& line : lines) { - if (section == SectionPunctuation) { - ParsePunctuationLine(std::move(line), grammar); - } else if (section == SectionKeyword) { - ParseKeywordLine(std::move(line), grammar); - } else if (section == SectionOther) { - ParseOtherLine(std::move(line), grammar); - } else { - Y_ABORT("Unexpected section %s", section); - } + for (auto& [section, lines] : sections) { + for (auto& line : lines) { + if (section == SectionPunctuation) { + ParsePunctuationLine(std::move(line), grammar); + } else if (section == SectionKeyword) { + ParseKeywordLine(std::move(line), grammar); + } else if (section == SectionOther) { + ParseOtherLine(std::move(line), grammar); + } else { + Y_ABORT("Unexpected section %s", section); } } - - return grammar; } + return grammar; +} + } // namespace NSQLReflect diff --git a/yql/essentials/sql/v1/reflect/sql_reflect.h b/yql/essentials/sql/v1/reflect/sql_reflect.h index dec5ff98816..da511a969ff 100644 --- a/yql/essentials/sql/v1/reflect/sql_reflect.h +++ b/yql/essentials/sql/v1/reflect/sql_reflect.h @@ -7,16 +7,16 @@ namespace NSQLReflect { - struct TLexerGrammar { - THashSet<TString> KeywordNames; - THashSet<TString> PunctuationNames; - TVector<TString> OtherNames; - THashMap<TString, TString> BlockByName; +struct TLexerGrammar { + THashSet<TString> KeywordNames; + THashSet<TString> PunctuationNames; + TVector<TString> OtherNames; + THashMap<TString, TString> BlockByName; - static const TStringBuf KeywordBlockByName(const TStringBuf name); - static const TString KeywordNameByBlock(const TStringBuf block); - }; + static const TStringBuf KeywordBlockByName(const TStringBuf name); + static const TString KeywordNameByBlock(const TStringBuf block); +}; - TLexerGrammar LoadLexerGrammar(); +TLexerGrammar LoadLexerGrammar(); } // namespace NSQLReflect diff --git a/yql/essentials/sql/v1/reflect/sql_reflect_ut.cpp b/yql/essentials/sql/v1/reflect/sql_reflect_ut.cpp index 18c7b89751b..8c6fd50c7d9 100644 --- a/yql/essentials/sql/v1/reflect/sql_reflect_ut.cpp +++ b/yql/essentials/sql/v1/reflect/sql_reflect_ut.cpp @@ -5,42 +5,42 @@ using namespace NSQLReflect; namespace { - TLexerGrammar grammar = LoadLexerGrammar(); +TLexerGrammar grammar = LoadLexerGrammar(); } // namespace Y_UNIT_TEST_SUITE(SqlReflectTests) { - Y_UNIT_TEST(Keywords) { - UNIT_ASSERT_VALUES_EQUAL(grammar.KeywordNames.contains("SELECT"), true); - UNIT_ASSERT_VALUES_EQUAL(grammar.KeywordNames.contains("INSERT"), true); - UNIT_ASSERT_VALUES_EQUAL(grammar.KeywordNames.contains("WHERE"), true); - UNIT_ASSERT_VALUES_EQUAL(grammar.KeywordNames.contains("COMMIT"), true); - } - - Y_UNIT_TEST(Punctuation) { - UNIT_ASSERT_VALUES_EQUAL(grammar.PunctuationNames.contains("LPAREN"), true); - UNIT_ASSERT_VALUES_EQUAL(grammar.BlockByName.at("LPAREN"), "("); - - UNIT_ASSERT_VALUES_EQUAL(grammar.PunctuationNames.contains("MINUS"), true); - UNIT_ASSERT_VALUES_EQUAL(grammar.BlockByName.at("MINUS"), "-"); - - UNIT_ASSERT_VALUES_EQUAL(grammar.PunctuationNames.contains("NAMESPACE"), true); - UNIT_ASSERT_VALUES_EQUAL(grammar.BlockByName.at("NAMESPACE"), "::"); - } - - Y_UNIT_TEST(Other) { - UNIT_ASSERT_VALUES_EQUAL(Count(grammar.OtherNames, "REAL"), 1); - UNIT_ASSERT_VALUES_EQUAL(Count(grammar.OtherNames, "STRING_VALUE"), 1); - UNIT_ASSERT_VALUES_EQUAL(Count(grammar.OtherNames, "STRING_MULTILINE"), 0); - - UNIT_ASSERT_VALUES_EQUAL( - grammar.BlockByName.at("FLOAT_EXP"), - "E (PLUS | MINUS)? DECDIGITS"); - UNIT_ASSERT_VALUES_EQUAL( - grammar.BlockByName.at("STRING_MULTILINE"), - "(DOUBLE_COMMAT .*? DOUBLE_COMMAT)+ COMMAT?"); - UNIT_ASSERT_VALUES_EQUAL( - grammar.BlockByName.at("REAL"), - "(DECDIGITS DOT DIGIT* FLOAT_EXP? | DECDIGITS FLOAT_EXP) (F | P (F ('4' | '8') | N)?)?"); - } +Y_UNIT_TEST(Keywords) { + UNIT_ASSERT_VALUES_EQUAL(grammar.KeywordNames.contains("SELECT"), true); + UNIT_ASSERT_VALUES_EQUAL(grammar.KeywordNames.contains("INSERT"), true); + UNIT_ASSERT_VALUES_EQUAL(grammar.KeywordNames.contains("WHERE"), true); + UNIT_ASSERT_VALUES_EQUAL(grammar.KeywordNames.contains("COMMIT"), true); +} + +Y_UNIT_TEST(Punctuation) { + UNIT_ASSERT_VALUES_EQUAL(grammar.PunctuationNames.contains("LPAREN"), true); + UNIT_ASSERT_VALUES_EQUAL(grammar.BlockByName.at("LPAREN"), "("); + + UNIT_ASSERT_VALUES_EQUAL(grammar.PunctuationNames.contains("MINUS"), true); + UNIT_ASSERT_VALUES_EQUAL(grammar.BlockByName.at("MINUS"), "-"); + + UNIT_ASSERT_VALUES_EQUAL(grammar.PunctuationNames.contains("NAMESPACE"), true); + UNIT_ASSERT_VALUES_EQUAL(grammar.BlockByName.at("NAMESPACE"), "::"); +} + +Y_UNIT_TEST(Other) { + UNIT_ASSERT_VALUES_EQUAL(Count(grammar.OtherNames, "REAL"), 1); + UNIT_ASSERT_VALUES_EQUAL(Count(grammar.OtherNames, "STRING_VALUE"), 1); + UNIT_ASSERT_VALUES_EQUAL(Count(grammar.OtherNames, "STRING_MULTILINE"), 0); + + UNIT_ASSERT_VALUES_EQUAL( + grammar.BlockByName.at("FLOAT_EXP"), + "E (PLUS | MINUS)? DECDIGITS"); + UNIT_ASSERT_VALUES_EQUAL( + grammar.BlockByName.at("STRING_MULTILINE"), + "(DOUBLE_COMMAT .*? DOUBLE_COMMAT)+ COMMAT?"); + UNIT_ASSERT_VALUES_EQUAL( + grammar.BlockByName.at("REAL"), + "(DECDIGITS DOT DIGIT* FLOAT_EXP? | DECDIGITS FLOAT_EXP) (F | P (F ('4' | '8') | N)?)?"); +} } // Y_UNIT_TEST_SUITE(SqlReflectTests) diff --git a/yql/essentials/sql/v1/reflect/ya.make b/yql/essentials/sql/v1/reflect/ya.make index 1843aabf19b..865257529e8 100644 --- a/yql/essentials/sql/v1/reflect/ya.make +++ b/yql/essentials/sql/v1/reflect/ya.make @@ -1,5 +1,7 @@ LIBRARY() +ENABLE(YQL_STYLE_CPP) + SRCS( sql_reflect.cpp ) diff --git a/yql/essentials/sql/v1/select.cpp b/yql/essentials/sql/v1/select.cpp index 41689db592c..860676ad1bc 100644 --- a/yql/essentials/sql/v1/select.cpp +++ b/yql/essentials/sql/v1/select.cpp @@ -100,7 +100,8 @@ public: , Source_(std::move(source)) , CheckExist_(checkExist) , WithTables_(withTables) - {} + { + } ISource* GetSource() override { return Source_.Get(); @@ -167,6 +168,7 @@ public: TPtr DoClone() const final { return new TSourceNode(Pos_, Source_->CloneSource(), CheckExist_, WithTables_); } + protected: TSourcePtr Source_; TNodePtr Node_; @@ -184,7 +186,8 @@ public: : ISource(pos) , MissingFrom_(missingFrom) , InSubquery_(inSubquery) - {} + { + } bool IsFake() const override { return true; @@ -201,14 +204,14 @@ public: return {}; } - bool AddFilter(TContext& ctx, TNodePtr filter) override { + bool AddFilter(TContext& ctx, TNodePtr filter) override { Y_UNUSED(filter); auto pos = filter ? filter->GetPos() : Pos_; ctx.Error(pos) << (MissingFrom_ ? "Filtering is not allowed without FROM" : "Source does not allow filtering"); return false; } - TNodePtr Build(TContext& ctx) override { + TNodePtr Build(TContext& ctx) override { Y_UNUSED(ctx); auto ret = Y("AsList", Y("AsStruct")); if (InSubquery_) { @@ -264,12 +267,13 @@ public: std::pair<TNodePtr, bool> BuildAggregation(const TString& label, TContext& ctx) override { Y_UNUSED(label); Y_UNUSED(ctx); - return { nullptr, true }; + return {nullptr, true}; } TPtr DoClone() const final { return new TFakeSource(Pos_, MissingFrom_, InSubquery_); } + private: const bool MissingFrom_; const bool InSubquery_; @@ -308,7 +312,7 @@ public: return ISource::DoInit(ctx, src); } - TNodePtr Build(TContext& /*ctx*/) final { + TNodePtr Build(TContext& /*ctx*/) final { auto nodeAst = AstNode(Node_); if (WrapToList_) { nodeAst = Y("ToList", nodeAst); @@ -341,7 +345,8 @@ protected: IProxySource(TPosition pos, ISource* src) : ISource(pos) , Source_(src) - {} + { + } void AllColumns() override { Y_DEBUG_ABORT_UNLESS(Source_); @@ -451,7 +456,7 @@ protected: TColumns Columns_; }; -class IComposableSource : private TNonCopyable { +class IComposableSource: private TNonCopyable { public: virtual ~IComposableSource() = default; virtual void BuildProjectWindowDistinct(TNodePtr& blocks, TContext& ctx, bool ordered) = 0; @@ -469,7 +474,7 @@ public: } void AllColumns() final { - for (auto& source: Sources_) { + for (auto& source : Sources_) { source->AllColumns(); } } @@ -480,18 +485,18 @@ public: } void GetInputTables(TTableList& tableList) const final { - for (auto& source: Sources_) { + for (auto& source : Sources_) { source->GetInputTables(tableList); } ISource::GetInputTables(tableList); } bool IsStream() const final { - return AnyOf(Sources_, [] (const TSourcePtr& s) { return s->IsStream(); }); + return AnyOf(Sources_, [](const TSourcePtr& s) { return s->IsStream(); }); } bool DoInit(TContext& ctx, ISource* src) final { - for (auto& source: Sources_) { + for (auto& source : Sources_) { if (AsInner_) { source->UseAsInner(); } @@ -510,7 +515,7 @@ public: } TMaybe<bool> AddColumn(TContext& ctx, TColumnNode& column) final { - for (auto& source: Sources_) { + for (auto& source : Sources_) { if (!source->AddColumn(ctx, column)) { return {}; } @@ -611,18 +616,18 @@ public: return true; } - TNodePtr Build(TContext& ctx) override { + TNodePtr Build(TContext& ctx) override { Y_UNUSED(ctx); return Node_; } bool SetSamplingOptions( - TContext& ctx, - TPosition pos, - ESampleClause sampleClause, - ESampleMode mode, - TNodePtr samplingRate, - TNodePtr samplingSeed) override { + TContext& ctx, + TPosition pos, + ESampleClause sampleClause, + ESampleMode mode, + TNodePtr samplingRate, + TNodePtr samplingSeed) override { if (mode == ESampleMode::System) { ctx.Error(pos) << "only Bernoulli sampling mode is supported for subqueries"; return false; @@ -726,13 +731,12 @@ public: } bool SetSamplingOptions( - TContext& ctx, - TPosition pos, - ESampleClause sampleClause, - ESampleMode mode, - TNodePtr samplingRate, - TNodePtr samplingSeed) override - { + TContext& ctx, + TPosition pos, + ESampleClause sampleClause, + ESampleMode mode, + TNodePtr samplingRate, + TNodePtr samplingSeed) override { Y_UNUSED(pos); TString modeName; if (!samplingSeed) { @@ -799,8 +803,10 @@ public: bool IsTableSource() const override { return true; } + protected: TTableRef Table_; + private: const TSourcePtr FakeSource_; }; @@ -924,6 +930,7 @@ public: TPtr DoClone() const final { return new TInnerSource(Pos_, SafeClone(Node_), Service_, Cluster_, GetLabel()); } + protected: TNodePtr Node_; TString Service_; @@ -977,16 +984,16 @@ static bool IsComparableExpression(TContext& ctx, const TNodePtr& expr, bool ass class TReduceSource: public IRealSource { public: TReduceSource(TPosition pos, - ReduceMode mode, - TSourcePtr source, - TVector<TSortSpecificationPtr>&& orderBy, - TVector<TNodePtr>&& keys, - TVector<TNodePtr>&& args, - TNodePtr udf, - TNodePtr having, - const TWriteSettings& settings, - const TVector<TSortSpecificationPtr>& assumeOrderBy, - bool listCall) + ReduceMode mode, + TSourcePtr source, + TVector<TSortSpecificationPtr>&& orderBy, + TVector<TNodePtr>&& keys, + TVector<TNodePtr>&& args, + TNodePtr udf, + TNodePtr having, + const TWriteSettings& settings, + const TVector<TSortSpecificationPtr>& assumeOrderBy, + bool listCall) : IRealSource(pos) , Mode_(mode) , Source_(std::move(source)) @@ -1021,7 +1028,7 @@ public: return false; } src = Source_.Get(); - for (auto& key: Keys_) { + for (auto& key : Keys_) { if (!key->Init(ctx, src)) { return false; } @@ -1044,7 +1051,7 @@ public: return false; } - for (auto orderSpec: OrderBy_) { + for (auto orderSpec : OrderBy_) { if (!orderSpec->OrderExpr->Init(ctx, src)) { return false; } @@ -1061,7 +1068,7 @@ public: } const auto label = GetLabel(); - for (const auto& sortSpec: AssumeOrderBy_) { + for (const auto& sortSpec : AssumeOrderBy_) { auto& expr = sortSpec->OrderExpr; SetLabel(Source_->GetLabel()); if (!expr->Init(ctx, this)) { @@ -1085,9 +1092,8 @@ public: auto keysTuple = Y(); if (Keys_.size() == 1) { keysTuple = Y("Member", "row", BuildQuotedAtom(Pos_, *Keys_.back()->GetColumnName())); - } - else { - for (const auto& key: Keys_) { + } else { + for (const auto& key : Keys_) { keysTuple = L(keysTuple, Y("Member", "row", BuildQuotedAtom(Pos_, *key->GetColumnName()))); } keysTuple = Q(keysTuple); @@ -1110,16 +1116,16 @@ public: auto columnPtr = Args_[0]->GetColumnName(); TNodePtr expr = BuildAtom(Pos_, "partitionStream"); if (!columnPtr || *columnPtr != "*") { - expr = Y("Map", "partitionStream", BuildLambda(Pos_, Y("keyPair"), Q(L(Y(),\ - Y("Nth", "keyPair", Q(ToString("0"))),\ - Y("Map", Y("Nth", "keyPair", Q(ToString("1"))), BuildLambda(Pos_, Y("row"), Args_[0])))))); + expr = Y("Map", "partitionStream", BuildLambda(Pos_, Y("keyPair"), Q(L(Y(), + Y("Nth", "keyPair", Q(ToString("0"))), + Y("Map", Y("Nth", "keyPair", Q(ToString("1"))), BuildLambda(Pos_, Y("row"), Args_[0])))))); } processPartitions = Y("SqlReduce", "partitionStream", BuildQuotedAtom(Pos_, "byAll", TNodeFlags::Default), Udf_, expr); break; } case ReduceMode::ByPartition: { processPartitions = Y("SqlReduce", "partitionStream", extractKeyLambda, Udf_, - BuildLambda(Pos_, Y("row"), Args_[0])); + BuildLambda(Pos_, Y("row"), Args_[0])); break; } default: @@ -1135,7 +1141,7 @@ public: } auto partitionByKey = Y(!ListCall_ && Mode_ == ReduceMode::ByAll ? "PartitionByKey" : "PartitionsByKeys", "core", extractKeyLambda, - sortDirection, sortKeySelector, BuildLambda(Pos_, Y("partitionStream"), processPartitions)); + sortDirection, sortKeySelector, BuildLambda(Pos_, Y("partitionStream"), processPartitions)); auto inputLabel = ListCall_ ? "inputRowsList" : "core"; auto block(Y(Y("let", inputLabel, input))); @@ -1153,8 +1159,7 @@ public: block = L(block, Y("let", "core", Y("AutoDemux", partitionByKey))); if (Having_) { block = L(block, Y("let", "core", - Y("Filter", "core", BuildLambda(Pos_, Y("row"), Y("Coalesce", Having_, Y("Bool", Q("false"))))) - )); + Y("Filter", "core", BuildLambda(Pos_, Y("row"), Y("Coalesce", Having_, Y("Bool", Q("false"))))))); } return Y("block", Q(L(block, Y("return", "core")))); } @@ -1182,9 +1187,10 @@ public: TPtr DoClone() const final { return new TReduceSource(Pos_, Mode_, Source_->CloneSource(), CloneContainer(OrderBy_), - CloneContainer(Keys_), CloneContainer(Args_), SafeClone(Udf_), SafeClone(Having_), Settings_, - CloneContainer(AssumeOrderBy_), ListCall_); + CloneContainer(Keys_), CloneContainer(Args_), SafeClone(Udf_), SafeClone(Having_), Settings_, + CloneContainer(AssumeOrderBy_), ListCall_); } + private: ReduceMode Mode_; TSourcePtr Source_; @@ -1199,18 +1205,18 @@ private: }; TSourcePtr BuildReduce(TPosition pos, - ReduceMode mode, - TSourcePtr source, - TVector<TSortSpecificationPtr>&& orderBy, - TVector<TNodePtr>&& keys, - TVector<TNodePtr>&& args, - TNodePtr udf, - TNodePtr having, - const TWriteSettings& settings, - const TVector<TSortSpecificationPtr>& assumeOrderBy, - bool listCall) { + ReduceMode mode, + TSourcePtr source, + TVector<TSortSpecificationPtr>&& orderBy, + TVector<TNodePtr>&& keys, + TVector<TNodePtr>&& args, + TNodePtr udf, + TNodePtr having, + const TWriteSettings& settings, + const TVector<TSortSpecificationPtr>& assumeOrderBy, + bool listCall) { return new TReduceSource(pos, mode, std::move(source), std::move(orderBy), std::move(keys), - std::move(args), udf, having, settings, assumeOrderBy, listCall); + std::move(args), udf, having, settings, assumeOrderBy, listCall); } namespace { @@ -1245,7 +1251,7 @@ bool InitAndGetGroupKey(TContext& ctx, const TNodePtr& expr, ISource* src, TStri return true; } -} +} // namespace class TCompositeSelect: public IRealSource { public: @@ -1266,7 +1272,7 @@ public: } void GetInputTables(TTableList& tableList) const override { - for (const auto& select: Subselects_) { + for (const auto& select : Subselects_) { select->GetInputTables(tableList); } ISource::GetInputTables(tableList); @@ -1297,9 +1303,7 @@ public: } if (origSrc->IsFlattenByColumns() || origSrc->IsFlattenColumns()) { - Flatten_ = origSrc->IsFlattenByColumns() ? - origSrc->BuildFlattenByColumns("row") : - origSrc->BuildFlattenColumns("row"); + Flatten_ = origSrc->IsFlattenByColumns() ? origSrc->BuildFlattenByColumns("row") : origSrc->BuildFlattenColumns("row"); if (!Flatten_ || !Flatten_->Init(ctx, src)) { return false; } @@ -1317,7 +1321,7 @@ public: } } - for (const auto& select: Subselects_) { + for (const auto& select : Subselects_) { select->SetLabel(Label_); if (AsInner_) { select->UseAsInner(); @@ -1336,7 +1340,7 @@ public: groupingColumnsCount = count; } else if (*groupingColumnsCount != count) { ctx.Error(select->GetPos()) << TStringBuilder() << "Mismatch GROUPING() column count in composite select input #" - << idx << ": expected " << *groupingColumnsCount << ", got: " << count << ". Please submit bug report"; + << idx << ": expected " << *groupingColumnsCount << ", got: " << count << ". Please submit bug report"; return false; } ++idx; @@ -1345,7 +1349,7 @@ public: } TMaybe<bool> AddColumn(TContext& ctx, TColumnNode& column) override { - for (const auto& select: Subselects_) { + for (const auto& select : Subselects_) { if (!select->AddColumn(ctx, column)) { return {}; } @@ -1370,7 +1374,7 @@ public: } TNodePtr compositeNode = Y("UnionAll"); - for (const auto& select: Subselects_) { + for (const auto& select : Subselects_) { YQL_ENSURE(dynamic_cast<IComposableSource*>(select.Get())); auto addNode = select->Build(ctx); if (!addNode) { @@ -1402,7 +1406,7 @@ public: return Subselects_.front()->GetOrderKind(); } - const TColumns* GetColumns() const override{ + const TColumns* GetColumns() const override { return Subselects_.front()->GetColumns(); } @@ -1423,6 +1427,7 @@ public: newSource->SetSubselects(CloneContainer(Subselects_), CloneContainer(Grouping_), CloneContainer(GroupByExpr_)); return newSource; } + private: bool CalculateGroupingCols(TContext& ctx, ISource* initSrc) { auto origSrc = OriginalSource_->CloneSource(); @@ -1431,7 +1436,7 @@ private: } bool hasError = false; - for (auto& expr: GroupByExpr_) { + for (auto& expr : GroupByExpr_) { if (!expr->Init(ctx, origSrc.Get()) || !IsComparableExpression(ctx, expr, false, "GROUP BY")) { hasError = true; } @@ -1465,15 +1470,15 @@ private: }; namespace { - TString FullColumnName(const TColumnNode& column) { - YQL_ENSURE(column.GetColumnName()); - TString columnName = *column.GetColumnName(); - if (column.IsUseSource()) { - columnName = DotJoin(*column.GetSourceName(), columnName); - } - return columnName; +TString FullColumnName(const TColumnNode& column) { + YQL_ENSURE(column.GetColumnName()); + TString columnName = *column.GetColumnName(); + if (column.IsUseSource()) { + columnName = DotJoin(*column.GetSourceName(), columnName); } + return columnName; } +} // namespace /// \todo simplify class class TSelectCore: public IRealSource, public IComposableSource { @@ -1497,8 +1502,7 @@ public: bool selectStream, const TWriteSettings& settings, TColumnsSets&& uniqueSets, - TColumnsSets&& distinctSets - ) + TColumnsSets&& distinctSets) : IRealSource(pos) , Source_(std::move(source)) , GroupByExpr_(groupByExpr) @@ -1568,7 +1572,7 @@ public: src->SetCompactGroupBy(CompactGroupBy_); src->SetGroupBySuffix(GroupBySuffix_); - for (auto& term: Terms_) { + for (auto& term : Terms_) { term->CollectPreaggregateExprs(ctx, *src, DistinctAggrExpr_); } @@ -1576,7 +1580,7 @@ public: Having_->CollectPreaggregateExprs(ctx, *src, DistinctAggrExpr_); } - for (auto& expr: GroupByExpr_) { + for (auto& expr : GroupByExpr_) { if (auto sessionWindow = dynamic_cast<TSessionWindow*>(expr.Get())) { if (Source_->IsStream()) { ctx.Error(Pos_) << "SessionWindow is unsupported for streaming sources"; @@ -1607,7 +1611,7 @@ public: return false; } - for (auto& expr: DistinctAggrExpr_) { + for (auto& expr : DistinctAggrExpr_) { if (!expr->Init(ctx, src)) { hasError = true; } @@ -1621,7 +1625,7 @@ public: return false; } - for (auto& expr: GroupBy_) { + for (auto& expr : GroupBy_) { TString usedColumn; if (!InitAndGetGroupKey(ctx, expr, src, "GROUP BY", usedColumn)) { hasError = true; @@ -1654,9 +1658,7 @@ public: Aggregate_ = aggRes.first; if (src->IsFlattenByColumns() || src->IsFlattenColumns()) { - Flatten_ = src->IsFlattenByColumns() ? - src->BuildFlattenByColumns("row") : - src->BuildFlattenColumns("row"); + Flatten_ = src->IsFlattenByColumns() ? src->BuildFlattenByColumns("row") : src->BuildFlattenColumns("row"); if (!Flatten_ || !Flatten_->Init(ctx, src)) { return false; } @@ -1683,20 +1685,18 @@ public: Aggregate_ = Y( "Filter", Aggregate_, - BuildLambda(Pos_, Y("row"), Y("Coalesce", Having_, Y("Bool", Q("false")))) - ); + BuildLambda(Pos_, Y("row"), Y("Coalesce", Having_, Y("Bool", Q("false"))))); } } else if (Having_) { if (Distinct_) { Aggregate_ = Y( "Filter", "core", - BuildLambda(Pos_, Y("row"), Y("Coalesce", Having_, Y("Bool", Q("false")))) - ); + BuildLambda(Pos_, Y("row"), Y("Coalesce", Having_, Y("Bool", Q("false"))))); if (!ctx.Warning(Having_->GetPos(), TIssuesIds::YQL_HAVING_WITHOUT_AGGREGATION_IN_SELECT_DISTINCT, [](auto& out) { - out << "The usage of HAVING without aggregations with SELECT DISTINCT is " - << "non-standard and will stop working soon. Please use WHERE instead."; - })) { + out << "The usage of HAVING without aggregations with SELECT DISTINCT is " + << "non-standard and will stop working soon. Please use WHERE instead."; + })) { return false; } } else { @@ -1736,9 +1736,9 @@ public: if (Source_->HasMatchRecognize()) { if (auto matchRecognize = Source_->BuildMatchRecognize(ctx, "core")) { - //use unique name match_recognize to find this block easily in unit tests + // use unique name match_recognize to find this block easily in unit tests block = L(block, Y("let", "match_recognize", matchRecognize)); - //then bind to the conventional name + // then bind to the conventional name block = L(block, Y("let", "core", "match_recognize")); } else { return nullptr; @@ -1838,7 +1838,7 @@ public: cleanup = Y("let", label, Y("RemoveSystemMembers", label)); } else { TNodePtr members; - for (auto& term: Terms_) { + for (auto& term : Terms_) { if (term->IsAsterisk()) { auto sourceName = term->GetSourceName(); YQL_ENSURE(*sourceName && !sourceName->empty()); @@ -1919,7 +1919,7 @@ public: return true; } - for (auto without: Without_) { + for (auto without : Without_) { auto name = *without->GetColumnName(); if (Source_ && Source_->GetJoin()) { name = DotJoin(*without->GetSourceName(), name); @@ -1935,7 +1935,7 @@ public: TNodePtr PrepareWithout(const TNodePtr& base) { auto terms = base; if (Without_) { - for (auto without: Without_) { + for (auto without : Without_) { auto name = *without->GetColumnName(); if (Source_ && Source_->GetJoin()) { name = DotJoin(*without->GetSourceName(), name); @@ -1955,9 +1955,9 @@ public: TNodePtr DoClone() const final { return new TSelectCore(Pos_, Source_->CloneSource(), CloneContainer(GroupByExpr_), - CloneContainer(GroupBy_), CompactGroupBy_, GroupBySuffix_, AssumeSorted_, CloneContainer(OrderBy_), - SafeClone(Having_), CloneContainer(WinSpecs_), SafeClone(LegacyHoppingWindowSpec_), - CloneContainer(Terms_), Distinct_, Without_, ForceWithout_, SelectStream_, Settings_, TColumnsSets(UniqueSets_), TColumnsSets(DistinctSets_)); + CloneContainer(GroupBy_), CompactGroupBy_, GroupBySuffix_, AssumeSorted_, CloneContainer(OrderBy_), + SafeClone(Having_), CloneContainer(WinSpecs_), SafeClone(LegacyHoppingWindowSpec_), + CloneContainer(Terms_), Distinct_, Without_, ForceWithout_, SelectStream_, Settings_, TColumnsSets(UniqueSets_), TColumnsSets(DistinctSets_)); } private: @@ -1998,7 +1998,7 @@ private: src->SetLegacyHoppingWindowSpec(LegacyHoppingWindowSpec_); } - for (auto& term: Terms_) { + for (auto& term : Terms_) { if (!term->Init(ctx, src)) { hasError = true; continue; @@ -2018,8 +2018,8 @@ private: hasName = false; if (ctx.WarnUnnamedColumns) { if (!ctx.Warning(term->GetPos(), TIssuesIds::YQL_UNNAMED_COLUMN, [&](auto& out) { - out << "Autogenerated column name " << label << " will be used for expression"; - })) { + out << "Autogenerated column name " << label << " will be used for expression"; + })) { return false; } } @@ -2036,21 +2036,21 @@ private: auto compositeSrcPtr = static_cast<TCompositeSelect*>(Source_->GetCompositeSource()); if (compositeSrcPtr) { const auto& groupings = compositeSrcPtr->GetGroupingCols(); - for (const auto& column: groupings) { + for (const auto& column : groupings) { if (Source_->IsGroupByColumn(column)) { continue; } const TString tableName = (GroupByExpr_ || DistinctAggrExpr_) ? "preaggregated" : "origcore"; CompositeTerms_ = L(CompositeTerms_, Y("let", "row", Y("AddMember", "row", BuildQuotedAtom(Pos_, column), Y("Nothing", Y("MatchType", - Y("StructMemberType", Y("ListItemType", Y("TypeOf", tableName)), Q(column)), - Q("Optional"), Y("lambda", Q(Y("item")), "item"), Y("lambda", Q(Y("item")), Y("OptionalType", "item"))))))); + Y("StructMemberType", Y("ListItemType", Y("TypeOf", tableName)), Q(column)), + Q("Optional"), Y("lambda", Q(Y("item")), "item"), Y("lambda", Q(Y("item")), Y("OptionalType", "item"))))))); } } } - for (auto iter: WinSpecs_) { + for (auto iter : WinSpecs_) { auto winSpec = *iter.second; - for (auto orderSpec: winSpec.OrderBy) { + for (auto orderSpec : winSpec.OrderBy) { if (!orderSpec->OrderExpr->Init(ctx, src)) { hasError = true; } @@ -2060,7 +2060,7 @@ private: if (Columns_.All || Columns_.QualifiedAll) { Source_->AllColumns(); } - for (const auto& without: Without_) { + for (const auto& without : Without_) { auto namePtr = without->GetColumnName(); auto sourcePtr = without->GetSourceName(); YQL_ENSURE(namePtr && *namePtr); @@ -2083,8 +2083,8 @@ private: if (Having_) { exprs.push_back(Having_); } - for (const auto& iter: WinSpecs_) { - for (const auto& sortSpec: iter.second->OrderBy) { + for (const auto& iter : WinSpecs_) { + for (const auto& sortSpec : iter.second->OrderBy) { exprs.push_back(sortSpec->OrderExpr); } } @@ -2093,7 +2093,7 @@ private: } } const auto label = GetLabel(); - for (const auto& sortSpec: OrderBy_) { + for (const auto& sortSpec : OrderBy_) { auto& expr = sortSpec->OrderExpr; SetLabel(Source_->GetLabel()); OrderByInit_ = true; @@ -2115,7 +2115,7 @@ private: TNodePtr PrepareJoinCoalesce(TContext& ctx, const TNodePtr& base, bool multipleQualifiedAll, const TVector<TString>& coalesceLabels) { const bool isJoin = Source_->GetJoin(); const bool needCoalesce = isJoin && ctx.SimpleColumns && - (Columns_.All || multipleQualifiedAll || ctx.CoalesceJoinKeysOnQualifiedAll); + (Columns_.All || multipleQualifiedAll || ctx.CoalesceJoinKeysOnQualifiedAll); if (!needCoalesce) { return base; @@ -2125,7 +2125,7 @@ private: const auto& sameKeyMap = Source_->GetJoin()->GetSameKeysMap(); if (sameKeyMap) { terms = L(terms, Y("let", "flatSameKeys", "row")); - for (const auto& [key, sources]: sameKeyMap) { + for (const auto& [key, sources] : sameKeyMap) { auto coalesceKeys = Y(); for (const auto& label : coalesceLabels) { if (sources.contains(label)) { @@ -2171,13 +2171,13 @@ private: auto groupColumnsStruct = Y("DivePrefixMembers", "row", Q(members)); terms = L(terms, Y("let", "res", Y("FlattenMembers", Q(Y(BuildQuotedAtom(Pos_, ""), groupExprStruct)), - Q(Y(BuildQuotedAtom(Pos_, ""), groupColumnsStruct))))); + Q(Y(BuildQuotedAtom(Pos_, ""), groupColumnsStruct))))); } options = L(options, Q(Y(Q("divePrefix"), Q(members)))); } else { terms = L(terms, Y("let", "res", "row")); } - sqlProjectArgs = L(sqlProjectArgs, Y("SqlProjectStarItem", "projectCoreType", BuildQuotedAtom(Pos_, ""), BuildLambda(Pos_, Y("row"), terms, "res"), Q(options))); + sqlProjectArgs = L(sqlProjectArgs, Y("SqlProjectStarItem", "projectCoreType", BuildQuotedAtom(Pos_, ""), BuildLambda(Pos_, Y("row"), terms, "res"), Q(options))); } else { YQL_ENSURE(!Columns_.List.empty()); YQL_ENSURE(Columns_.List.size() == Terms_.size()); @@ -2187,7 +2187,7 @@ private: if (isJoin && ctx.SimpleColumns) { THashSet<TString> starTerms; - for (auto& term: Terms_) { + for (auto& term : Terms_) { if (term->IsAsterisk()) { auto sourceName = term->GetSourceName(); YQL_ENSURE(*sourceName && !sourceName->empty()); @@ -2214,7 +2214,7 @@ private: auto column = Columns_.List.begin(); auto isNamedColumn = Columns_.NamedColumns.begin(); - for (auto& term: Terms_) { + for (auto& term : Terms_) { auto sourceName = term->GetSourceName(); if (!term->IsAsterisk()) { auto body = Y(); @@ -2266,7 +2266,7 @@ private: } } - for (const auto& [columnName, column]: ExtraSortColumns_) { + for (const auto& [columnName, column] : ExtraSortColumns_) { auto body = Y(); body = L(body, Y("let", "res", column)); TPosition pos = column->GetPos(); @@ -2343,8 +2343,7 @@ public: bool listCall, bool processStream, const TWriteSettings& settings, - const TVector<TSortSpecificationPtr>& assumeOrderBy - ) + const TVector<TSortSpecificationPtr>& assumeOrderBy) : IRealSource(pos) , Source_(std::move(source)) , With_(with) @@ -2421,7 +2420,7 @@ public: } TMaybe<ui32> listPosIndex; ui32 termIndex = 0; - for (auto& term: Terms_) { + for (auto& term : Terms_) { if (!term->GetLabel().empty()) { ctx.Error(term->GetPos()) << "Labels are not allowed for PROCESS terms"; hasError = true; @@ -2463,7 +2462,7 @@ public: src->FinishColumns(); const auto label = GetLabel(); - for (const auto& sortSpec: AssumeOrderBy_) { + for (const auto& sortSpec : AssumeOrderBy_) { auto& expr = sortSpec->OrderExpr; SetLabel(Source_->GetLabel()); if (!expr->Init(ctx, this)) { @@ -2556,7 +2555,7 @@ public: TNodePtr DoClone() const final { return new TProcessSource(Pos_, Source_->CloneSource(), SafeClone(With_), WithExtFunction_, - CloneContainer(Terms_), ListCall_, ProcessStream_, Settings_, CloneContainer(AssumeOrderBy_)); + CloneContainer(Terms_), ListCall_, ProcessStream_, Settings_, CloneContainer(AssumeOrderBy_)); } private: @@ -2569,7 +2568,7 @@ private: } else { Y_DEBUG_ABORT_UNLESS(Columns_.List.size() == Terms_.size()); terms = L(Y(), Y("let", "res", - L(Y("AsStructUnordered"), Q(Y(BuildQuotedAtom(Pos_, Columns_.List.front()), Terms_.front()))))); + L(Y("AsStructUnordered"), Q(Y(BuildQuotedAtom(Pos_, Columns_.List.front()), Terms_.front()))))); terms = L(terms, Y("let", "res", Y("Just", "res"))); } return terms; @@ -2595,8 +2594,7 @@ TSourcePtr BuildProcess( bool listCall, bool processStream, const TWriteSettings& settings, - const TVector<TSortSpecificationPtr>& assumeOrderBy -) { + const TVector<TSortSpecificationPtr>& assumeOrderBy) { return new TProcessSource(pos, std::move(source), with, withExtFunction, std::move(terms), listCall, processStream, settings, assumeOrderBy); } @@ -2607,19 +2605,21 @@ public: , CompositeSelect_(nullptr) , Holder_(std::move(source)) , GroupBy_(groupBy) - {} + { + } TNestedProxySource(TCompositeSelect* compositeSelect, const TVector<TNodePtr>& groupBy) : IProxySource(compositeSelect->GetPos(), compositeSelect->RealSource()) , CompositeSelect_(compositeSelect) , GroupBy_(groupBy) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { return Source_->Init(ctx, src); } - TNodePtr Build(TContext& ctx) override { + TNodePtr Build(TContext& ctx) override { return CompositeSelect_ ? BuildAtom(Pos_, "composite", TNodeFlags::Default) : Source_->Build(ctx); } @@ -2649,7 +2649,7 @@ public: ui64 hint = 0; if (GroupByColumns_.empty()) { const bool isJoin = GetJoin(); - for (const auto& groupByNode: GroupBy_) { + for (const auto& groupByNode : GroupBy_) { auto namePtr = groupByNode->GetColumnName(); YQL_ENSURE(namePtr); TString column = *namePtr; @@ -2662,7 +2662,7 @@ public: GroupByColumns_.insert(column); } } - for (const auto& column: columns) { + for (const auto& column : columns) { hint <<= 1; if (!GroupByColumns_.contains(column)) { hint += 1; @@ -2690,7 +2690,6 @@ public: return Y("Map", label, BuildLambda(Pos_, Y("row"), body, "row")); } - void FinishColumns() override { Source_->FinishColumns(); } @@ -2706,8 +2705,7 @@ public: TPtr DoClone() const final { YQL_ENSURE(Hints_.empty()); - return Holder_.Get() ? new TNestedProxySource(Pos_, CloneContainer(GroupBy_), Holder_->CloneSource()) : - new TNestedProxySource(CompositeSelect_, CloneContainer(GroupBy_)); + return Holder_.Get() ? new TNestedProxySource(Pos_, CloneContainer(GroupBy_), Holder_->CloneSource()) : new TNestedProxySource(CompositeSelect_, CloneContainer(GroupBy_)); } private: @@ -2718,7 +2716,6 @@ private: mutable TVector<ui64> Hints_; }; - namespace { TSourcePtr DoBuildSelectCore( TContext& ctx, @@ -2741,26 +2738,25 @@ TSourcePtr DoBuildSelectCore( bool selectStream, const TWriteSettings& settings, TColumnsSets&& uniqueSets, - TColumnsSets&& distinctSets -) { + TColumnsSets&& distinctSets) { if (groupBy.empty() || !groupBy.front()->ContentListPtr()) { return new TSelectCore(pos, std::move(source), groupByExpr, groupBy, compactGroupBy, groupBySuffix, assumeSorted, - orderBy, having, winSpecs, legacyHoppingWindowSpec, terms, distinct, without, forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); + orderBy, having, winSpecs, legacyHoppingWindowSpec, terms, distinct, without, forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); } if (groupBy.size() == 1) { /// actualy no big idea to use grouping function in this case (result allways 0) auto contentPtr = groupBy.front()->ContentListPtr(); source = new TNestedProxySource(pos, *contentPtr, source); return DoBuildSelectCore(ctx, pos, originalSource, source, groupByExpr, *contentPtr, compactGroupBy, groupBySuffix, - assumeSorted, orderBy, having, std::move(winSpecs), - legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); + assumeSorted, orderBy, having, std::move(winSpecs), + legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); } /// \todo some smart merge logic, generalize common part of grouping (expr, flatten, etc)? TIntrusivePtr<TCompositeSelect> compositeSelect = new TCompositeSelect(pos, std::move(source), originalSource->CloneSource(), settings); size_t totalGroups = 0; TVector<TSourcePtr> subselects; TVector<TNodePtr> groupingCols; - for (auto& grouping: groupBy) { + for (auto& grouping : groupBy) { auto contentPtr = grouping->ContentListPtr(); TVector<TNodePtr> cache(1, nullptr); if (!contentPtr) { @@ -2772,15 +2768,15 @@ TSourcePtr DoBuildSelectCore( if (!subselects.empty()) { /// clone terms for others usage TVector<TNodePtr> termsCopy; - for (const auto& term: terms) { + for (const auto& term : terms) { termsCopy.emplace_back(term->Clone()); } std::swap(terms, termsCopy); } totalGroups += contentPtr->size(); TSelectCore* selectCore = new TSelectCore(pos, std::move(proxySource), CloneContainer(groupByExpr), - CloneContainer(*contentPtr), compactGroupBy, groupBySuffix, assumeSorted, orderBy, SafeClone(having), CloneContainer(winSpecs), - legacyHoppingWindowSpec, terms, distinct, without, forceWithout, selectStream, settings, TColumnsSets(uniqueSets), TColumnsSets(distinctSets)); + CloneContainer(*contentPtr), compactGroupBy, groupBySuffix, assumeSorted, orderBy, SafeClone(having), CloneContainer(winSpecs), + legacyHoppingWindowSpec, terms, distinct, without, forceWithout, selectStream, settings, TColumnsSets(uniqueSets), TColumnsSets(distinctSets)); subselects.emplace_back(selectCore); } if (totalGroups > ctx.PragmaGroupByLimit) { @@ -2791,7 +2787,7 @@ TSourcePtr DoBuildSelectCore( return compositeSelect; } -} +} // namespace TSourcePtr BuildSelectCore( TContext& ctx, @@ -2813,11 +2809,10 @@ TSourcePtr BuildSelectCore( bool selectStream, const TWriteSettings& settings, TColumnsSets&& uniqueSets, - TColumnsSets&& distinctSets -) + TColumnsSets&& distinctSets) { return DoBuildSelectCore(ctx, pos, source, source, groupByExpr, groupBy, compactGroupBy, groupBySuffix, assumeSorted, orderBy, - having, std::move(winSpecs), legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); + having, std::move(winSpecs), legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); } class TSelectOp: public IRealSource { @@ -2845,7 +2840,7 @@ public: bool DoInit(TContext& ctx, ISource* src) override { bool first = true; - for (auto& s: Sources_) { + for (auto& s : Sources_) { s->UseAsInner(); if (!s->Init(ctx, src)) { return false; @@ -2886,7 +2881,7 @@ public: TPtr res = Y(op); - for (auto& s: Sources_) { + for (auto& s : Sources_) { auto input = s->Build(ctx); if (!input) { return nullptr; @@ -2896,9 +2891,8 @@ public: return res; } - bool IsStream() const override { - for (auto& s: Sources_) { + for (auto& s : Sources_) { if (!s->IsStream()) { return false; } @@ -2934,8 +2928,7 @@ TSourcePtr BuildSelectOp( TVector<TSourcePtr>&& sources, const TString& op, bool quantifierAll, - const TWriteSettings& settings -) { + const TWriteSettings& settings) { return new TSelectOp(pos, std::move(sources), op, quantifierAll, settings); } @@ -3011,7 +3004,8 @@ TSourcePtr BuildOverWindowSource(TPosition pos, const TString& windowName, ISour class TSkipTakeNode final: public TAstListNode { public: TSkipTakeNode(TPosition pos, const TNodePtr& skip, const TNodePtr& take) - : TAstListNode(pos), IsSkipProvided_(!!skip) + : TAstListNode(pos) + , IsSkipProvided_(!!skip) { TNodePtr select(AstNode("select")); if (skip) { @@ -3028,6 +3022,7 @@ public: bool HasSkip() const { return IsSkipProvided_; } + private: const bool IsSkipProvided_; }; @@ -3042,7 +3037,8 @@ public: : IProxySource(pos, source.Get()) , Source_(std::move(source)) , SkipTake_(skipTake) - {} + { + } bool DoInit(TContext& ctx, ISource* src) override { Source_->SetLabel(Label_); @@ -3053,8 +3049,8 @@ public: if (IgnoreSort()) { Source_->DisableSort(); if (!ctx.Warning(Source_->GetPos(), TIssuesIds::YQL_ORDER_BY_WITHOUT_LIMIT_IN_SUBQUERY, [](auto& out) { - out << "ORDER BY without LIMIT in subquery will be ignored"; - })) { + out << "ORDER BY without LIMIT in subquery will be ignored"; + })) { return false; } } @@ -3070,9 +3066,9 @@ public: } if (SkipTake_->HasSkip() && Source_->GetOrderKind() != EOrderKind::Sort && Source_->GetOrderKind() != EOrderKind::Assume) { if (!ctx.Warning(Source_->GetPos(), TIssuesIds::YQL_OFFSET_WITHOUT_SORT, [](auto& out) { - out << "LIMIT with OFFSET without [ASSUME] ORDER BY may provide " - << "different results from run to run"; - })) { + out << "LIMIT with OFFSET without [ASSUME] ORDER BY may provide " + << "different results from run to run"; + })) { return false; } } @@ -3114,12 +3110,12 @@ public: } bool SetSamplingOptions( - TContext& ctx, - TPosition pos, - ESampleClause sampleClause, - ESampleMode mode, - TNodePtr samplingRate, - TNodePtr samplingSeed) override { + TContext& ctx, + TPosition pos, + ESampleClause sampleClause, + ESampleMode mode, + TNodePtr samplingRate, + TNodePtr samplingSeed) override { if (mode == ESampleMode::System) { ctx.Error(pos) << "only Bernoulli sampling mode is supported for subqueries"; return false; @@ -3142,6 +3138,7 @@ public: TPtr DoClone() const final { return MakeIntrusive<TSelect>(Pos_, Source_->CloneSource(), SafeClone(SkipTake_)); } + protected: bool IgnoreSort() const { return AsInner_ && !SkipTake_ && EOrderKind::Sort == Source_->GetOrderKind(); @@ -3156,9 +3153,12 @@ TSourcePtr BuildSelect(TPosition pos, TSourcePtr source, TNodePtr skipTake) { return new TSelect(pos, std::move(source), skipTake); } -class TAnyColumnSource final : public ISource { +class TAnyColumnSource final: public ISource { public: - TAnyColumnSource(TPosition pos) : ISource(pos) {} + TAnyColumnSource(TPosition pos) + : ISource(pos) + { + } bool DoInit(TContext&, ISource*) final { return true; @@ -3184,7 +3184,7 @@ TSourcePtr BuildAnyColumnSource(TPosition pos) { class TSelectResultNode final: public TAstListNode { public: TSelectResultNode(TPosition pos, TSourcePtr source, bool writeResult, bool inSubquery, - TScopedStatePtr scoped) + TScopedStatePtr scoped) : TAstListNode(pos) , Source_(std::move(source)) , WriteResult_(writeResult) @@ -3299,6 +3299,7 @@ public: TPtr DoClone() const final { return {}; } + protected: TSourcePtr Source_; @@ -3309,7 +3310,7 @@ protected: }; TNodePtr BuildSelectResult(TPosition pos, TSourcePtr source, bool writeResult, bool inSubquery, - TScopedStatePtr scoped) { + TScopedStatePtr scoped) { return new TSelectResultNode(pos, std::move(source), writeResult, inSubquery, scoped); } diff --git a/yql/essentials/sql/v1/source.cpp b/yql/essentials/sql/v1/source.cpp index 1a5f9d1cd09..fd3764fb908 100644 --- a/yql/essentials/sql/v1/source.cpp +++ b/yql/essentials/sql/v1/source.cpp @@ -20,7 +20,6 @@ using namespace NYql; namespace NSQLTranslationV1 { - TTableRef::TTableRef(const TString& refName, const TString& service, const TDeferredAtom& cluster, TNodePtr keys) : RefName(refName) , Service(to_lower(service)) @@ -49,7 +48,7 @@ ISource::~ISource() TSourcePtr ISource::CloneSource() const { Y_DEBUG_ABORT_UNLESS(dynamic_cast<ISource*>(Clone().Get()), "Cloned node is no source"); TSourcePtr result = static_cast<ISource*>(Clone().Get()); - for (auto curFilter: Filters_) { + for (auto curFilter : Filters_) { result->Filters_.emplace_back(curFilter->Clone()); } for (int i = 0; i < static_cast<int>(EExprSeat::Max); ++i) { @@ -73,7 +72,7 @@ const TColumns* ISource::GetColumns() const { } void ISource::GetInputTables(TTableList& tableList) const { - for (auto srcPtr: UsedSources_) { + for (auto srcPtr : UsedSources_) { srcPtr->GetInputTables(tableList); } return; @@ -82,8 +81,7 @@ void ISource::GetInputTables(TTableList& tableList) const { TMaybe<bool> ISource::AddColumn(TContext& ctx, TColumnNode& column) { if (column.IsReliable()) { ctx.Error(Pos_) << "Source does not allow column references"; - ctx.Error(column.GetPos()) << "Column reference " << - (column.GetColumnName() ? "'" + *column.GetColumnName() + "'" : "(expr)"); + ctx.Error(column.GetPos()) << "Column reference " << (column.GetColumnName() ? "'" + *column.GetColumnName() + "'" : "(expr)"); } return {}; } @@ -91,7 +89,6 @@ TMaybe<bool> ISource::AddColumn(TContext& ctx, TColumnNode& column) { void ISource::FinishColumns() { } - bool ISource::AddFilter(TContext& ctx, TNodePtr filter) { Y_UNUSED(ctx); Filters_.push_back(filter); @@ -126,7 +123,7 @@ bool ISource::AddExpressions(TContext& ctx, const TVector<TNodePtr>& expressions // TODO: merge FlattenBy with FlattenByExpr const bool isFlatten = (exprSeat == EExprSeat::FlattenBy || exprSeat == EExprSeat::FlattenByExpr); THashSet<TString>& aliases = isFlatten ? FlattenByAliases_ : aliasSet; - for (const auto& expr: expressions) { + for (const auto& expr : expressions) { const auto& alias = expr->GetLabel(); const auto& columnNamePtr = expr->GetColumnName(); if (alias) { @@ -158,8 +155,7 @@ bool ISource::AddExpressions(TContext& ctx, const TVector<TNodePtr>& expressions auto columnAlias = GroupByColumnAliases_.emplace(columnName, alias); auto oldAlias = columnAlias.first->second; if (columnAlias.second && oldAlias != alias) { - ctx.Error(expr->GetPos()) << "Alias for column not same, column: " << columnName << - ", exist alias: " << oldAlias << ", another alias: " << alias; + ctx.Error(expr->GetPos()) << "Alias for column not same, column: " << columnName << ", exist alias: " << oldAlias << ", another alias: " << alias; return false; } } @@ -337,7 +333,7 @@ bool ISource::IsFlattenByExprs() const { } bool ISource::IsAlias(EExprSeat exprSeat, const TString& column) const { - for (const auto& exprNode: Expressions(exprSeat)) { + for (const auto& exprNode : Expressions(exprSeat)) { const auto& labelName = exprNode->GetLabel(); if (labelName && labelName == column) { return true; @@ -349,7 +345,7 @@ bool ISource::IsAlias(EExprSeat exprSeat, const TString& column) const { bool ISource::IsExprAlias(const TString& column) const { std::array<EExprSeat, 5> exprSeats = {{EExprSeat::FlattenBy, EExprSeat::FlattenByExpr, EExprSeat::GroupBy, EExprSeat::WindowPartitionBy, EExprSeat::DistinctAggr}}; - for (auto seat: exprSeats) { + for (auto seat : exprSeats) { if (IsAlias(seat, column)) { return true; } @@ -362,7 +358,7 @@ bool ISource::IsExprSeat(EExprSeat exprSeat, EExprType type) const { if (!expressions) { return false; } - for (const auto& exprNode: expressions) { + for (const auto& exprNode : expressions) { if (exprNode->GetLabel()) { return type == EExprType::WithExpression; } @@ -384,7 +380,7 @@ const TString* ISource::GetWindowName() const { bool ISource::IsCalcOverWindow() const { return !AggregationOverWindow_.empty() || !FuncOverWindow_.empty() || - AnyOf(WinSpecs_, [](const auto& item) { return item.second->Session; }); + AnyOf(WinSpecs_, [](const auto& item) { return item.second->Session; }); } bool ISource::IsOverWindowSource() const { @@ -407,7 +403,7 @@ TNodePtr ISource::PrepareSamplingRate(TPosition pos, ESampleClause clause, TNode if (ESampleClause::Sample == clause) { samplingRate = Y("*", samplingRate, Y("Double", Q("100"))); } - auto ensureLow = Y("Ensure", "samplingRate", Y(">=", "samplingRate", Y("Double", Q("0"))), Y("String", BuildQuotedAtom(pos, "Expected sampling rate to be nonnegative"))); + auto ensureLow = Y("Ensure", "samplingRate", Y(">=", "samplingRate", Y("Double", Q("0"))), Y("String", BuildQuotedAtom(pos, "Expected sampling rate to be nonnegative"))); auto ensureHigh = Y("Ensure", "samplingRate", Y("<=", "samplingRate", Y("Double", Q("100"))), Y("String", BuildQuotedAtom(pos, "Sampling rate is over 100%"))); auto block(Y(Y("let", "samplingRate", samplingRate))); @@ -417,7 +413,6 @@ TNodePtr ISource::PrepareSamplingRate(TPosition pos, ESampleClause clause, TNode return samplingRate; } - bool ISource::SetSamplingOptions(TContext& ctx, TPosition pos, ESampleClause sampleClause, @@ -474,7 +469,7 @@ TNodePtr ISource::BuildFilterLambda() { TNodePtr ISource::BuildFlattenByColumns(const TString& label) { auto columnsList = Y("FlattenByColumns", Q(FlattenMode_), label); - for (const auto& column: Expressions(EExprSeat::FlattenBy)) { + for (const auto& column : Expressions(EExprSeat::FlattenBy)) { const auto columnNamePtr = column->GetColumnName(); YQL_ENSURE(columnNamePtr); if (column->GetLabel().empty()) { @@ -494,7 +489,7 @@ namespace { TNodePtr BuildLambdaBodyForExprAliases(TPosition pos, const TVector<TNodePtr>& exprs, bool override, bool persistable) { auto structObj = BuildAtom(pos, "row", TNodeFlags::Default); - for (const auto& exprNode: exprs) { + for (const auto& exprNode : exprs) { const auto name = exprNode->GetLabel(); YQL_ENSURE(name); if (override) { @@ -512,7 +507,7 @@ TNodePtr BuildLambdaBodyForExprAliases(TPosition pos, const TVector<TNodePtr>& e return structObj->Y("AsList", structObj); } -} +} // namespace TNodePtr ISource::BuildPreaggregatedMap(TContext& ctx) { Y_UNUSED(ctx); @@ -537,7 +532,7 @@ TNodePtr ISource::BuildPreaggregatedMap(TContext& ctx) { ctx.GroupByExprAfterWhere || !ctx.FailOnGroupByExprOverride, ctx.PersistableFlattenAndAggrExprs); auto lambda = BuildLambda(Pos_, Y("row"), body); - res = res ? Y("FlatMap", res, lambda) : Y("FlatMap", "core", lambda); + res = res ? Y("FlatMap", res, lambda) : Y("FlatMap", "core", lambda); } return res; } @@ -550,7 +545,7 @@ TNodePtr ISource::BuildPreFlattenMap(TContext& ctx) { TNodePtr ISource::BuildPrewindowMap(TContext& ctx) { auto feed = BuildAtom(Pos_, "row", TNodeFlags::Default); - for (const auto& exprNode: Expressions(EExprSeat::WindowPartitionBy)) { + for (const auto& exprNode : Expressions(EExprSeat::WindowPartitionBy)) { const auto name = exprNode->GetLabel(); if (name && !dynamic_cast<const TSessionWindow*>(exprNode.Get())) { feed = Y("AddMember", feed, Q(name), exprNode); @@ -582,18 +577,18 @@ bool ISource::SetSamplingRate(TContext& ctx, ESampleClause clause, TNodePtr samp std::pair<TNodePtr, bool> ISource::BuildAggregation(const TString& label, TContext& ctx) { if (GroupKeys_.empty() && Aggregations_.empty() && !IsCompositeSource() && !LegacyHoppingWindowSpec_) { - return { nullptr, true }; + return {nullptr, true}; } auto keysTuple = Y(); YQL_ENSURE(GroupKeys_.size() == OrderedGroupKeys_.size()); - for (const auto& key: OrderedGroupKeys_) { + for (const auto& key : OrderedGroupKeys_) { YQL_ENSURE(GroupKeys_.contains(key)); keysTuple = L(keysTuple, BuildQuotedAtom(Pos_, key)); } std::map<std::pair<bool, TString>, std::vector<IAggregation*>> genericAggrs; - for (const auto& aggr: Aggregations_) { + for (const auto& aggr : Aggregations_) { if (auto key = aggr->GetGenericKey()) { genericAggrs[{aggr->IsDistinct(), *key}].emplace_back(aggr.Get()); } @@ -608,12 +603,12 @@ std::pair<TNodePtr, bool> ISource::BuildAggregation(const TString& label, TConte const auto listType = Y("TypeOf", label); auto aggrArgs = Y(); const bool overState = GroupBySuffix_ == "CombineState" || GroupBySuffix_ == "MergeState" || - GroupBySuffix_ == "MergeFinalize" || GroupBySuffix_ == "MergeManyFinalize"; + GroupBySuffix_ == "MergeFinalize" || GroupBySuffix_ == "MergeManyFinalize"; const bool allowAggApply = !LegacyHoppingWindowSpec_ && !SessionWindow_ && !HoppingWindow_; - for (const auto& aggr: Aggregations_) { + for (const auto& aggr : Aggregations_) { auto res = aggr->AggregationTraits(listType, overState, GroupBySuffix_ == "MergeManyFinalize", allowAggApply, ctx); if (!res.second) { - return { nullptr, false }; + return {nullptr, false}; } if (res.first) { @@ -645,7 +640,7 @@ std::pair<TNodePtr, bool> ISource::BuildAggregation(const TString& label, TConte auto sessionWindow = dynamic_cast<TSessionWindow*>(SessionWindow_.Get()); YQL_ENSURE(sessionWindow); options = L(options, Q(Y(Q("session"), - Q(Y(BuildQuotedAtom(Pos_, SessionWindow_->GetLabel()), sessionWindow->BuildTraits(label)))))); + Q(Y(BuildQuotedAtom(Pos_, SessionWindow_->GetLabel()), sessionWindow->BuildTraits(label)))))); } if (HoppingWindow_) { @@ -653,10 +648,10 @@ std::pair<TNodePtr, bool> ISource::BuildAggregation(const TString& label, TConte auto hoppingWindow = dynamic_cast<THoppingWindow*>(HoppingWindow_.Get()); YQL_ENSURE(hoppingWindow); options = L(options, Q(Y(Q("hopping"), - Q(Y(BuildQuotedAtom(Pos_, HoppingWindow_->GetLabel()), hoppingWindow->BuildTraits(label)))))); + Q(Y(BuildQuotedAtom(Pos_, HoppingWindow_->GetLabel()), hoppingWindow->BuildTraits(label)))))); } - return { Y("AssumeColumnOrderPartial", Y("Aggregate" + GroupBySuffix_, label, Q(keysTuple), Q(aggrArgs), Q(options)), Q(keysTuple)), true }; + return {Y("AssumeColumnOrderPartial", Y("Aggregate" + GroupBySuffix_, label, Q(keysTuple), Q(aggrArgs), Q(options)), Q(keysTuple)), true}; } TMaybe<TString> ISource::FindColumnMistype(const TString& name) const { @@ -671,7 +666,7 @@ void ISource::AddDependentSource(TSourcePtr usedSource) { class TYqlFrameBound final: public TCallNode { public: TYqlFrameBound(TPosition pos, TNodePtr bound) - : TCallNode(pos, "EvaluateExpr", 1, 1, { bound }) + : TCallNode(pos, "EvaluateExpr", 1, 1, {bound}) , FakeSource_(BuildFakeSource(pos)) { } @@ -691,6 +686,7 @@ public: TNodePtr DoClone() const final { return new TYqlFrameBound(Pos_, Args_[0]->Clone()); } + private: TSourcePtr FakeSource_; }; @@ -698,10 +694,17 @@ private: TNodePtr BuildFrameNode(const TFrameBound& frame, EFrameType frameType) { TString settingStr; switch (frame.Settings) { - case FramePreceding: settingStr = "preceding"; break; - case FrameCurrentRow: settingStr = "currentRow"; break; - case FrameFollowing: settingStr = "following"; break; - default: YQL_ENSURE(false, "Unexpected frame setting"); + case FramePreceding: + settingStr = "preceding"; + break; + case FrameCurrentRow: + settingStr = "currentRow"; + break; + case FrameFollowing: + settingStr = "following"; + break; + default: + YQL_ENSURE(false, "Unexpected frame setting"); } TNodePtr node = frame.Bound; @@ -731,10 +734,10 @@ TNodePtr BuildFrameNode(const TFrameBound& frame, EFrameType frameType) { if (frame.Settings == FramePreceding) { value = -value; } - node = new TCallNodeImpl(pos, "Int32", { BuildQuotedAtom(pos, ToString(value), TNodeFlags::Default) }); + node = new TCallNodeImpl(pos, "Int32", {BuildQuotedAtom(pos, ToString(value), TNodeFlags::Default)}); } else { if (frame.Settings == FramePreceding) { - node = new TCallNodeImpl(pos, "Minus", { node->Clone() }); + node = new TCallNodeImpl(pos, "Minus", {node->Clone()}); } node = new TYqlFrameBound(pos, node); } @@ -779,6 +782,7 @@ public: TNodePtr DoClone() const final { return new TSessionWindowTraits(Pos_, CloneContainer(Args_)); } + private: TSourcePtr FakeSource_; }; @@ -820,9 +824,15 @@ TNodePtr ISource::BuildCalcOverWindow(TContext& ctx, const TString& label) { auto frames = Y(); TString frameType; switch (spec->Frame->FrameType) { - case EFrameType::FrameByRows: frameType = "WinOnRows"; break; - case EFrameType::FrameByRange: frameType = "WinOnRange"; break; - case EFrameType::FrameByGroups: frameType = "WinOnGroups"; break; + case EFrameType::FrameByRows: + frameType = "WinOnRows"; + break; + case EFrameType::FrameByRange: + frameType = "WinOnRange"; + break; + case EFrameType::FrameByGroups: + frameType = "WinOnGroups"; + break; } YQL_ENSURE(frameType); auto callOnFrame = Y(frameType, BuildWindowFrame(*spec->Frame, spec->IsCompact)); @@ -837,7 +847,7 @@ TNodePtr ISource::BuildCalcOverWindow(TContext& ctx, const TString& label) { frames = L(frames, callOnFrame); auto keysTuple = Y(); - for (const auto& key: spec->Partitions) { + for (const auto& key : spec->Partitions) { if (!dynamic_cast<TSessionWindow*>(key.Get())) { keysTuple = L(keysTuple, AliasOrColumn(key, GetJoin())); } @@ -912,7 +922,7 @@ bool ISource::IsJoinKeysInitializing() const { } bool ISource::DoInit(TContext& ctx, ISource* src) { - for (auto& column: Expressions(EExprSeat::FlattenBy)) { + for (auto& column : Expressions(EExprSeat::FlattenBy)) { if (!column->Init(ctx, this)) { return false; } @@ -926,7 +936,7 @@ bool ISource::DoInit(TContext& ctx, ISource* src) { } bool ISource::InitFilters(TContext& ctx) { - for (auto& filter: Filters_) { + for (auto& filter : Filters_) { if (!filter->Init(ctx, this)) { return false; } @@ -957,7 +967,7 @@ void ISource::FillSortParts(const TVector<TSortSpecificationPtr>& orderBy, TNode } else { auto exprList = Y(); sortDirection = Y(); - for (const auto& sortSpec: orderBy) { + for (const auto& sortSpec : orderBy) { const auto asc = sortSpec->Ascending; sortDirection = L(sortDirection, Y("Bool", Q(asc ? "true" : "false"))); exprList = L(exprList, Y("PersistableRepr", sortSpec->OrderExpr)); @@ -986,7 +996,7 @@ bool ISource::HasMatchRecognize() const { return static_cast<bool>(MatchRecognizeBuilder_); } -TNodePtr ISource::BuildMatchRecognize(TContext& ctx, TString&& inputTable){ +TNodePtr ISource::BuildMatchRecognize(TContext& ctx, TString&& inputTable) { YQL_ENSURE(HasMatchRecognize()); return MatchRecognizeBuilder_->Build(ctx, std::move(inputTable), this); }; diff --git a/yql/essentials/sql/v1/source.h b/yql/essentials/sql/v1/source.h index bd3a0327cb2..6c52af6be1f 100644 --- a/yql/essentials/sql/v1/source.h +++ b/yql/essentials/sql/v1/source.h @@ -4,335 +4,331 @@ #include <library/cpp/containers/sorted_vector/sorted_vector.h> namespace NSQLTranslationV1 { - using TColumnsSets = NSorted::TSimpleSet<NSorted::TSimpleSet<TString>>; - - class ISource; - typedef TIntrusivePtr<ISource> TSourcePtr; - - struct TTableRef { - TString RefName; - TString Service; - TDeferredAtom Cluster; - TNodePtr Keys; - TNodePtr Options; - TSourcePtr Source; - - TTableRef() = default; - TTableRef(const TString& refName, const TString& service, const TDeferredAtom& cluster, TNodePtr keys); - TTableRef(const TTableRef&) = default; - TTableRef& operator=(const TTableRef&) = default; - - TString ShortName() const; - }; - - typedef TVector<TTableRef> TTableList; - - - class IJoin; - class ISource: public INode { - public: - virtual ~ISource(); - - virtual bool IsFake() const; - virtual void AllColumns(); - virtual const TColumns* GetColumns() const; - virtual void GetInputTables(TTableList& tableList) const; - /// in case of error unfilled, flag show if ensure column name - virtual TMaybe<bool> AddColumn(TContext& ctx, TColumnNode& column); - virtual void FinishColumns(); - virtual bool AddExpressions(TContext& ctx, const TVector<TNodePtr>& columns, EExprSeat exprSeat); - virtual void SetFlattenByMode(const TString& mode); - virtual void MarkFlattenColumns(); - virtual bool IsFlattenColumns() const; - virtual bool AddFilter(TContext& ctx, TNodePtr filter); - virtual bool AddGroupKey(TContext& ctx, const TString& column); - virtual void SetCompactGroupBy(bool compactGroupBy); - virtual TStringBuf GetGroupBySuffix() const; - virtual void SetGroupBySuffix(const TString& suffix); - virtual TString MakeLocalName(const TString& name); - virtual bool AddAggregation(TContext& ctx, TAggregationPtr aggr); - virtual bool AddFuncOverWindow(TContext& ctx, TNodePtr expr); - virtual void AddTmpWindowColumn(const TString& column); - virtual void SetMatchRecognize(TMatchRecognizeBuilderPtr matchRecognize); - virtual const TVector<TString>& GetTmpWindowColumns() const; - virtual bool HasAggregations() const; - virtual void AddWindowSpecs(TWinSpecs winSpecs); - virtual bool AddAggregationOverWindow(TContext& ctx, const TString& windowName, TAggregationPtr func); - virtual bool AddFuncOverWindow(TContext& ctx, const TString& windowName, TNodePtr func); - virtual void SetLegacyHoppingWindowSpec(TLegacyHoppingWindowSpecPtr spec); - virtual TLegacyHoppingWindowSpecPtr GetLegacyHoppingWindowSpec() const; - virtual TNodePtr GetSessionWindowSpec() const; - virtual TNodePtr GetHoppingWindowSpec() const; - virtual bool IsCompositeSource() const; - virtual bool IsGroupByColumn(const TString& column) const; - virtual bool IsFlattenByColumns() const; - virtual bool IsFlattenByExprs() const; - virtual bool IsCalcOverWindow() const; - virtual bool IsOverWindowSource() const; - virtual bool IsStream() const; - virtual EOrderKind GetOrderKind() const; - virtual TWriteSettings GetWriteSettings() const; - TNodePtr PrepareSamplingRate(TPosition pos, ESampleClause clause, TNodePtr samplingRate); - virtual bool SetSamplingOptions(TContext& ctx, TPosition pos, ESampleClause clause, ESampleMode mode, TNodePtr samplingRate, TNodePtr samplingSeed); - virtual bool SetTableHints(TContext& ctx, TPosition pos, const TTableHints& hints, const TTableHints& contextHints); - virtual bool AddGrouping(TContext& ctx, const TVector<TString>& columns, TString& groupingColumn); - virtual size_t GetGroupingColumnsCount() const; - virtual TNodePtr BuildFilter(TContext& ctx, const TString& label); - virtual TNodePtr BuildFilterLambda(); - virtual TNodePtr BuildFlattenByColumns(const TString& label); - virtual TNodePtr BuildFlattenColumns(const TString& label); - virtual TNodePtr BuildPreaggregatedMap(TContext& ctx); - virtual TNodePtr BuildPreFlattenMap(TContext& ctx); - virtual TNodePtr BuildPrewindowMap(TContext& ctx); - virtual std::pair<TNodePtr, bool> BuildAggregation(const TString& label, TContext& ctx); - virtual TNodePtr BuildCalcOverWindow(TContext& ctx, const TString& label); - virtual TNodePtr BuildSort(TContext& ctx, const TString& label); - virtual TNodePtr BuildCleanupColumns(TContext& ctx, const TString& label); - virtual TNodePtr BuildGroupingColumns(const TString& label); - virtual bool BuildSamplingLambda(TNodePtr& node); - virtual bool SetSamplingRate(TContext& ctx, ESampleClause clause, TNodePtr samplingRate); - virtual IJoin* GetJoin(); - virtual ISource* GetCompositeSource(); - virtual bool IsSelect() const; - virtual bool IsTableSource() const; - virtual bool ShouldUseSourceAsColumn(const TString& source) const; - virtual bool IsJoinKeysInitializing() const; - virtual const TString* GetWindowName() const; - virtual bool HasMatchRecognize() const; - virtual TNodePtr BuildMatchRecognize(TContext& ctx, TString&& inputTable); - virtual bool DoInit(TContext& ctx, ISource* src); - virtual TNodePtr Build(TContext& ctx) = 0; - - virtual TMaybe<TString> FindColumnMistype(const TString& name) const; - - virtual bool InitFilters(TContext& ctx); - void AddDependentSource(TSourcePtr usedSource); - bool IsAlias(EExprSeat exprSeat, const TString& label) const; - bool IsExprAlias(const TString& label) const; - bool IsExprSeat(EExprSeat exprSeat, EExprType type = EExprType::WithExpression) const; - TString GetGroupByColumnAlias(const TString& column) const; - const TVector<TNodePtr>& Expressions(EExprSeat exprSeat) const; - - virtual TWindowSpecificationPtr FindWindowSpecification(TContext& ctx, const TString& windowName) const; - - TIntrusivePtr<ISource> CloneSource() const; - TNodePtr BuildSortSpec(const TVector<TSortSpecificationPtr>& orderBy, const TString& label, bool traits, bool assume); - - protected: - ISource(TPosition pos); - virtual TAstNode* Translate(TContext& ctx) const; - - void FillSortParts(const TVector<TSortSpecificationPtr>& orderBy, TNodePtr& sortKeySelector, TNodePtr& sortDirection); - - TVector<TNodePtr>& Expressions(EExprSeat exprSeat); - TNodePtr AliasOrColumn(const TNodePtr& node, bool withSource); - - TNodePtr BuildWindowFrame(const TFrameSpecification& spec, bool isCompact); - - THashSet<TString> ExprAliases_; - THashSet<TString> FlattenByAliases_; - THashMap<TString, TString> GroupByColumnAliases_; - TVector<TNodePtr> Filters_; - bool CompactGroupBy_ = false; - TString GroupBySuffix_; - TSet<TString> GroupKeys_; - TVector<TString> OrderedGroupKeys_; - std::array<TVector<TNodePtr>, static_cast<unsigned>(EExprSeat::Max)> NamedExprs_; - TVector<TAggregationPtr> Aggregations_; - TMap<TString, TVector<TAggregationPtr>> AggregationOverWindow_; - TMap<TString, TVector<TNodePtr>> FuncOverWindow_; - TWinSpecs WinSpecs_; - TLegacyHoppingWindowSpecPtr LegacyHoppingWindowSpec_; - TNodePtr SessionWindow_; - TNodePtr HoppingWindow_; - TVector<TSourcePtr> UsedSources_; - TString FlattenMode_; - bool FlattenColumns_ = false; - THashMap<TString, ui32> GenIndexes_; - TVector<TString> TmpWindowColumns_; - TNodePtr SamplingRate_; - TMatchRecognizeBuilderPtr MatchRecognizeBuilder_; - }; - - template<> - inline TVector<TSourcePtr> CloneContainer<TSourcePtr>(const TVector<TSourcePtr>& args) { - TVector<TSourcePtr> cloneArgs; - cloneArgs.reserve(args.size()); - for (const auto& arg: args) { - cloneArgs.emplace_back(arg ? arg->CloneSource() : nullptr); - } - return cloneArgs; +using TColumnsSets = NSorted::TSimpleSet<NSorted::TSimpleSet<TString>>; + +class ISource; +typedef TIntrusivePtr<ISource> TSourcePtr; + +struct TTableRef { + TString RefName; + TString Service; + TDeferredAtom Cluster; + TNodePtr Keys; + TNodePtr Options; + TSourcePtr Source; + + TTableRef() = default; + TTableRef(const TString& refName, const TString& service, const TDeferredAtom& cluster, TNodePtr keys); + TTableRef(const TTableRef&) = default; + TTableRef& operator=(const TTableRef&) = default; + + TString ShortName() const; +}; + +typedef TVector<TTableRef> TTableList; + +class IJoin; +class ISource: public INode { +public: + virtual ~ISource(); + + virtual bool IsFake() const; + virtual void AllColumns(); + virtual const TColumns* GetColumns() const; + virtual void GetInputTables(TTableList& tableList) const; + /// in case of error unfilled, flag show if ensure column name + virtual TMaybe<bool> AddColumn(TContext& ctx, TColumnNode& column); + virtual void FinishColumns(); + virtual bool AddExpressions(TContext& ctx, const TVector<TNodePtr>& columns, EExprSeat exprSeat); + virtual void SetFlattenByMode(const TString& mode); + virtual void MarkFlattenColumns(); + virtual bool IsFlattenColumns() const; + virtual bool AddFilter(TContext& ctx, TNodePtr filter); + virtual bool AddGroupKey(TContext& ctx, const TString& column); + virtual void SetCompactGroupBy(bool compactGroupBy); + virtual TStringBuf GetGroupBySuffix() const; + virtual void SetGroupBySuffix(const TString& suffix); + virtual TString MakeLocalName(const TString& name); + virtual bool AddAggregation(TContext& ctx, TAggregationPtr aggr); + virtual bool AddFuncOverWindow(TContext& ctx, TNodePtr expr); + virtual void AddTmpWindowColumn(const TString& column); + virtual void SetMatchRecognize(TMatchRecognizeBuilderPtr matchRecognize); + virtual const TVector<TString>& GetTmpWindowColumns() const; + virtual bool HasAggregations() const; + virtual void AddWindowSpecs(TWinSpecs winSpecs); + virtual bool AddAggregationOverWindow(TContext& ctx, const TString& windowName, TAggregationPtr func); + virtual bool AddFuncOverWindow(TContext& ctx, const TString& windowName, TNodePtr func); + virtual void SetLegacyHoppingWindowSpec(TLegacyHoppingWindowSpecPtr spec); + virtual TLegacyHoppingWindowSpecPtr GetLegacyHoppingWindowSpec() const; + virtual TNodePtr GetSessionWindowSpec() const; + virtual TNodePtr GetHoppingWindowSpec() const; + virtual bool IsCompositeSource() const; + virtual bool IsGroupByColumn(const TString& column) const; + virtual bool IsFlattenByColumns() const; + virtual bool IsFlattenByExprs() const; + virtual bool IsCalcOverWindow() const; + virtual bool IsOverWindowSource() const; + virtual bool IsStream() const; + virtual EOrderKind GetOrderKind() const; + virtual TWriteSettings GetWriteSettings() const; + TNodePtr PrepareSamplingRate(TPosition pos, ESampleClause clause, TNodePtr samplingRate); + virtual bool SetSamplingOptions(TContext& ctx, TPosition pos, ESampleClause clause, ESampleMode mode, TNodePtr samplingRate, TNodePtr samplingSeed); + virtual bool SetTableHints(TContext& ctx, TPosition pos, const TTableHints& hints, const TTableHints& contextHints); + virtual bool AddGrouping(TContext& ctx, const TVector<TString>& columns, TString& groupingColumn); + virtual size_t GetGroupingColumnsCount() const; + virtual TNodePtr BuildFilter(TContext& ctx, const TString& label); + virtual TNodePtr BuildFilterLambda(); + virtual TNodePtr BuildFlattenByColumns(const TString& label); + virtual TNodePtr BuildFlattenColumns(const TString& label); + virtual TNodePtr BuildPreaggregatedMap(TContext& ctx); + virtual TNodePtr BuildPreFlattenMap(TContext& ctx); + virtual TNodePtr BuildPrewindowMap(TContext& ctx); + virtual std::pair<TNodePtr, bool> BuildAggregation(const TString& label, TContext& ctx); + virtual TNodePtr BuildCalcOverWindow(TContext& ctx, const TString& label); + virtual TNodePtr BuildSort(TContext& ctx, const TString& label); + virtual TNodePtr BuildCleanupColumns(TContext& ctx, const TString& label); + virtual TNodePtr BuildGroupingColumns(const TString& label); + virtual bool BuildSamplingLambda(TNodePtr& node); + virtual bool SetSamplingRate(TContext& ctx, ESampleClause clause, TNodePtr samplingRate); + virtual IJoin* GetJoin(); + virtual ISource* GetCompositeSource(); + virtual bool IsSelect() const; + virtual bool IsTableSource() const; + virtual bool ShouldUseSourceAsColumn(const TString& source) const; + virtual bool IsJoinKeysInitializing() const; + virtual const TString* GetWindowName() const; + virtual bool HasMatchRecognize() const; + virtual TNodePtr BuildMatchRecognize(TContext& ctx, TString&& inputTable); + virtual bool DoInit(TContext& ctx, ISource* src); + virtual TNodePtr Build(TContext& ctx) = 0; + + virtual TMaybe<TString> FindColumnMistype(const TString& name) const; + + virtual bool InitFilters(TContext& ctx); + void AddDependentSource(TSourcePtr usedSource); + bool IsAlias(EExprSeat exprSeat, const TString& label) const; + bool IsExprAlias(const TString& label) const; + bool IsExprSeat(EExprSeat exprSeat, EExprType type = EExprType::WithExpression) const; + TString GetGroupByColumnAlias(const TString& column) const; + const TVector<TNodePtr>& Expressions(EExprSeat exprSeat) const; + + virtual TWindowSpecificationPtr FindWindowSpecification(TContext& ctx, const TString& windowName) const; + + TIntrusivePtr<ISource> CloneSource() const; + TNodePtr BuildSortSpec(const TVector<TSortSpecificationPtr>& orderBy, const TString& label, bool traits, bool assume); + +protected: + ISource(TPosition pos); + virtual TAstNode* Translate(TContext& ctx) const; + + void FillSortParts(const TVector<TSortSpecificationPtr>& orderBy, TNodePtr& sortKeySelector, TNodePtr& sortDirection); + + TVector<TNodePtr>& Expressions(EExprSeat exprSeat); + TNodePtr AliasOrColumn(const TNodePtr& node, bool withSource); + + TNodePtr BuildWindowFrame(const TFrameSpecification& spec, bool isCompact); + + THashSet<TString> ExprAliases_; + THashSet<TString> FlattenByAliases_; + THashMap<TString, TString> GroupByColumnAliases_; + TVector<TNodePtr> Filters_; + bool CompactGroupBy_ = false; + TString GroupBySuffix_; + TSet<TString> GroupKeys_; + TVector<TString> OrderedGroupKeys_; + std::array<TVector<TNodePtr>, static_cast<unsigned>(EExprSeat::Max)> NamedExprs_; + TVector<TAggregationPtr> Aggregations_; + TMap<TString, TVector<TAggregationPtr>> AggregationOverWindow_; + TMap<TString, TVector<TNodePtr>> FuncOverWindow_; + TWinSpecs WinSpecs_; + TLegacyHoppingWindowSpecPtr LegacyHoppingWindowSpec_; + TNodePtr SessionWindow_; + TNodePtr HoppingWindow_; + TVector<TSourcePtr> UsedSources_; + TString FlattenMode_; + bool FlattenColumns_ = false; + THashMap<TString, ui32> GenIndexes_; + TVector<TString> TmpWindowColumns_; + TNodePtr SamplingRate_; + TMatchRecognizeBuilderPtr MatchRecognizeBuilder_; +}; + +template <> +inline TVector<TSourcePtr> CloneContainer<TSourcePtr>(const TVector<TSourcePtr>& args) { + TVector<TSourcePtr> cloneArgs; + cloneArgs.reserve(args.size()); + for (const auto& arg : args) { + cloneArgs.emplace_back(arg ? arg->CloneSource() : nullptr); } - - TSourcePtr MoveOutIfSource(TNodePtr& node); - - struct TJoinLinkSettings { - enum class EStrategy { - Default, - SortedMerge, - StreamLookup, - ForceMap, - ForceGrace - }; - EStrategy Strategy = EStrategy::Default; - TVector<TString> Values; - bool Compact = false; - }; - - class IJoin: public ISource { - public: - virtual ~IJoin(); - - virtual IJoin* GetJoin(); - virtual TNodePtr BuildJoinKeys(TContext& ctx, const TVector<TDeferredAtom>& names) = 0; - virtual void SetupJoin(const TString& joinOp, TNodePtr joinExpr, const TJoinLinkSettings& linkSettings) = 0; - virtual const THashMap<TString, THashSet<TString>>& GetSameKeysMap() const = 0; - virtual TVector<TString> GetJoinLabels() const = 0; - - protected: - IJoin(TPosition pos); - }; - - class TSessionWindow final : public INode { - public: - TSessionWindow(TPosition pos, const TVector<TNodePtr>& args); - void MarkValid(); - TNodePtr BuildTraits(const TString& label) const; - private: - bool DoInit(TContext& ctx, ISource* src) override; - TAstNode* Translate(TContext&) const override; - void DoUpdateState() const override; - TNodePtr DoClone() const override; - TString GetOpName() const override; - - TVector<TNodePtr> Args_; - TSourcePtr FakeSource_; - TNodePtr Node_; - bool Valid_; - }; - - class THoppingWindow final : public INode { - public: - THoppingWindow(TPosition pos, TVector<TNodePtr> args); - TNodePtr BuildTraits(const TString& label) const; - TNodePtr GetInterval() const; - void MarkValid(); - - private: - bool DoInit(TContext& ctx, ISource* src) override; - TAstNode* Translate(TContext&) const override; - void DoUpdateState() const override; - TNodePtr DoClone() const override; - TString GetOpName() const override; - TNodePtr ProcessIntervalParam(const TNodePtr& val) const; - - private: - TVector<TNodePtr> Args_; - TSourcePtr FakeSource_; - TNodePtr TimeExtractor_; - TNodePtr Hop_; - TNodePtr Interval_; - const TNodePtr Delay_ = Y("Interval", Q("0")); - const TString DataWatermarks_ = "true"; - bool Valid_; - }; - - - // Implemented in join.cpp - TString NormalizeJoinOp(const TString& joinOp); - TSourcePtr BuildEquiJoin(TPosition pos, TVector<TSourcePtr>&& sources, TVector<bool>&& anyFlags, bool strictJoinKeyTypes); - - // Implemented in select.cpp - TNodePtr BuildSubquery(TSourcePtr source, const TString& alias, bool inSubquery, int ensureTupleSize, TScopedStatePtr scoped); - TNodePtr BuildSubqueryRef(TNodePtr subquery, const TString& alias, int tupleIndex = -1); - bool IsSubqueryRef(const TSourcePtr& source); - - TNodePtr BuildInvalidSubqueryRef(TPosition subqueryPos); - TNodePtr BuildSourceNode(TPosition pos, TSourcePtr source, bool checkExist = false, bool withTables = false); - TSourcePtr BuildMuxSource(TPosition pos, TVector<TSourcePtr>&& sources); - TSourcePtr BuildFakeSource(TPosition pos, bool missingFrom = false, bool inSubquery = false); - TSourcePtr BuildNodeSource(TPosition pos, const TNodePtr& node, bool wrapToList = false, bool wrapByTableSource = false); - TSourcePtr BuildTableSource(TPosition pos, const TTableRef& table, const TString& label = TString()); - TSourcePtr BuildInnerSource(TPosition pos, TNodePtr node, const TString& service, const TDeferredAtom& cluster, const TString& label = TString()); - TSourcePtr BuildRefColumnSource(TPosition pos, const TString& partExpression); - TSourcePtr BuildSelectOp(TPosition pos, TVector<TSourcePtr>&& sources, const TString& op, bool quantifierAll, const TWriteSettings& settings); - TSourcePtr BuildOverWindowSource(TPosition pos, const TString& windowName, ISource* origSource); - - TNodePtr BuildOrderBy(TPosition pos, const TVector<TNodePtr>& keys, const TVector<bool>& order); - TNodePtr BuildSkipTake(TPosition pos, const TNodePtr& skip, const TNodePtr& take); - - - TSourcePtr BuildSelectCore( - TContext& ctx, - TPosition pos, - TSourcePtr source, - const TVector<TNodePtr>& groupByExpr, - const TVector<TNodePtr>& groupBy, - bool compactGroupBy, - const TString& groupBySuffix, - bool assumeSorted, - const TVector<TSortSpecificationPtr>& orderBy, - TNodePtr having, - TWinSpecs&& windowSpec, - TLegacyHoppingWindowSpecPtr legacyHoppingWindowSpec, - TVector<TNodePtr>&& terms, - bool distinct, - TVector<TNodePtr>&& without, - bool forceWithout, - bool selectStream, - const TWriteSettings& settings, - TColumnsSets&& uniqueSets, - TColumnsSets&& distinctSets - ); - TSourcePtr BuildSelect(TPosition pos, TSourcePtr source, TNodePtr skipTake); - TSourcePtr BuildAnyColumnSource(TPosition pos); - - - enum class ReduceMode { - ByPartition, - ByAll, + return cloneArgs; +} + +TSourcePtr MoveOutIfSource(TNodePtr& node); + +struct TJoinLinkSettings { + enum class EStrategy { + Default, + SortedMerge, + StreamLookup, + ForceMap, + ForceGrace }; - TSourcePtr BuildReduce(TPosition pos, ReduceMode mode, TSourcePtr source, TVector<TSortSpecificationPtr>&& orderBy, - TVector<TNodePtr>&& keys, TVector<TNodePtr>&& args, TNodePtr udf, TNodePtr having, const TWriteSettings& settings, - const TVector<TSortSpecificationPtr>& assumeOrderBy, bool listCall); - TSourcePtr BuildProcess(TPosition pos, TSourcePtr source, TNodePtr with, bool withExtFunction, TVector<TNodePtr>&& terms, bool listCall, - bool processStream, const TWriteSettings& settings, const TVector<TSortSpecificationPtr>& assumeOrderBy); - - TNodePtr BuildSelectResult(TPosition pos, TSourcePtr source, bool writeResult, bool inSubquery, TScopedStatePtr scoped); - - // Implemented in insert.cpp - TSourcePtr BuildWriteValues(TPosition pos, const TString& operationHumanName, const TVector<TString>& columnsHint, const TVector<TVector<TNodePtr>>& values); - TSourcePtr BuildWriteValues(TPosition pos, const TString& operationHumanName, const TVector<TString>& columnsHint, TSourcePtr source); - TSourcePtr BuildUpdateValues(TPosition pos, const TVector<TString>& columnsHint, const TVector<TNodePtr>& values); - - EWriteColumnMode ToWriteColumnsMode(ESQLWriteColumnMode sqlWriteColumnMode); - TNodePtr BuildEraseColumns(TPosition pos, const TVector<TString>& columns); - TNodePtr BuildIntoTableOptions(TPosition pos, const TVector<TString>& eraseColumns, const TTableHints& hints); - TNodePtr BuildWriteColumns(TPosition pos, TScopedStatePtr scoped, const TTableRef& table, EWriteColumnMode mode, TSourcePtr values, TNodePtr options = nullptr); - TNodePtr BuildUpdateColumns(TPosition pos, TScopedStatePtr scoped, const TTableRef& table, TSourcePtr values, TSourcePtr source, TNodePtr options = nullptr); - TNodePtr BuildBatchUpdate(TPosition pos, TScopedStatePtr scoped, const TTableRef& table, TSourcePtr values, TSourcePtr source, TNodePtr options = nullptr); - TNodePtr BuildDelete(TPosition pos, TScopedStatePtr scoped, const TTableRef& table, TSourcePtr source, TNodePtr options = nullptr); - TNodePtr BuildBatchDelete(TPosition pos, TScopedStatePtr scoped, const TTableRef& table, TSourcePtr source, TNodePtr options = nullptr); - - // Implemented in query.cpp - TNodePtr BuildAlterTable(TPosition pos, const TTableRef& tr, const TAlterTableParameters& params, TScopedStatePtr scoped); - TNodePtr BuildAlterDatabase(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TAlterDatabaseParameters& params,TScopedStatePtr scoped); - TNodePtr BuildTableKey(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TViewDescription& view); - TNodePtr BuildTableKeys(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TString& func, const TVector<TTableArg>& args); - TNodePtr BuildTopicKey(TPosition pos, const TDeferredAtom& cluster, const TDeferredAtom& name); - TNodePtr BuildInputOptions(TPosition pos, const TTableHints& hints); - TNodePtr BuildInputTables(TPosition pos, const TTableList& tables, bool inSubquery, TScopedStatePtr scoped); - TNodePtr BuildCreateTable(TPosition pos, const TTableRef& tr, bool existingOk, bool replaceIfExists, const TCreateTableParameters& params, TSourcePtr source, TScopedStatePtr scoped); - TNodePtr BuildAlterTable(TPosition pos, const TTableRef& tr, const TAlterTableParameters& params, TScopedStatePtr scoped); - TNodePtr BuildDropTable(TPosition pos, const TTableRef& table, bool missingOk, ETableType tableType, TScopedStatePtr scoped); - TNodePtr BuildWriteTable(TPosition pos, const TString& label, const TTableRef& table, EWriteColumnMode mode, TNodePtr options, - TScopedStatePtr scoped); - TNodePtr BuildAnalyze(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TAnalyzeParams& params, TScopedStatePtr scoped); - TNodePtr BuildShowCreate(TPosition pos, const TTableRef& table, const TString& type, TScopedStatePtr scoped); - TNodePtr BuildAlterSequence(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TString& id, const TSequenceParameters& params, TScopedStatePtr scoped); - TSourcePtr TryMakeSourceFromExpression(TPosition pos, TContext& ctx, const TString& currService, const TDeferredAtom& currCluster, - TNodePtr node, const TString& view = {}); - void MakeTableFromExpression(TPosition pos, TContext& ctx, TNodePtr node, TDeferredAtom& table, const TString& prefix = {}); - TDeferredAtom MakeAtomFromExpression(TPosition pos, TContext& ctx, TNodePtr node, const TString& prefix = {}); - TString NormalizeTypeString(const TString& str); -} // namespace NSQLTranslationV1 + EStrategy Strategy = EStrategy::Default; + TVector<TString> Values; + bool Compact = false; +}; + +class IJoin: public ISource { +public: + virtual ~IJoin(); + + virtual IJoin* GetJoin(); + virtual TNodePtr BuildJoinKeys(TContext& ctx, const TVector<TDeferredAtom>& names) = 0; + virtual void SetupJoin(const TString& joinOp, TNodePtr joinExpr, const TJoinLinkSettings& linkSettings) = 0; + virtual const THashMap<TString, THashSet<TString>>& GetSameKeysMap() const = 0; + virtual TVector<TString> GetJoinLabels() const = 0; + +protected: + IJoin(TPosition pos); +}; + +class TSessionWindow final: public INode { +public: + TSessionWindow(TPosition pos, const TVector<TNodePtr>& args); + void MarkValid(); + TNodePtr BuildTraits(const TString& label) const; + +private: + bool DoInit(TContext& ctx, ISource* src) override; + TAstNode* Translate(TContext&) const override; + void DoUpdateState() const override; + TNodePtr DoClone() const override; + TString GetOpName() const override; + + TVector<TNodePtr> Args_; + TSourcePtr FakeSource_; + TNodePtr Node_; + bool Valid_; +}; + +class THoppingWindow final: public INode { +public: + THoppingWindow(TPosition pos, TVector<TNodePtr> args); + TNodePtr BuildTraits(const TString& label) const; + TNodePtr GetInterval() const; + void MarkValid(); + +private: + bool DoInit(TContext& ctx, ISource* src) override; + TAstNode* Translate(TContext&) const override; + void DoUpdateState() const override; + TNodePtr DoClone() const override; + TString GetOpName() const override; + TNodePtr ProcessIntervalParam(const TNodePtr& val) const; + +private: + TVector<TNodePtr> Args_; + TSourcePtr FakeSource_; + TNodePtr TimeExtractor_; + TNodePtr Hop_; + TNodePtr Interval_; + const TNodePtr Delay_ = Y("Interval", Q("0")); + const TString DataWatermarks_ = "true"; + bool Valid_; +}; + +// Implemented in join.cpp +TString NormalizeJoinOp(const TString& joinOp); +TSourcePtr BuildEquiJoin(TPosition pos, TVector<TSourcePtr>&& sources, TVector<bool>&& anyFlags, bool strictJoinKeyTypes); + +// Implemented in select.cpp +TNodePtr BuildSubquery(TSourcePtr source, const TString& alias, bool inSubquery, int ensureTupleSize, TScopedStatePtr scoped); +TNodePtr BuildSubqueryRef(TNodePtr subquery, const TString& alias, int tupleIndex = -1); +bool IsSubqueryRef(const TSourcePtr& source); + +TNodePtr BuildInvalidSubqueryRef(TPosition subqueryPos); +TNodePtr BuildSourceNode(TPosition pos, TSourcePtr source, bool checkExist = false, bool withTables = false); +TSourcePtr BuildMuxSource(TPosition pos, TVector<TSourcePtr>&& sources); +TSourcePtr BuildFakeSource(TPosition pos, bool missingFrom = false, bool inSubquery = false); +TSourcePtr BuildNodeSource(TPosition pos, const TNodePtr& node, bool wrapToList = false, bool wrapByTableSource = false); +TSourcePtr BuildTableSource(TPosition pos, const TTableRef& table, const TString& label = TString()); +TSourcePtr BuildInnerSource(TPosition pos, TNodePtr node, const TString& service, const TDeferredAtom& cluster, const TString& label = TString()); +TSourcePtr BuildRefColumnSource(TPosition pos, const TString& partExpression); +TSourcePtr BuildSelectOp(TPosition pos, TVector<TSourcePtr>&& sources, const TString& op, bool quantifierAll, const TWriteSettings& settings); +TSourcePtr BuildOverWindowSource(TPosition pos, const TString& windowName, ISource* origSource); + +TNodePtr BuildOrderBy(TPosition pos, const TVector<TNodePtr>& keys, const TVector<bool>& order); +TNodePtr BuildSkipTake(TPosition pos, const TNodePtr& skip, const TNodePtr& take); + +TSourcePtr BuildSelectCore( + TContext& ctx, + TPosition pos, + TSourcePtr source, + const TVector<TNodePtr>& groupByExpr, + const TVector<TNodePtr>& groupBy, + bool compactGroupBy, + const TString& groupBySuffix, + bool assumeSorted, + const TVector<TSortSpecificationPtr>& orderBy, + TNodePtr having, + TWinSpecs&& windowSpec, + TLegacyHoppingWindowSpecPtr legacyHoppingWindowSpec, + TVector<TNodePtr>&& terms, + bool distinct, + TVector<TNodePtr>&& without, + bool forceWithout, + bool selectStream, + const TWriteSettings& settings, + TColumnsSets&& uniqueSets, + TColumnsSets&& distinctSets); +TSourcePtr BuildSelect(TPosition pos, TSourcePtr source, TNodePtr skipTake); +TSourcePtr BuildAnyColumnSource(TPosition pos); + +enum class ReduceMode { + ByPartition, + ByAll, +}; +TSourcePtr BuildReduce(TPosition pos, ReduceMode mode, TSourcePtr source, TVector<TSortSpecificationPtr>&& orderBy, + TVector<TNodePtr>&& keys, TVector<TNodePtr>&& args, TNodePtr udf, TNodePtr having, const TWriteSettings& settings, + const TVector<TSortSpecificationPtr>& assumeOrderBy, bool listCall); +TSourcePtr BuildProcess(TPosition pos, TSourcePtr source, TNodePtr with, bool withExtFunction, TVector<TNodePtr>&& terms, bool listCall, + bool processStream, const TWriteSettings& settings, const TVector<TSortSpecificationPtr>& assumeOrderBy); + +TNodePtr BuildSelectResult(TPosition pos, TSourcePtr source, bool writeResult, bool inSubquery, TScopedStatePtr scoped); + +// Implemented in insert.cpp +TSourcePtr BuildWriteValues(TPosition pos, const TString& operationHumanName, const TVector<TString>& columnsHint, const TVector<TVector<TNodePtr>>& values); +TSourcePtr BuildWriteValues(TPosition pos, const TString& operationHumanName, const TVector<TString>& columnsHint, TSourcePtr source); +TSourcePtr BuildUpdateValues(TPosition pos, const TVector<TString>& columnsHint, const TVector<TNodePtr>& values); + +EWriteColumnMode ToWriteColumnsMode(ESQLWriteColumnMode sqlWriteColumnMode); +TNodePtr BuildEraseColumns(TPosition pos, const TVector<TString>& columns); +TNodePtr BuildIntoTableOptions(TPosition pos, const TVector<TString>& eraseColumns, const TTableHints& hints); +TNodePtr BuildWriteColumns(TPosition pos, TScopedStatePtr scoped, const TTableRef& table, EWriteColumnMode mode, TSourcePtr values, TNodePtr options = nullptr); +TNodePtr BuildUpdateColumns(TPosition pos, TScopedStatePtr scoped, const TTableRef& table, TSourcePtr values, TSourcePtr source, TNodePtr options = nullptr); +TNodePtr BuildBatchUpdate(TPosition pos, TScopedStatePtr scoped, const TTableRef& table, TSourcePtr values, TSourcePtr source, TNodePtr options = nullptr); +TNodePtr BuildDelete(TPosition pos, TScopedStatePtr scoped, const TTableRef& table, TSourcePtr source, TNodePtr options = nullptr); +TNodePtr BuildBatchDelete(TPosition pos, TScopedStatePtr scoped, const TTableRef& table, TSourcePtr source, TNodePtr options = nullptr); + +// Implemented in query.cpp +TNodePtr BuildAlterTable(TPosition pos, const TTableRef& tr, const TAlterTableParameters& params, TScopedStatePtr scoped); +TNodePtr BuildAlterDatabase(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TAlterDatabaseParameters& params, TScopedStatePtr scoped); +TNodePtr BuildTableKey(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TViewDescription& view); +TNodePtr BuildTableKeys(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TString& func, const TVector<TTableArg>& args); +TNodePtr BuildTopicKey(TPosition pos, const TDeferredAtom& cluster, const TDeferredAtom& name); +TNodePtr BuildInputOptions(TPosition pos, const TTableHints& hints); +TNodePtr BuildInputTables(TPosition pos, const TTableList& tables, bool inSubquery, TScopedStatePtr scoped); +TNodePtr BuildCreateTable(TPosition pos, const TTableRef& tr, bool existingOk, bool replaceIfExists, const TCreateTableParameters& params, TSourcePtr source, TScopedStatePtr scoped); +TNodePtr BuildAlterTable(TPosition pos, const TTableRef& tr, const TAlterTableParameters& params, TScopedStatePtr scoped); +TNodePtr BuildDropTable(TPosition pos, const TTableRef& table, bool missingOk, ETableType tableType, TScopedStatePtr scoped); +TNodePtr BuildWriteTable(TPosition pos, const TString& label, const TTableRef& table, EWriteColumnMode mode, TNodePtr options, + TScopedStatePtr scoped); +TNodePtr BuildAnalyze(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TAnalyzeParams& params, TScopedStatePtr scoped); +TNodePtr BuildShowCreate(TPosition pos, const TTableRef& table, const TString& type, TScopedStatePtr scoped); +TNodePtr BuildAlterSequence(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TString& id, const TSequenceParameters& params, TScopedStatePtr scoped); +TSourcePtr TryMakeSourceFromExpression(TPosition pos, TContext& ctx, const TString& currService, const TDeferredAtom& currCluster, + TNodePtr node, const TString& view = {}); +void MakeTableFromExpression(TPosition pos, TContext& ctx, TNodePtr node, TDeferredAtom& table, const TString& prefix = {}); +TDeferredAtom MakeAtomFromExpression(TPosition pos, TContext& ctx, TNodePtr node, const TString& prefix = {}); +TString NormalizeTypeString(const TString& str); +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/sql.cpp b/yql/essentials/sql/v1/sql.cpp index 7ddc2a40b18..1fb88c6089b 100644 --- a/yql/essentials/sql/v1/sql.cpp +++ b/yql/essentials/sql/v1/sql.cpp @@ -42,7 +42,7 @@ TAstNode* SqlASTsToYqls(const std::vector<::NSQLv1Generated::TRule_sql_stmt_core } void SqlASTToYqlImpl(NYql::TAstParseResult& res, const google::protobuf::Message& protoAst, - TContext& ctx) { + TContext& ctx) { res.Root = SqlASTToYql(protoAst, ctx); res.Pool = std::move(ctx.Pool); if (!res.Root) { @@ -50,8 +50,7 @@ void SqlASTToYqlImpl(NYql::TAstParseResult& res, const google::protobuf::Message ctx.IncrementMonCounter("sql_errors", "AstToYqlError"); } else { ctx.IncrementMonCounter("sql_errors", "AstToYqlSilentError"); - ctx.Error() << "Error occurred on parse SQL query, but no error is collected" << - ", please send this request over bug report into YQL interface or write on yql@ maillist"; + ctx.Error() << "Error occurred on parse SQL query, but no error is collected" << ", please send this request over bug report into YQL interface or write on yql@ maillist"; } } else { ctx.WarnUnusedHints(); @@ -66,8 +65,7 @@ void SqlASTsToYqlsImpl(NYql::TAstParseResult& res, const std::vector<::NSQLv1Gen ctx.IncrementMonCounter("sql_errors", "AstToYqlError"); } else { ctx.IncrementMonCounter("sql_errors", "AstToYqlSilentError"); - ctx.Error() << "Error occurred on parse SQL query, but no error is collected" << - ", please send this request over bug report into YQL interface or write on yql@ maillist"; + ctx.Error() << "Error occurred on parse SQL query, but no error is collected" << ", please send this request over bug report into YQL interface or write on yql@ maillist"; } } else { ctx.WarnUnusedHints(); @@ -75,10 +73,10 @@ void SqlASTsToYqlsImpl(NYql::TAstParseResult& res, const std::vector<::NSQLv1Gen } NYql::TAstParseResult SqlASTToYql(const TLexers& lexers, const TParsers& parsers, - const TString& query, - const google::protobuf::Message& protoAst, - const NSQLTranslation::TSQLHints& hints, - const NSQLTranslation::TTranslationSettings& settings) + const TString& query, + const google::protobuf::Message& protoAst, + const NSQLTranslation::TSQLHints& hints, + const NSQLTranslation::TTranslationSettings& settings) { YQL_ENSURE(IsQueryMode(settings.Mode)); TAstParseResult res; @@ -103,7 +101,7 @@ NYql::TAstParseResult SqlToYql(const TLexers& lexers, const TParsers& parsers, c TContext ctx(lexers, parsers, settings, hints, res.Issues, query); NSQLTranslation::TErrorCollectorOverIssues collector(res.Issues, settings.MaxErrors, settings.File); - google::protobuf::Message* ast(SqlAST(parsers, query, queryName, collector, settings.AnsiLexer, settings.Antlr4Parser, settings.Arena)); + google::protobuf::Message* ast(SqlAST(parsers, query, queryName, collector, settings.AnsiLexer, settings.Antlr4Parser, settings.Arena)); if (ast) { SqlASTToYqlImpl(res, *ast, ctx); } else { @@ -194,7 +192,7 @@ bool NeedUseForAllStatements(const TRule_sql_stmt_core::AltCase& subquery) { } TVector<NYql::TAstParseResult> SqlToAstStatements(const TLexers& lexers, const TParsers& parsers, const TString& queryText, const NSQLTranslation::TTranslationSettings& settings, NYql::TWarningRules* warningRules, - TVector<NYql::TStmtParseInfo>* stmtParseInfo) + TVector<NYql::TStmtParseInfo>* stmtParseInfo) { TVector<TAstParseResult> result; const TString queryName = settings.File; @@ -230,7 +228,7 @@ TVector<NYql::TAstParseResult> SqlToAstStatements(const TLexers& lexers, const T result.back().Issues = std::move(issues); issues.Clear(); } - for (auto block: statements.GetBlock3()) { + for (auto block : statements.GetBlock3()) { if (NeedUseForAllStatements(block.GetRule_sql_stmt2().GetRule_sql_stmt_core2().Alt_case())) { commonStates.push_back(block.GetRule_sql_stmt2().GetRule_sql_stmt_core2()); continue; @@ -258,7 +256,7 @@ TVector<NYql::TAstParseResult> SqlToAstStatements(const TLexers& lexers, const T } bool SplitQueryToStatements(const TLexers& lexers, const TParsers& parsers, const TString& query, TVector<TString>& statements, NYql::TIssues& issues, - const NSQLTranslation::TTranslationSettings& settings) { + const NSQLTranslation::TTranslationSettings& settings) { auto lexer = NSQLTranslationV1::MakeLexer(lexers, settings.AnsiLexer, settings.Antlr4Parser); TVector<TString> parts; @@ -269,7 +267,7 @@ bool SplitQueryToStatements(const TLexers& lexers, const TParsers& parsers, cons for (auto& currentQuery : parts) { NYql::TIssues parserIssues; auto message = NSQLTranslationV1::SqlAST(parsers, currentQuery, settings.File, parserIssues, NSQLTranslation::SQL_MAX_PARSER_ERRORS, - settings.AnsiLexer, settings.Antlr4Parser, settings.Arena); + settings.AnsiLexer, settings.Antlr4Parser, settings.Arena); if (!message) { // Skip empty statements continue; @@ -281,7 +279,7 @@ bool SplitQueryToStatements(const TLexers& lexers, const TParsers& parsers, cons return true; } -class TTranslator : public NSQLTranslation::ITranslator { +class TTranslator: public NSQLTranslation::ITranslator { public: TTranslator(const TLexers& lexers, const TParsers& parsers) : Lexers_(lexers) @@ -294,23 +292,23 @@ public: } NYql::TAstParseResult TextToAst(const TString& query, const NSQLTranslation::TTranslationSettings& settings, - NYql::TWarningRules* warningRules, NYql::TStmtParseInfo* stmtParseInfo) final { + NYql::TWarningRules* warningRules, NYql::TStmtParseInfo* stmtParseInfo) final { Y_UNUSED(stmtParseInfo); return SqlToYql(Lexers_, Parsers_, query, settings, warningRules); } google::protobuf::Message* TextToMessage(const TString& query, const TString& queryName, - NYql::TIssues& issues, size_t maxErrors, const NSQLTranslation::TTranslationSettings& settings) final { + NYql::TIssues& issues, size_t maxErrors, const NSQLTranslation::TTranslationSettings& settings) final { return SqlAST(Parsers_, query, queryName, issues, maxErrors, settings.AnsiLexer, settings.Antlr4Parser, settings.Arena); } NYql::TAstParseResult TextAndMessageToAst(const TString& query, const google::protobuf::Message& protoAst, - const NSQLTranslation::TSQLHints& hints, const NSQLTranslation::TTranslationSettings& settings) final { + const NSQLTranslation::TSQLHints& hints, const NSQLTranslation::TTranslationSettings& settings) final { return SqlASTToYql(Lexers_, Parsers_, query, protoAst, hints, settings); } TVector<NYql::TAstParseResult> TextToManyAst(const TString& query, const NSQLTranslation::TTranslationSettings& settings, - NYql::TWarningRules* warningRules, TVector<NYql::TStmtParseInfo>* stmtParseInfo) final { + NYql::TWarningRules* warningRules, TVector<NYql::TStmtParseInfo>* stmtParseInfo) final { return SqlToAstStatements(Lexers_, Parsers_, query, settings, warningRules, stmtParseInfo); } diff --git a/yql/essentials/sql/v1/sql.h b/yql/essentials/sql/v1/sql.h index 7693d759157..be5bf5ce4f1 100644 --- a/yql/essentials/sql/v1/sql.h +++ b/yql/essentials/sql/v1/sql.h @@ -15,21 +15,21 @@ #include <google/protobuf/message.h> namespace NSQLTranslation { - struct TTranslationSettings; -} +struct TTranslationSettings; +} // namespace NSQLTranslation namespace NSQLTranslationV1 { - NYql::TAstParseResult SqlToYql(const TLexers& lexers, const TParsers& parsers, const TString& query, const NSQLTranslation::TTranslationSettings& settings, NYql::TWarningRules* warningRules = nullptr); +NYql::TAstParseResult SqlToYql(const TLexers& lexers, const TParsers& parsers, const TString& query, const NSQLTranslation::TTranslationSettings& settings, NYql::TWarningRules* warningRules = nullptr); - NYql::TAstParseResult SqlASTToYql(const TLexers& lexers, const TParsers& parsers, const TString& query, const google::protobuf::Message& protoAst, const NSQLTranslation::TSQLHints& hints, const NSQLTranslation::TTranslationSettings& settings); +NYql::TAstParseResult SqlASTToYql(const TLexers& lexers, const TParsers& parsers, const TString& query, const google::protobuf::Message& protoAst, const NSQLTranslation::TSQLHints& hints, const NSQLTranslation::TTranslationSettings& settings); - TVector<NYql::TAstParseResult> SqlToAstStatements(const TLexers& lexers, const TParsers& parsers, const TString& query, const NSQLTranslation::TTranslationSettings& settings, NYql::TWarningRules* warningRules, TVector<NYql::TStmtParseInfo>* stmtParseInfo = nullptr); +TVector<NYql::TAstParseResult> SqlToAstStatements(const TLexers& lexers, const TParsers& parsers, const TString& query, const NSQLTranslation::TTranslationSettings& settings, NYql::TWarningRules* warningRules, TVector<NYql::TStmtParseInfo>* stmtParseInfo = nullptr); - bool NeedUseForAllStatements(const NSQLv1Generated::TRule_sql_stmt_core::AltCase& subquery); +bool NeedUseForAllStatements(const NSQLv1Generated::TRule_sql_stmt_core::AltCase& subquery); - bool SplitQueryToStatements(const TLexers& lexers, const TParsers& parsers, const TString& query, TVector<TString>& statements, NYql::TIssues& issues, - const NSQLTranslation::TTranslationSettings& settings); +bool SplitQueryToStatements(const TLexers& lexers, const TParsers& parsers, const TString& query, TVector<TString>& statements, NYql::TIssues& issues, + const NSQLTranslation::TTranslationSettings& settings); - NSQLTranslation::TTranslatorPtr MakeTranslator(const TLexers& lexers, const TParsers& parsers); -} // namespace NSQLTranslationV1 +NSQLTranslation::TTranslatorPtr MakeTranslator(const TLexers& lexers, const TParsers& parsers); +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/sql_call_expr.cpp b/yql/essentials/sql/v1/sql_call_expr.cpp index 285bca8e2ca..f28da51216f 100644 --- a/yql/essentials/sql/v1/sql_call_expr.cpp +++ b/yql/essentials/sql/v1/sql_call_expr.cpp @@ -17,105 +17,105 @@ static bool ValidateForCounters(const TString& input) { } TNodePtr TSqlCallExpr::BuildUdf(bool forReduce) { - auto result = Node_ ? Node_ : BuildCallable(Pos_, Module_, Func_, Args_, forReduce); - if (to_lower(Module_) == "tensorflow" && Func_ == "RunBatch") { - if (Args_.size() > 2) { - Args_.erase(Args_.begin() + 2); - } else { - Ctx_.Error(Pos_) << "Excepted >= 3 arguments, but got: " << Args_.size(); - return nullptr; - } + auto result = Node_ ? Node_ : BuildCallable(Pos_, Module_, Func_, Args_, forReduce); + if (to_lower(Module_) == "tensorflow" && Func_ == "RunBatch") { + if (Args_.size() > 2) { + Args_.erase(Args_.begin() + 2); + } else { + Ctx_.Error(Pos_) << "Excepted >= 3 arguments, but got: " << Args_.size(); + return nullptr; } - return result; + } + return result; } TNodePtr TSqlCallExpr::BuildCall() { - TVector<TNodePtr> args; - bool warnOnYqlNameSpace = true; - - TUdfNode* udf_node = Node_ ? Node_->GetUdfNode() : nullptr; - if (udf_node) { - if (!udf_node->DoInit(Ctx_, nullptr)) { - return nullptr; - } - TNodePtr positional_args = BuildTuple(Pos_, PositionalArgs_); - TNodePtr positional = positional_args->Y("TypeOf", positional_args); - TNodePtr named_args = BuildStructure(Pos_, NamedArgs_); - TNodePtr named = named_args->Y("TypeOf", named_args); - - TNodePtr options = udf_node->BuildOptions(); - - if (udf_node->IsScript()) { - auto udf = BuildScriptUdf(Pos_, udf_node->GetModule(), udf_node->GetFunction(), udf_node->GetScriptArgs(), options); - TVector<TNodePtr> applyArgs; - applyArgs.push_back(new TAstAtomNodeImpl(Pos_, !NamedArgs_.empty() ? "NamedApply" : "Apply", TNodeFlags::Default)); - applyArgs.push_back(udf); - if (!NamedArgs_.empty()) { - applyArgs.push_back(BuildTuple(Pos_, PositionalArgs_)); - applyArgs.push_back(BuildStructure(Pos_, NamedArgs_)); - } else { - applyArgs.insert(applyArgs.end(), PositionalArgs_.begin(), PositionalArgs_.end()); - } + TVector<TNodePtr> args; + bool warnOnYqlNameSpace = true; - return new TAstListNodeImpl(Pos_, applyArgs); + TUdfNode* udf_node = Node_ ? Node_->GetUdfNode() : nullptr; + if (udf_node) { + if (!udf_node->DoInit(Ctx_, nullptr)) { + return nullptr; + } + TNodePtr positional_args = BuildTuple(Pos_, PositionalArgs_); + TNodePtr positional = positional_args->Y("TypeOf", positional_args); + TNodePtr named_args = BuildStructure(Pos_, NamedArgs_); + TNodePtr named = named_args->Y("TypeOf", named_args); + + TNodePtr options = udf_node->BuildOptions(); + + if (udf_node->IsScript()) { + auto udf = BuildScriptUdf(Pos_, udf_node->GetModule(), udf_node->GetFunction(), udf_node->GetScriptArgs(), options); + TVector<TNodePtr> applyArgs; + applyArgs.push_back(new TAstAtomNodeImpl(Pos_, !NamedArgs_.empty() ? "NamedApply" : "Apply", TNodeFlags::Default)); + applyArgs.push_back(udf); + if (!NamedArgs_.empty()) { + applyArgs.push_back(BuildTuple(Pos_, PositionalArgs_)); + applyArgs.push_back(BuildStructure(Pos_, NamedArgs_)); + } else { + applyArgs.insert(applyArgs.end(), PositionalArgs_.begin(), PositionalArgs_.end()); } - return BuildSqlCall(Ctx_, Pos_, udf_node->GetModule(), udf_node->GetFunction(), - args, positional_args, named_args, udf_node->GetExternalTypes(), - udf_node->GetTypeConfig(), udf_node->GetRunConfig(), options, - udf_node->GetDepends()); + return new TAstListNodeImpl(Pos_, applyArgs); } + return BuildSqlCall(Ctx_, Pos_, udf_node->GetModule(), udf_node->GetFunction(), + args, positional_args, named_args, udf_node->GetExternalTypes(), + udf_node->GetTypeConfig(), udf_node->GetRunConfig(), options, + udf_node->GetDepends()); + } + + if (Node_ && (!Node_->FuncName() || Node_->IsScript())) { + Module_ = "YQL"; + Func_ = NamedArgs_.empty() ? "Apply" : "NamedApply"; + warnOnYqlNameSpace = false; + args.push_back(Node_); + } + + if (Node_ && Node_->FuncName() && !Node_->IsScript()) { + Module_ = Node_->ModuleName() ? *Node_->ModuleName() : "YQL"; + Func_ = *Node_->FuncName(); + } + bool mustUseNamed = !NamedArgs_.empty(); + if (mustUseNamed) { if (Node_ && (!Node_->FuncName() || Node_->IsScript())) { - Module_ = "YQL"; - Func_ = NamedArgs_.empty() ? "Apply" : "NamedApply"; - warnOnYqlNameSpace = false; - args.push_back(Node_); + mustUseNamed = false; } - - if (Node_ && Node_->FuncName() && !Node_->IsScript()) { - Module_ = Node_->ModuleName() ? *Node_->ModuleName() : "YQL"; - Func_ = *Node_->FuncName(); + args.emplace_back(BuildTuple(Pos_, PositionalArgs_)); + args.emplace_back(BuildStructure(Pos_, NamedArgs_)); + } else if (IsExternalCall_) { + Func_ = "SqlExternalFunction"; + if (Args_.size() < 2 || Args_.size() > 3) { + Ctx_.Error(Pos_) << "EXTERNAL FUNCTION requires from 2 to 3 arguments, but got: " << Args_.size(); + return nullptr; } - bool mustUseNamed = !NamedArgs_.empty(); - if (mustUseNamed) { - if (Node_ && (!Node_->FuncName() || Node_->IsScript())) { - mustUseNamed = false; - } - args.emplace_back(BuildTuple(Pos_, PositionalArgs_)); - args.emplace_back(BuildStructure(Pos_, NamedArgs_)); - } else if (IsExternalCall_) { - Func_ = "SqlExternalFunction"; - if (Args_.size() < 2 || Args_.size() > 3) { - Ctx_.Error(Pos_) << "EXTERNAL FUNCTION requires from 2 to 3 arguments, but got: " << Args_.size(); - return nullptr; - } - if (Args_.size() == 3) { - args.insert(args.end(), Args_.begin(), Args_.end() - 1); - Args_.erase(Args_.begin(), Args_.end() - 1); - } else { - args.insert(args.end(), Args_.begin(), Args_.end()); - Args_.erase(Args_.begin(), Args_.end()); - } - auto configNode = new TExternalFunctionConfig(Pos_, CallConfig_); - auto configList = new TAstListNodeImpl(Pos_, { new TAstAtomNodeImpl(Pos_, "quote", 0), configNode }); - args.push_back(configList); + if (Args_.size() == 3) { + args.insert(args.end(), Args_.begin(), Args_.end() - 1); + Args_.erase(Args_.begin(), Args_.end() - 1); } else { args.insert(args.end(), Args_.begin(), Args_.end()); + Args_.erase(Args_.begin(), Args_.end()); } + auto configNode = new TExternalFunctionConfig(Pos_, CallConfig_); + auto configList = new TAstListNodeImpl(Pos_, {new TAstAtomNodeImpl(Pos_, "quote", 0), configNode}); + args.push_back(configList); + } else { + args.insert(args.end(), Args_.begin(), Args_.end()); + } - auto result = BuildBuiltinFunc(Ctx_, Pos_, Func_, args, Module_, AggMode_, &mustUseNamed, warnOnYqlNameSpace); - if (mustUseNamed) { - Error() << "Named args are used for call, but unsupported by function: " << Func_; - return nullptr; - } + auto result = BuildBuiltinFunc(Ctx_, Pos_, Func_, args, Module_, AggMode_, &mustUseNamed, warnOnYqlNameSpace); + if (mustUseNamed) { + Error() << "Named args are used for call, but unsupported by function: " << Func_; + return nullptr; + } - if (WindowName_) { - result = BuildCalcOverWindow(Pos_, WindowName_, result); - } + if (WindowName_) { + result = BuildCalcOverWindow(Pos_, WindowName_, result); + } - return result; + return result; } bool TSqlCallExpr::Init(const TRule_value_constructor& node) { @@ -172,7 +172,7 @@ bool TSqlCallExpr::ExtractCallParam(const TRule_external_call_param& node) { if (CallConfig_.contains(paramName)) { Ctx_.Error() << "WITH " << to_upper(paramName).Quote() - << " clause should be specified only once"; + << " clause should be specified only once"; return false; } @@ -189,7 +189,7 @@ bool TSqlCallExpr::ExtractCallParam(const TRule_external_call_param& node) { if (value && optimizeForParam) { TDeferredAtom atom; MakeTableFromExpression(Ctx_.Pos(), Ctx_, value, atom); - value = new TCallNodeImpl(Ctx_.Pos(), "String", { atom.Build() }); + value = new TCallNodeImpl(Ctx_.Pos(), "String", {atom.Build()}); } if (!value) { @@ -202,7 +202,7 @@ bool TSqlCallExpr::ExtractCallParam(const TRule_external_call_param& node) { bool TSqlCallExpr::ConfigureExternalCall(const TRule_external_call_settings& node) { bool success = ExtractCallParam(node.GetRule_external_call_param1()); - for (auto& block: node.GetBlock2()) { + for (auto& block : node.GetBlock2()) { success = ExtractCallParam(block.GetRule_external_call_param2()) && success; } @@ -297,7 +297,7 @@ bool TSqlCallExpr::FillArgs(const TRule_named_expr_list& node) { return false; } - for (auto& b: node.GetBlock2()) { + for (auto& b : node.GetBlock2()) { if (!FillArg(module, func, idx, b.GetRule_named_expr2())) { return false; } @@ -314,48 +314,47 @@ bool TSqlCallExpr::Init(const TRule_invoke_expr& node) { Pos_ = Ctx_.Pos(); if (node.HasBlock2()) { switch (node.GetBlock2().Alt_case()) { - case TRule_invoke_expr::TBlock2::kAlt1: { - const auto& alt = node.GetBlock2().GetAlt1(); - TPosition distinctPos; - if (IsDistinctOptSet(alt.GetRule_opt_set_quantifier1(), distinctPos)) { - if (!DistinctAllowed_) { - if (UsingCallExpr_) { - Ctx_.Error(distinctPos) << "DISTINCT can not be used in PROCESS/REDUCE"; - } else { - Ctx_.Error(distinctPos) << "DISTINCT can only be used in aggregation functions"; + case TRule_invoke_expr::TBlock2::kAlt1: { + const auto& alt = node.GetBlock2().GetAlt1(); + TPosition distinctPos; + if (IsDistinctOptSet(alt.GetRule_opt_set_quantifier1(), distinctPos)) { + if (!DistinctAllowed_) { + if (UsingCallExpr_) { + Ctx_.Error(distinctPos) << "DISTINCT can not be used in PROCESS/REDUCE"; + } else { + Ctx_.Error(distinctPos) << "DISTINCT can only be used in aggregation functions"; + } + return false; } - return false; + YQL_ENSURE(AggMode_ == EAggregateMode::Normal); + AggMode_ = EAggregateMode::Distinct; + Ctx_.IncrementMonCounter("sql_features", "DistinctInCallExpr"); } - YQL_ENSURE(AggMode_ == EAggregateMode::Normal); - AggMode_ = EAggregateMode::Distinct; - Ctx_.IncrementMonCounter("sql_features", "DistinctInCallExpr"); - } - if (!FillArgs(alt.GetRule_named_expr_list2())) { - return false; - } - for (const auto& arg : Args_) { - if (arg->GetLabel()) { - NamedArgs_.push_back(arg); + if (!FillArgs(alt.GetRule_named_expr_list2())) { + return false; } - else { - PositionalArgs_.push_back(arg); - if (!NamedArgs_.empty()) { - Ctx_.Error(arg->GetPos()) << "Unnamed arguments can not follow after named one"; - return false; + for (const auto& arg : Args_) { + if (arg->GetLabel()) { + NamedArgs_.push_back(arg); + } else { + PositionalArgs_.push_back(arg); + if (!NamedArgs_.empty()) { + Ctx_.Error(arg->GetPos()) << "Unnamed arguments can not follow after named one"; + return false; + } } } + break; } - break; - } - case TRule_invoke_expr::TBlock2::kAlt2: - if (IsExternalCall_) { - Ctx_.Error() << "You should set EXTERNAL FUNCTION type. Example: EXTERNAL FUNCTION('YANDEX-CLOUD', ...)"; - } else { - Args_.push_back(new TAsteriskNode(Pos_)); - } - break; - case TRule_invoke_expr::TBlock2::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_invoke_expr::TBlock2::kAlt2: + if (IsExternalCall_) { + Ctx_.Error() << "You should set EXTERNAL FUNCTION type. Example: EXTERNAL FUNCTION('YANDEX-CLOUD', ...)"; + } else { + Args_.push_back(new TAsteriskNode(Pos_)); + } + break; + case TRule_invoke_expr::TBlock2::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } } @@ -368,23 +367,23 @@ bool TSqlCallExpr::Init(const TRule_invoke_expr& node) { } switch (tail.GetBlock1().Alt_case()) { - case TRule_invoke_expr_tail::TBlock1::kAlt1: { - if (!tail.HasBlock2()) { - Ctx_.Error() << "RESPECT/IGNORE NULLS can only be used with window functions"; - return false; + case TRule_invoke_expr_tail::TBlock1::kAlt1: { + if (!tail.HasBlock2()) { + Ctx_.Error() << "RESPECT/IGNORE NULLS can only be used with window functions"; + return false; + } + const auto& alt = tail.GetBlock1().GetAlt1(); + if (alt.GetRule_null_treatment1().Alt_case() == TRule_null_treatment::kAltNullTreatment2) { + SetIgnoreNulls(); + } + break; } - const auto& alt = tail.GetBlock1().GetAlt1(); - if (alt.GetRule_null_treatment1().Alt_case() == TRule_null_treatment::kAltNullTreatment2) { - SetIgnoreNulls(); + case TRule_invoke_expr_tail::TBlock1::kAlt2: { + Ctx_.Error() << "FILTER clause is not supported yet"; + return false; } - break; - } - case TRule_invoke_expr_tail::TBlock1::kAlt2: { - Ctx_.Error() << "FILTER clause is not supported yet"; - return false; - } - case TRule_invoke_expr_tail::TBlock1::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_invoke_expr_tail::TBlock1::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } } @@ -400,31 +399,31 @@ bool TSqlCallExpr::Init(const TRule_invoke_expr& node) { } auto winRule = tail.GetBlock2().GetRule_window_name_or_specification2(); switch (winRule.Alt_case()) { - case TRule_window_name_or_specification::kAltWindowNameOrSpecification1: { - WindowName_ = Id(winRule.GetAlt_window_name_or_specification1().GetRule_window_name1().GetRule_an_id_window1(), *this); - break; - } - case TRule_window_name_or_specification::kAltWindowNameOrSpecification2: { - if (!Ctx_.WinSpecsScopes) { - auto pos = Ctx_.TokenPosition(tail.GetBlock2().GetToken1()); - Ctx_.Error(pos) << "Window and aggregation functions are not allowed in this context"; - return false; + case TRule_window_name_or_specification::kAltWindowNameOrSpecification1: { + WindowName_ = Id(winRule.GetAlt_window_name_or_specification1().GetRule_window_name1().GetRule_an_id_window1(), *this); + break; } + case TRule_window_name_or_specification::kAltWindowNameOrSpecification2: { + if (!Ctx_.WinSpecsScopes) { + auto pos = Ctx_.TokenPosition(tail.GetBlock2().GetToken1()); + Ctx_.Error(pos) << "Window and aggregation functions are not allowed in this context"; + return false; + } - TWindowSpecificationPtr spec = WindowSpecification( - winRule.GetAlt_window_name_or_specification2().GetRule_window_specification1().GetRule_window_specification_details2()); - if (!spec) { - return false; - } + TWindowSpecificationPtr spec = WindowSpecification( + winRule.GetAlt_window_name_or_specification2().GetRule_window_specification1().GetRule_window_specification_details2()); + if (!spec) { + return false; + } - WindowName_ = Ctx_.MakeName("_yql_anonymous_window"); - TWinSpecs& specs = Ctx_.WinSpecsScopes.back(); - YQL_ENSURE(!specs.contains(WindowName_)); - specs[WindowName_] = spec; - break; - } - case TRule_window_name_or_specification::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + WindowName_ = Ctx_.MakeName("_yql_anonymous_window"); + TWinSpecs& specs = Ctx_.WinSpecsScopes.back(); + YQL_ENSURE(!specs.contains(WindowName_)); + specs[WindowName_] = spec; + break; + } + case TRule_window_name_or_specification::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } Ctx_.IncrementMonCounter("sql_features", "WindowFunctionOver"); } @@ -442,7 +441,7 @@ void TSqlCallExpr::IncCounters() { if (ValidateForCounters(Func_)) { auto scriptType = NKikimr::NMiniKQL::ScriptTypeFromStr(Module_); if (scriptType == NKikimr::NMiniKQL::EScriptType::Unknown) { - Ctx_.IncrementMonCounter("udf_functions", Module_ + "." + Func_); + Ctx_.IncrementMonCounter("udf_functions", Module_ + "." + Func_); } } } diff --git a/yql/essentials/sql/v1/sql_call_param.h b/yql/essentials/sql/v1/sql_call_param.h index 57495afd88f..c4312cb8b4b 100644 --- a/yql/essentials/sql/v1/sql_call_param.h +++ b/yql/essentials/sql/v1/sql_call_param.h @@ -7,14 +7,14 @@ namespace NSQLTranslationV1 { /////////////////////////////////////////////////////////////////////////////////////////////// enum class ESqlCallParam: ui32 { - InputType /* "INPUT_TYPE" */, // as is - OutputType /* "OUTPUT_TYPE" */, // as is - Concurrency /* "CONCURRENCY" */, // as is - BatchSize /* "BATCH_SIZE" */, // as is - OptimizeFor /* "OPTIMIZE_FOR" */, // evaluate atom - Connection /* "CONNECTION" */, // evaluate atom - Init /* "INIT" */, // as is + InputType /* "INPUT_TYPE" */, // as is + OutputType /* "OUTPUT_TYPE" */, // as is + Concurrency /* "CONCURRENCY" */, // as is + BatchSize /* "BATCH_SIZE" */, // as is + OptimizeFor /* "OPTIMIZE_FOR" */, // evaluate atom + Connection /* "CONNECTION" */, // evaluate atom + Init /* "INIT" */, // as is }; /////////////////////////////////////////////////////////////////////////////////////////////// -} +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/sql_expression.cpp b/yql/essentials/sql/v1/sql_expression.cpp index 79d7c7c66b7..7ece4db8fca 100644 --- a/yql/essentials/sql/v1/sql_expression.cpp +++ b/yql/essentials/sql/v1/sql_expression.cpp @@ -18,22 +18,22 @@ using NALPDefaultAntlr4::SQLv1Antlr4Lexer; using namespace NSQLv1Generated; TNodePtr TSqlExpression::BuildSourceOrNode(const TRule_expr& node) { - // expr: - // or_subexpr (OR or_subexpr)* - // | type_name_composite - switch (node.Alt_case()) { - case TRule_expr::kAltExpr1: { - auto getNode = [](const TRule_expr_TAlt1_TBlock2& b) -> const TRule_or_subexpr& { return b.GetRule_or_subexpr2(); }; - return BinOper("Or", node.GetAlt_expr1().GetRule_or_subexpr1(), getNode, - node.GetAlt_expr1().GetBlock2().begin(), node.GetAlt_expr1().GetBlock2().end(), {}); - } - case TRule_expr::kAltExpr2: { - return TypeNode(node.GetAlt_expr2().GetRule_type_name_composite1()); - } - case TRule_expr::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + // expr: + // or_subexpr (OR or_subexpr)* + // | type_name_composite + switch (node.Alt_case()) { + case TRule_expr::kAltExpr1: { + auto getNode = [](const TRule_expr_TAlt1_TBlock2& b) -> const TRule_or_subexpr& { return b.GetRule_or_subexpr2(); }; + return BinOper("Or", node.GetAlt_expr1().GetRule_or_subexpr1(), getNode, + node.GetAlt_expr1().GetBlock2().begin(), node.GetAlt_expr1().GetBlock2().end(), {}); + } + case TRule_expr::kAltExpr2: { + return TypeNode(node.GetAlt_expr2().GetRule_type_name_composite1()); } + case TRule_expr::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } +} TNodePtr TSqlExpression::Build(const TRule_expr& node) { const bool prevIsSourceAllowed = IsSourceAllowed_; @@ -46,29 +46,29 @@ TNodePtr TSqlExpression::Build(const TRule_expr& node) { } TNodePtr TSqlExpression::Build(const TRule_lambda_or_parameter& node) { - // lambda_or_parameter: - // lambda - // | bind_parameter - switch (node.Alt_case()) { - case TRule_lambda_or_parameter::kAltLambdaOrParameter1: { - return LambdaRule(node.alt_lambda_or_parameter1().GetRule_lambda1()); + // lambda_or_parameter: + // lambda + // | bind_parameter + switch (node.Alt_case()) { + case TRule_lambda_or_parameter::kAltLambdaOrParameter1: { + return LambdaRule(node.alt_lambda_or_parameter1().GetRule_lambda1()); + } + case TRule_lambda_or_parameter::kAltLambdaOrParameter2: { + TString named; + if (!NamedNodeImpl(node.GetAlt_lambda_or_parameter2().GetRule_bind_parameter1(), named, *this)) { + return nullptr; } - case TRule_lambda_or_parameter::kAltLambdaOrParameter2: { - TString named; - if (!NamedNodeImpl(node.GetAlt_lambda_or_parameter2().GetRule_bind_parameter1(), named, *this)) { - return nullptr; - } - auto namedNode = GetNamedNode(named); - if (!namedNode) { - return nullptr; - } - - return namedNode; + auto namedNode = GetNamedNode(named); + if (!namedNode) { + return nullptr; } - case TRule_lambda_or_parameter::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + + return namedNode; } + case TRule_lambda_or_parameter::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } +} TSourcePtr TSqlExpression::BuildSource(const TRule_select_or_expr& node) { TNodePtr result = SelectOrExpr(node); @@ -89,77 +89,76 @@ TNodePtr TSqlExpression::BuildSourceOrNode(const TRule_smart_parenthesis& node) } TNodePtr TSqlExpression::SubExpr(const TRule_mul_subexpr& node, const TTrailingQuestions& tail) { - // mul_subexpr: con_subexpr (DOUBLE_PIPE con_subexpr)*; - auto getNode = [](const TRule_mul_subexpr::TBlock2& b) -> const TRule_con_subexpr& { return b.GetRule_con_subexpr2(); }; - return BinOper("Concat", node.GetRule_con_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); + // mul_subexpr: con_subexpr (DOUBLE_PIPE con_subexpr)*; + auto getNode = [](const TRule_mul_subexpr::TBlock2& b) -> const TRule_con_subexpr& { return b.GetRule_con_subexpr2(); }; + return BinOper("Concat", node.GetRule_con_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); } TNodePtr TSqlExpression::SubExpr(const TRule_add_subexpr& node, const TTrailingQuestions& tail) { - // add_subexpr: mul_subexpr ((ASTERISK | SLASH | PERCENT) mul_subexpr)*; - auto getNode = [](const TRule_add_subexpr::TBlock2& b) -> const TRule_mul_subexpr& { return b.GetRule_mul_subexpr2(); }; - return BinOpList(node.GetRule_mul_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); + // add_subexpr: mul_subexpr ((ASTERISK | SLASH | PERCENT) mul_subexpr)*; + auto getNode = [](const TRule_add_subexpr::TBlock2& b) -> const TRule_mul_subexpr& { return b.GetRule_mul_subexpr2(); }; + return BinOpList(node.GetRule_mul_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); } TNodePtr TSqlExpression::SubExpr(const TRule_bit_subexpr& node, const TTrailingQuestions& tail) { - // bit_subexpr: add_subexpr ((PLUS | MINUS) add_subexpr)*; - auto getNode = [](const TRule_bit_subexpr::TBlock2& b) -> const TRule_add_subexpr& { return b.GetRule_add_subexpr2(); }; - return BinOpList(node.GetRule_add_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); - } + // bit_subexpr: add_subexpr ((PLUS | MINUS) add_subexpr)*; + auto getNode = [](const TRule_bit_subexpr::TBlock2& b) -> const TRule_add_subexpr& { return b.GetRule_add_subexpr2(); }; + return BinOpList(node.GetRule_add_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); +} TNodePtr TSqlExpression::SubExpr(const TRule_neq_subexpr& node, const TTrailingQuestions& tailExternal) { - //neq_subexpr: bit_subexpr ((SHIFT_LEFT | shift_right | ROT_LEFT | rot_right | AMPERSAND | PIPE | CARET) bit_subexpr)* - // // trailing QUESTIONS are used in optional simple types (String?) and optional lambda args: ($x, $y?) -> ($x) - // ((double_question neq_subexpr) => double_question neq_subexpr | QUESTION+)?; - YQL_ENSURE(tailExternal.Count == 0); - MaybeUnnamedSmartParenOnTop_ = MaybeUnnamedSmartParenOnTop_ && !node.HasBlock3(); - TTrailingQuestions tail; - if (node.HasBlock3() && node.GetBlock3().Alt_case() == TRule_neq_subexpr::TBlock3::kAlt2) { - auto& questions = node.GetBlock3().GetAlt2(); - tail.Count = questions.GetBlock1().size(); - tail.Pos = Ctx_.TokenPosition(questions.GetBlock1().begin()->GetToken1()); - YQL_ENSURE(tail.Count > 0); - } - - auto getNode = [](const TRule_neq_subexpr::TBlock2& b) -> const TRule_bit_subexpr& { return b.GetRule_bit_subexpr2(); }; - auto result = BinOpList(node.GetRule_bit_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); - if (!result) { - return {}; - } - if (node.HasBlock3()) { - auto& block = node.GetBlock3(); - if (block.Alt_case() == TRule_neq_subexpr::TBlock3::kAlt1) { - TSqlExpression altExpr(Ctx_, Mode_); - auto altResult = SubExpr(block.GetAlt1().GetRule_neq_subexpr2(), {}); - if (!altResult) { - return {}; - } - const TVector<TNodePtr> args({result, altResult}); - Token(block.GetAlt1().GetRule_double_question1().GetToken1()); - result = BuildBuiltinFunc(Ctx_, Ctx_.Pos(), "Coalesce", args); + // neq_subexpr: bit_subexpr ((SHIFT_LEFT | shift_right | ROT_LEFT | rot_right | AMPERSAND | PIPE | CARET) bit_subexpr)* + // // trailing QUESTIONS are used in optional simple types (String?) and optional lambda args: ($x, $y?) -> ($x) + // ((double_question neq_subexpr) => double_question neq_subexpr | QUESTION+)?; + YQL_ENSURE(tailExternal.Count == 0); + MaybeUnnamedSmartParenOnTop_ = MaybeUnnamedSmartParenOnTop_ && !node.HasBlock3(); + TTrailingQuestions tail; + if (node.HasBlock3() && node.GetBlock3().Alt_case() == TRule_neq_subexpr::TBlock3::kAlt2) { + auto& questions = node.GetBlock3().GetAlt2(); + tail.Count = questions.GetBlock1().size(); + tail.Pos = Ctx_.TokenPosition(questions.GetBlock1().begin()->GetToken1()); + YQL_ENSURE(tail.Count > 0); + } + + auto getNode = [](const TRule_neq_subexpr::TBlock2& b) -> const TRule_bit_subexpr& { return b.GetRule_bit_subexpr2(); }; + auto result = BinOpList(node.GetRule_bit_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); + if (!result) { + return {}; + } + if (node.HasBlock3()) { + auto& block = node.GetBlock3(); + if (block.Alt_case() == TRule_neq_subexpr::TBlock3::kAlt1) { + TSqlExpression altExpr(Ctx_, Mode_); + auto altResult = SubExpr(block.GetAlt1().GetRule_neq_subexpr2(), {}); + if (!altResult) { + return {}; } + const TVector<TNodePtr> args({result, altResult}); + Token(block.GetAlt1().GetRule_double_question1().GetToken1()); + result = BuildBuiltinFunc(Ctx_, Ctx_.Pos(), "Coalesce", args); } - return result; } + return result; +} - TNodePtr TSqlExpression::SubExpr(const TRule_eq_subexpr& node, const TTrailingQuestions& tail) { - // eq_subexpr: neq_subexpr ((LESS | LESS_OR_EQ | GREATER | GREATER_OR_EQ) neq_subexpr)*; - auto getNode = [](const TRule_eq_subexpr::TBlock2& b) -> const TRule_neq_subexpr& { return b.GetRule_neq_subexpr2(); }; - return BinOpList(node.GetRule_neq_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); - } +TNodePtr TSqlExpression::SubExpr(const TRule_eq_subexpr& node, const TTrailingQuestions& tail) { + // eq_subexpr: neq_subexpr ((LESS | LESS_OR_EQ | GREATER | GREATER_OR_EQ) neq_subexpr)*; + auto getNode = [](const TRule_eq_subexpr::TBlock2& b) -> const TRule_neq_subexpr& { return b.GetRule_neq_subexpr2(); }; + return BinOpList(node.GetRule_neq_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); +} - TNodePtr TSqlExpression::SubExpr(const TRule_or_subexpr& node, const TTrailingQuestions& tail) { - // or_subexpr: and_subexpr (AND and_subexpr)*; - auto getNode = [](const TRule_or_subexpr::TBlock2& b) -> const TRule_and_subexpr& { return b.GetRule_and_subexpr2(); }; - return BinOper("And", node.GetRule_and_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); +TNodePtr TSqlExpression::SubExpr(const TRule_or_subexpr& node, const TTrailingQuestions& tail) { + // or_subexpr: and_subexpr (AND and_subexpr)*; + auto getNode = [](const TRule_or_subexpr::TBlock2& b) -> const TRule_and_subexpr& { return b.GetRule_and_subexpr2(); }; + return BinOper("And", node.GetRule_and_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); } TNodePtr TSqlExpression::SubExpr(const TRule_and_subexpr& node, const TTrailingQuestions& tail) { - // and_subexpr: xor_subexpr (XOR xor_subexpr)*; - auto getNode = [](const TRule_and_subexpr::TBlock2& b) -> const TRule_xor_subexpr& { return b.GetRule_xor_subexpr2(); }; - return BinOper("Xor", node.GetRule_xor_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); + // and_subexpr: xor_subexpr (XOR xor_subexpr)*; + auto getNode = [](const TRule_and_subexpr::TBlock2& b) -> const TRule_xor_subexpr& { return b.GetRule_xor_subexpr2(); }; + return BinOper("Xor", node.GetRule_xor_subexpr1(), getNode, node.GetBlock2().begin(), node.GetBlock2().end(), tail); } - bool ChangefeedSettingsEntry(const TRule_changefeed_settings_entry& node, TSqlExpression& ctx, TChangefeedSettings& settings, bool alter) { const auto id = IdEx(node.GetRule_an_id1(), ctx); if (alter) { @@ -288,11 +287,10 @@ bool CreateChangefeed(const TRule_changefeed& node, TSqlExpression& ctx, TVector } namespace { - bool WithoutAlpha(const std::string_view &literal) { - return literal.cend() == std::find_if(literal.cbegin(), literal.cend(), [](char c) { return std::isalpha(c) || (c & '\x80'); }); - } +bool WithoutAlpha(const std::string_view& literal) { + return literal.cend() == std::find_if(literal.cbegin(), literal.cend(), [](char c) { return std::isalpha(c) || (c & '\x80'); }); } - +} // namespace bool Expr(TSqlExpression& sqlExpr, TVector<TNodePtr>& exprNodes, const TRule_expr& node) { TNodePtr exprNode = sqlExpr.Build(node); @@ -307,7 +305,7 @@ bool ExprList(TSqlExpression& sqlExpr, TVector<TNodePtr>& exprNodes, const TRule if (!Expr(sqlExpr, exprNodes, node.GetRule_expr1())) { return false; } - for (auto b: node.GetBlock2()) { + for (auto b : node.GetBlock2()) { sqlExpr.Token(b.GetToken1()); if (!Expr(sqlExpr, exprNodes, b.GetRule_expr2())) { return false; @@ -331,7 +329,7 @@ bool ParseNumbers(TContext& ctx, const TString& strOrig, ui64& value, TString& s } if (strLen > 1) { auto iter = str.cend() - 1; - if (*iter == 'l' || *iter == 's' || *iter == 't' || *iter == 's' || *iter == 'i' || *iter == 'b' || *iter == 'n') { + if (*iter == 'l' || *iter == 's' || *iter == 't' || *iter == 's' || *iter == 'i' || *iter == 'b' || *iter == 'n') { --iter; } if (*iter == 'u' || *iter == 'p') { @@ -341,11 +339,10 @@ bool ParseNumbers(TContext& ctx, const TString& strOrig, ui64& value, TString& s } value = 0; const TString digString(str.begin() + (base == 10 ? 0 : 2), str.end() - suffix.size()); - for (const char& cur: digString) { + for (const char& cur : digString) { const ui64 curDigit = Char2DigitTable[static_cast<int>(cur)]; if (curDigit >= base) { - ctx.Error(ctx.Pos()) << "Failed to parse number from string: " << strOrig << ", char: '" << cur << - "' is out of base: " << base; + ctx.Error(ctx.Pos()) << "Failed to parse number from string: " << strOrig << ", char: '" << cur << "' is out of base: " << base; return false; } @@ -381,7 +378,7 @@ TNodePtr LiteralNumber(TContext& ctx, const TRule_integer& node) { const bool noSpaceForInt32 = value >> 31; const bool noSpaceForInt64 = value >> 63; - if (suffix == "") { + if (suffix == "") { bool implicitType = true; if (noSpaceForInt64) { return new TLiteralNumberNode<ui64>(ctx.Pos(), "Uint64", ToString(value), implicitType); @@ -429,15 +426,15 @@ TNodePtr LiteralReal(TContext& ctx, const TRule_real& node) { YQL_ENSURE(!value.empty()); auto lower = to_lower(value); if (lower.EndsWith("f")) { - return new TLiteralNumberNode<float>(ctx.Pos(), "Float", value.substr(0, value.size()-1)); + return new TLiteralNumberNode<float>(ctx.Pos(), "Float", value.substr(0, value.size() - 1)); } else if (lower.EndsWith("p")) { - return new TLiteralNumberNode<float>(ctx.Pos(), "PgFloat8", value.substr(0, value.size()-1)); + return new TLiteralNumberNode<float>(ctx.Pos(), "PgFloat8", value.substr(0, value.size() - 1)); } else if (lower.EndsWith("pf4")) { - return new TLiteralNumberNode<float>(ctx.Pos(), "PgFloat4", value.substr(0, value.size()-3)); + return new TLiteralNumberNode<float>(ctx.Pos(), "PgFloat4", value.substr(0, value.size() - 3)); } else if (lower.EndsWith("pf8")) { - return new TLiteralNumberNode<float>(ctx.Pos(), "PgFloat8", value.substr(0, value.size()-3)); + return new TLiteralNumberNode<float>(ctx.Pos(), "PgFloat8", value.substr(0, value.size() - 3)); } else if (lower.EndsWith("pn")) { - return new TLiteralNode(ctx.Pos(), "PgNumeric", value.substr(0, value.size()-2)); + return new TLiteralNode(ctx.Pos(), "PgNumeric", value.substr(0, value.size() - 2)); } else { return new TLiteralNumberNode<double>(ctx.Pos(), "Double", value); } @@ -501,7 +498,7 @@ TMaybe<TExprOrIdent> TSqlExpression::LiteralExpr(const TRule_literal_value& node return result; } -template<typename TUnarySubExprType> +template <typename TUnarySubExprType> TNodePtr TSqlExpression::UnaryExpr(const TUnarySubExprType& node, const TTrailingQuestions& tail) { if constexpr (std::is_same_v<TUnarySubExprType, TRule_unary_subexpr>) { if (node.Alt_case() == TRule_unary_subexpr::kAltUnarySubexpr1) { @@ -553,9 +550,7 @@ TNodePtr TSqlExpression::JsonInputArg(const TRule_json_common_args& node) { */ TNodePtr jsonExpr = Build(node.GetRule_expr1()); if (!jsonExpr || jsonExpr->IsNull()) { - jsonExpr = new TCallNodeImpl(Ctx_.Pos(), "Nothing", { - new TCallNodeImpl(Ctx_.Pos(), "OptionalType", {BuildDataType(Ctx_.Pos(), "Json")}) - }); + jsonExpr = new TCallNodeImpl(Ctx_.Pos(), "Nothing", {new TCallNodeImpl(Ctx_.Pos(), "OptionalType", {BuildDataType(Ctx_.Pos(), "Json")})}); } return jsonExpr; @@ -602,7 +597,7 @@ void TSqlExpression::AddJsonVariables(const TRule_json_variables& node, TVector< */ AddJsonVariable(node.GetRule_json_variable1(), children); for (size_t i = 0; i < node.Block2Size(); i++) { - AddJsonVariable(node.GetBlock2(i).GetRule_json_variable2(), children); + AddJsonVariable(node.GetBlock2(i).GetRule_json_variable2(), children); } } @@ -763,9 +758,7 @@ void TSqlExpression::AddJsonExistsHandler(const TRule_json_exists& node, TVector const auto pos = GetPos(token); const auto mode = to_lower(token.GetValue()); if (mode == "unknown") { - const auto nothingNode = new TCallNodeImpl(pos, "Nothing", { - new TCallNodeImpl(pos, "OptionalType", {BuildDataType(pos, "Bool")}) - }); + const auto nothingNode = new TCallNodeImpl(pos, "Nothing", {new TCallNodeImpl(pos, "OptionalType", {BuildDataType(pos, "Bool")})}); children.push_back(nothingNode); } else if (mode != "error") { children.push_back(buildJustBool(pos, FromString<bool>(mode))); @@ -920,8 +913,8 @@ TNodePtr TSqlExpression::RowPatternVarAccess(TString var, const TRule_unary_sube case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt3: switch (block.GetAlt3().GetRule_an_id_or_type1().GetAltCase()) { case TRule_an_id_or_type::kAltAnIdOrType1: { - const auto &idOrType = block.GetAlt3().GetRule_an_id_or_type1().GetAlt_an_id_or_type1().GetRule_id_or_type1(); - switch(idOrType.GetAltCase()) { + const auto& idOrType = block.GetAlt3().GetRule_an_id_or_type1().GetAlt_an_id_or_type1().GetRule_id_or_type1(); + switch (idOrType.GetAltCase()) { case TRule_id_or_type::kAltIdOrType1: { const auto column = Id(idOrType.GetAlt_id_or_type1().GetRule_id1(), *this); return BuildMatchRecognizeColumnAccess(Ctx_.Pos(), std::move(var), std::move(column)); @@ -945,7 +938,7 @@ TNodePtr TSqlExpression::RowPatternVarAccess(TString var, const TRule_unary_sube return {}; } -template<typename TUnaryCasualExprRule> +template <typename TUnaryCasualExprRule> TNodePtr TSqlExpression::UnaryCasualExpr(const TUnaryCasualExprRule& node, const TTrailingQuestions& tail) { // unary_casual_subexpr: (id_expr | atom_expr) unary_subexpr_suffix; // OR @@ -1005,39 +998,37 @@ TNodePtr TSqlExpression::UnaryCasualExpr(const TUnaryCasualExprRule& node, const for (auto& _b : suffix.GetBlock1()) { auto& b = _b.GetBlock1(); switch (b.Alt_case()) { - case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt1: { - // key_expr - // onlyDots = false; - break; - } - case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt2: { - // invoke_expr - cannot be a column, function name - if (isFirstElem) { - isColumnRef = false; + case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt1: { + // key_expr + // onlyDots = false; + break; } + case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt2: { + // invoke_expr - cannot be a column, function name + if (isFirstElem) { + isColumnRef = false; + } - // onlyDots = false; - break; - } - case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt3: { - // In case of MATCH_RECOGNIZE lambdas - // X.Y is treated as Var.Column access - if (isColumnRef && ( - EColumnRefState::MatchRecognizeMeasures == Ctx_.GetColumnReferenceState() || - EColumnRefState::MatchRecognizeDefine == Ctx_.GetColumnReferenceState() || - EColumnRefState::MatchRecognizeDefineAggregate == Ctx_.GetColumnReferenceState() - )) { - if (suffix.GetBlock1().size() != 1) { - Ctx_.Error() << "Expected Var.Column, but got chain of " << suffix.GetBlock1().size() << " column accesses"; - return nullptr; + // onlyDots = false; + break; + } + case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt3: { + // In case of MATCH_RECOGNIZE lambdas + // X.Y is treated as Var.Column access + if (isColumnRef && (EColumnRefState::MatchRecognizeMeasures == Ctx_.GetColumnReferenceState() || + EColumnRefState::MatchRecognizeDefine == Ctx_.GetColumnReferenceState() || + EColumnRefState::MatchRecognizeDefineAggregate == Ctx_.GetColumnReferenceState())) { + if (suffix.GetBlock1().size() != 1) { + Ctx_.Error() << "Expected Var.Column, but got chain of " << suffix.GetBlock1().size() << " column accesses"; + return nullptr; + } + return RowPatternVarAccess(std::move(name), b.GetAlt3().GetBlock2()); } - return RowPatternVarAccess(std::move(name), b.GetAlt3().GetBlock2()); + break; } - break; - } - case TRule_unary_subexpr_suffix::TBlock1::TBlock1::ALT_NOT_SET: - AltNotImplemented("unary_subexpr_suffix", b); - return nullptr; + case TRule_unary_subexpr_suffix::TBlock1::TBlock1::ALT_NOT_SET: + AltNotImplemented("unary_subexpr_suffix", b); + return nullptr; } isFirstElem = false; @@ -1085,96 +1076,96 @@ TNodePtr TSqlExpression::UnaryCasualExpr(const TUnaryCasualExprRule& node, const for (auto& _b : suffix.GetBlock1()) { auto& b = _b.GetBlock1(); switch (b.Alt_case()) { - case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt1: { - // key_expr - auto keyExpr = KeyExpr(b.GetAlt1().GetRule_key_expr1()); - if (!keyExpr) { - Ctx_.IncrementMonCounter("sql_errors", "BadKeyExpr"); - return nullptr; - } + case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt1: { + // key_expr + auto keyExpr = KeyExpr(b.GetAlt1().GetRule_key_expr1()); + if (!keyExpr) { + Ctx_.IncrementMonCounter("sql_errors", "BadKeyExpr"); + return nullptr; + } - if (!lastExpr) { - lastExpr = BuildAccess(pos, ids, false); + if (!lastExpr) { + lastExpr = BuildAccess(pos, ids, false); + ids.clear(); + } + + ids.push_back(lastExpr); + ids.push_back(keyExpr); + lastExpr = BuildAccess(pos, ids, true); ids.clear(); + break; } + case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt2: { + // invoke_expr - cannot be a column, function name + TSqlCallExpr call(Ctx_, Mode_); + if (isFirstElem && !name.empty()) { + call.AllowDistinct(); + call.InitName(name); + } else { + call.InitExpr(lastExpr); + } - ids.push_back(lastExpr); - ids.push_back(keyExpr); - lastExpr = BuildAccess(pos, ids, true); - ids.clear(); - break; - } - case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt2: { - // invoke_expr - cannot be a column, function name - TSqlCallExpr call(Ctx_, Mode_); - if (isFirstElem && !name.empty()) { - call.AllowDistinct(); - call.InitName(name); - } else { - call.InitExpr(lastExpr); - } + bool initRet = call.Init(b.GetAlt2().GetRule_invoke_expr1()); + if (initRet) { + call.IncCounters(); + } - bool initRet = call.Init(b.GetAlt2().GetRule_invoke_expr1()); - if (initRet) { - call.IncCounters(); - } + if (!initRet) { + return nullptr; + } - if (!initRet) { - return nullptr; - } + lastExpr = call.BuildCall(); + if (!lastExpr) { + return nullptr; + } - lastExpr = call.BuildCall(); - if (!lastExpr) { - return nullptr; + break; } + case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt3: { + // dot + if (lastExpr) { + ids.push_back(lastExpr); + } - break; - } - case TRule_unary_subexpr_suffix::TBlock1::TBlock1::kAlt3: { - // dot - if (lastExpr) { - ids.push_back(lastExpr); - } + auto bb = b.GetAlt3().GetBlock2(); + switch (bb.Alt_case()) { + case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt1: { + TString named; + if (!NamedNodeImpl(bb.GetAlt1().GetRule_bind_parameter1(), named, *this)) { + return nullptr; + } + auto namedNode = GetNamedNode(named); + if (!namedNode) { + return nullptr; + } - auto bb = b.GetAlt3().GetBlock2(); - switch (bb.Alt_case()) { - case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt1: { - TString named; - if (!NamedNodeImpl(bb.GetAlt1().GetRule_bind_parameter1(), named, *this)) { - return nullptr; + ids.push_back(named); + ids.back().Expr = namedNode; + break; } - auto namedNode = GetNamedNode(named); - if (!namedNode) { - return nullptr; + case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt2: { + const TString str(Token(bb.GetAlt2().GetToken1())); + ids.push_back(str); + break; } - - ids.push_back(named); - ids.back().Expr = namedNode; - break; - } - case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt2: { - const TString str(Token(bb.GetAlt2().GetToken1())); - ids.push_back(str); - break; + case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt3: { + ids.push_back(Id(bb.GetAlt3().GetRule_an_id_or_type1(), *this)); + break; + } + case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } - case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::kAlt3: { - ids.push_back(Id(bb.GetAlt3().GetRule_an_id_or_type1(), *this)); - break; + + if (lastExpr) { + lastExpr = BuildAccess(pos, ids, false); + ids.clear(); } - case TRule_unary_subexpr_suffix_TBlock1_TBlock1_TAlt3_TBlock2::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); - } - if (lastExpr) { - lastExpr = BuildAccess(pos, ids, false); - ids.clear(); + break; } - - break; - } - case TRule_unary_subexpr_suffix::TBlock1::TBlock1::ALT_NOT_SET: - AltNotImplemented("unary_subexpr_suffix", b); - return nullptr; + case TRule_unary_subexpr_suffix::TBlock1::TBlock1::ALT_NOT_SET: + AltNotImplemented("unary_subexpr_suffix", b); + return nullptr; } isFirstElem = false; @@ -1248,7 +1239,7 @@ TNodePtr TSqlExpression::LambdaRule(const TRule_lambda& rule) { Token(bodyBlock.GetToken1()); TPosition pos(Ctx_.Pos()); TVector<TNodePtr> exprSeq; - for (auto& arg: args) { + for (auto& arg : args) { arg.Name = PushNamedAtom(arg.Pos, arg.Name); } bool ret = false; @@ -1273,10 +1264,8 @@ TNodePtr TSqlExpression::LambdaRule(const TRule_lambda& rule) { auto lambdaNode = BuildSqlLambda(pos, std::move(argNames), std::move(exprSeq)); if (optionalArgumentsCount > 0) { - lambdaNode = new TCallNodeImpl(pos, "WithOptionalArgs", { - lambdaNode, - BuildQuotedAtom(pos, ToString(optionalArgumentsCount), TNodeFlags::Default) - }); + lambdaNode = new TCallNodeImpl(pos, "WithOptionalArgs", {lambdaNode, + BuildQuotedAtom(pos, ToString(optionalArgumentsCount), TNodeFlags::Default)}); } return lambdaNode; @@ -1395,7 +1384,7 @@ TNodePtr TSqlExpression::CaseRule(const TRule_case_expr& rule) { } } auto final = ReduceCaseBranches(branches.begin(), branches.end()); - return BuildBuiltinFunc(Ctx_, Ctx_.Pos(), "If", { final.Pred, final.Value, elseExpr }); + return BuildBuiltinFunc(Ctx_, Ctx_.Pos(), "If", {final.Pred, final.Value, elseExpr}); } TMaybe<TExprOrIdent> TSqlExpression::AtomExpr(const TRule_atom_expr& node, const TTrailingQuestions& tail) { @@ -1530,21 +1519,21 @@ TMaybe<TExprOrIdent> TSqlExpression::InAtomExpr(const TRule_in_atom_expr& node, TPosition pos(Ctx_.Pos()); TString name; switch (alt.GetBlock3().Alt_case()) { - case TRule_in_atom_expr::TAlt6::TBlock3::kAlt1: - name = Id(alt.GetBlock3().GetAlt1().GetRule_id_or_type1(), *this); - break; - case TRule_in_atom_expr::TAlt6::TBlock3::kAlt2: { - name = Token(alt.GetBlock3().GetAlt2().GetToken1()); - if (Ctx_.AnsiQuotedIdentifiers && name.StartsWith('"')) { - // same as previous case - name = IdContentFromString(Ctx_, name); - } else { - module = "@" + module; + case TRule_in_atom_expr::TAlt6::TBlock3::kAlt1: + name = Id(alt.GetBlock3().GetAlt1().GetRule_id_or_type1(), *this); + break; + case TRule_in_atom_expr::TAlt6::TBlock3::kAlt2: { + name = Token(alt.GetBlock3().GetAlt2().GetToken1()); + if (Ctx_.AnsiQuotedIdentifiers && name.StartsWith('"')) { + // same as previous case + name = IdContentFromString(Ctx_, name); + } else { + module = "@" + module; + } + break; } - break; - } - case TRule_in_atom_expr::TAlt6::TBlock3::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_in_atom_expr::TAlt6::TBlock3::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } result.Expr = BuildCallable(pos, module, name, {}); break; @@ -1578,13 +1567,14 @@ bool TSqlExpression::SqlLambdaParams(const TNodePtr& node, TVector<TSymbolNameWi args.clear(); optionalArgumentsCount = 0; auto errMsg = TStringBuf("Invalid lambda arguments syntax. Lambda arguments should start with '$' as named value."); - auto tupleNodePtr = node->GetTupleNode();; + auto tupleNodePtr = node->GetTupleNode(); + if (!tupleNodePtr) { Ctx_.Error(node->GetPos()) << errMsg; return false; } THashSet<TString> dupArgsChecker; - for (const auto& argPtr: tupleNodePtr->Elements()) { + for (const auto& argPtr : tupleNodePtr->Elements()) { auto contentPtr = argPtr->GetAtomContent(); if (!contentPtr || !contentPtr->StartsWith("$")) { Ctx_.Error(argPtr->GetPos()) << errMsg; @@ -1620,7 +1610,7 @@ bool TSqlExpression::SqlLambdaExprBody(TContext& ctx, const TRule_lambda_body& n TSqlExpression expr(ctx, ctx.Settings.Mode); TVector<TString> localNames; bool hasError = false; - for (auto& block: node.GetBlock2()) { + for (auto& block : node.GetBlock2()) { const auto& rule = block.GetRule_lambda_stmt1(); switch (rule.Alt_case()) { case TRule_lambda_stmt::kAltLambdaStmt1: { @@ -1743,7 +1733,7 @@ TNodePtr TSqlExpression::SubExpr(const TRule_xor_subexpr& node, const TTrailingQ const TString* escapeLiteral = nullptr; TNodePtr escapeNode; const auto& escaper = BuildUdf(Ctx_, pos, "Re2", "PatternFromLike", {}); - TVector<TNodePtr> escaperArgs({ escaper, pattern }); + TVector<TNodePtr> escaperArgs({escaper, pattern}); if (matchOp.HasBlock4()) { const auto& escapeBlock = matchOp.GetBlock4(); @@ -1786,15 +1776,15 @@ TNodePtr TSqlExpression::SubExpr(const TRule_xor_subexpr& node, const TTrailingQ } auto csModeLiteral = BuildLiteralBool(pos, opName != "ilike"); csModeLiteral->SetLabel("CaseSensitive"); - auto csOption = BuildStructure(pos, { csModeLiteral }); - auto optionsApply = new TCallNodeImpl(pos, "NamedApply", { re2options, BuildTuple(pos, {}), csOption }); + auto csOption = BuildStructure(pos, {csModeLiteral}); + auto optionsApply = new TCallNodeImpl(pos, "NamedApply", {re2options, BuildTuple(pos, {}), csOption}); - const TNodePtr escapedPattern = new TCallNodeImpl(pos, "Apply", { escaperArgs }); - auto list = new TAstListNodeImpl(pos, { escapedPattern, optionsApply }); - auto runConfig = new TAstListNodeImpl(pos, { new TAstAtomNodeImpl(pos, "quote", 0), list }); + const TNodePtr escapedPattern = new TCallNodeImpl(pos, "Apply", {escaperArgs}); + auto list = new TAstListNodeImpl(pos, {escapedPattern, optionsApply}); + auto runConfig = new TAstListNodeImpl(pos, {new TAstAtomNodeImpl(pos, "quote", 0), list}); - const TNodePtr matcher = new TCallNodeImpl(pos, "AssumeStrict", { BuildUdf(Ctx_, pos, "Re2", "Match", { runConfig }) }); - isMatch = new TCallNodeImpl(pos, "Apply", { matcher, res }); + const TNodePtr matcher = new TCallNodeImpl(pos, "AssumeStrict", {BuildUdf(Ctx_, pos, "Re2", "Match", {runConfig})}); + isMatch = new TCallNodeImpl(pos, "Apply", {matcher, res}); bool isUtf8 = false; const TString* literalPattern = pattern->GetLiteral("String"); @@ -1861,8 +1851,7 @@ TNodePtr TSqlExpression::SubExpr(const TRule_xor_subexpr& node, const TTrailingQ pos, "And", prefixMatch, - BuildBinaryOp(Ctx_, pos, "<", res, BuildLiteralRawString(pos, TString(*upperBound), isUtf8)) - ); + BuildBinaryOp(Ctx_, pos, "<", res, BuildLiteralRawString(pos, TString(*upperBound), isUtf8))); } } @@ -1874,14 +1863,12 @@ TNodePtr TSqlExpression::SubExpr(const TRule_xor_subexpr& node, const TTrailingQ } else { // len(str) >= len(prefix) + len(suffix) && StartsWith(str, prefix) && EndsWith(str, suffix) TNodePtr sizePred = BuildBinaryOp(Ctx_, pos, ">=", - TNodePtr(new TCallNodeImpl(pos, "Size", { res })), - TNodePtr(new TLiteralNumberNode<ui32>(pos, "Uint32", ToString(prefix.size() + suffix.size())))); + TNodePtr(new TCallNodeImpl(pos, "Size", {res})), + TNodePtr(new TLiteralNumberNode<ui32>(pos, "Uint32", ToString(prefix.size() + suffix.size())))); TNodePtr suffixMatch = BuildBinaryOp(Ctx_, pos, endsWithOp, res, BuildLiteralRawString(pos, suffix, isUtf8)); - isMatch = new TCallNodeImpl(pos, "And", { - sizePred, - prefixMatch, - suffixMatch - }); + isMatch = new TCallNodeImpl(pos, "And", {sizePred, + prefixMatch, + suffixMatch}); } } else { isMatch = BuildBinaryOp(Ctx_, pos, "And", prefixMatch, isMatch); @@ -1918,17 +1905,15 @@ TNodePtr TSqlExpression::SubExpr(const TRule_xor_subexpr& node, const TTrailingQ if (!Ctx_.PragmaRegexUseRe2) { if (!Ctx_.Warning(pos, TIssuesIds::CORE_LEGACY_REGEX_ENGINE, [](auto& out) { - out << "Legacy regex engine works incorrectly with unicode. " - << "Use PRAGMA RegexUseRe2='true';"; - })) { + out << "Legacy regex engine works incorrectly with unicode. " + << "Use PRAGMA RegexUseRe2='true';"; + })) { return nullptr; } } - const auto& matcher = Ctx_.PragmaRegexUseRe2 ? - BuildUdf(Ctx_, pos, "Re2", opName == "match" ? "Match" : "Grep", {BuildTuple(pos, {pattern, BuildLiteralNull(pos)})}): - BuildUdf(Ctx_, pos, "Pcre", opName == "match" ? "BacktrackingMatch" : "BacktrackingGrep", { pattern }); - isMatch = new TCallNodeImpl(pos, "Apply", { matcher, res }); + const auto& matcher = Ctx_.PragmaRegexUseRe2 ? BuildUdf(Ctx_, pos, "Re2", opName == "match" ? "Match" : "Grep", {BuildTuple(pos, {pattern, BuildLiteralNull(pos)})}) : BuildUdf(Ctx_, pos, "Pcre", opName == "match" ? "BacktrackingMatch" : "BacktrackingGrep", {pattern}); + isMatch = new TCallNodeImpl(pos, "Apply", {matcher, res}); if (opName != "match") { Ctx_.IncrementMonCounter("sql_features", notMatch ? "NotRegexp" : "Regexp"); } else { @@ -1942,7 +1927,7 @@ TNodePtr TSqlExpression::SubExpr(const TRule_xor_subexpr& node, const TTrailingQ return (notMatch && isMatch) ? isMatch->ApplyUnaryOp(Ctx_, pos, "Not") : isMatch; } case TRule_cond_expr::kAltCondExpr2: { - // | NOT? IN COMPACT? in_expr + // | NOT? IN COMPACT? in_expr auto altInExpr = cond.GetAlt_cond_expr2(); const bool notIn = altInExpr.HasBlock1(); auto hints = BuildTuple(pos, {}); @@ -1953,8 +1938,8 @@ TNodePtr TSqlExpression::SubExpr(const TRule_xor_subexpr& node, const TTrailingQ } if (isCompact) { Ctx_.IncrementMonCounter("sql_features", "IsCompactHint"); - auto sizeHint = BuildTuple(pos, { BuildQuotedAtom(pos, "isCompact", NYql::TNodeFlags::Default) }); - hints = BuildTuple(pos, { sizeHint }); + auto sizeHint = BuildTuple(pos, {BuildQuotedAtom(pos, "isCompact", NYql::TNodeFlags::Default)}); + hints = BuildTuple(pos, {sizeHint}); } TSqlExpression inSubexpr(Ctx_, Mode_); auto inRight = inSubexpr.SqlInExpr(altInExpr.GetRule_in_expr4(), tail); @@ -1970,15 +1955,14 @@ TNodePtr TSqlExpression::SubExpr(const TRule_xor_subexpr& node, const TTrailingQ auto altCase = cond.GetAlt_cond_expr3().GetBlock1().Alt_case(); const bool notNoll = altCase == TRule_cond_expr::TAlt3::TBlock1::kAlt2 || - altCase == TRule_cond_expr::TAlt3::TBlock1::kAlt4 - ; + altCase == TRule_cond_expr::TAlt3::TBlock1::kAlt4; if (altCase == TRule_cond_expr::TAlt3::TBlock1::kAlt4 && !cond.GetAlt_cond_expr3().GetBlock1().GetAlt4().HasBlock1()) { if (!Ctx_.Warning(Ctx_.Pos(), TIssuesIds::YQL_MISSING_IS_BEFORE_NOT_NULL, [](auto& out) { - out << "Missing IS keyword before NOT NULL"; - }, Ctx_.DisableLegacyNotNull)) { + out << "Missing IS keyword before NOT NULL"; + }, Ctx_.DisableLegacyNotNull)) { return {}; } } @@ -1998,12 +1982,12 @@ TNodePtr TSqlExpression::SubExpr(const TRule_xor_subexpr& node, const TTrailingQ } const bool bothArgNull = left->IsNull() && right->IsNull(); - const bool oneArgNull = left->IsNull() || right->IsNull(); + const bool oneArgNull = left->IsNull() || right->IsNull(); if (res->IsNull() || bothArgNull || (symmetric && oneArgNull)) { if (!Ctx_.Warning(pos, TIssuesIds::YQL_OPERATION_WILL_RETURN_NULL, [](auto& out) { - out << "BETWEEN operation will return NULL here"; - })) { + out << "BETWEEN operation will return NULL here"; + })) { return {}; } } @@ -2014,28 +1998,25 @@ TNodePtr TSqlExpression::SubExpr(const TRule_xor_subexpr& node, const TTrailingQ pos, "Or", BuildBinaryOpRaw(pos, "<", res, left), - BuildBinaryOpRaw(pos, ">", res, right) - ); + BuildBinaryOpRaw(pos, ">", res, right)); } else { return BuildBinaryOpRaw( pos, "And", BuildBinaryOpRaw(pos, ">=", res, left), - BuildBinaryOpRaw(pos, "<=", res, right) - ); + BuildBinaryOpRaw(pos, "<=", res, right)); } }; if (symmetric) { - Ctx_.IncrementMonCounter("sql_features", negation? "NotBetweenSymmetric" : "BetweenSymmetric"); + Ctx_.IncrementMonCounter("sql_features", negation ? "NotBetweenSymmetric" : "BetweenSymmetric"); return BuildBinaryOpRaw( pos, - negation? "And" : "Or", + negation ? "And" : "Or", buildSubexpr(left, right), - buildSubexpr(right, left) - ); + buildSubexpr(right, left)); } else { - Ctx_.IncrementMonCounter("sql_features", negation? "NotBetween" : "Between"); + Ctx_.IncrementMonCounter("sql_features", negation ? "NotBetween" : "Between"); return buildSubexpr(left, right); } } @@ -2058,9 +2039,10 @@ TNodePtr TSqlExpression::BinOperList(const TString& opName, TVector<TNodePtr>::c const size_t opCount = end - begin; Y_DEBUG_ABORT_UNLESS(opCount >= 2); if (opCount == 2) { - return BuildBinaryOp(Ctx_, pos, opName, *begin, *(begin+1)); - } if (opCount == 3) { - return BuildBinaryOp(Ctx_, pos, opName, BuildBinaryOp(Ctx_, pos, opName, *begin, *(begin+1)), *(begin+2)); + return BuildBinaryOp(Ctx_, pos, opName, *begin, *(begin + 1)); + } + if (opCount == 3) { + return BuildBinaryOp(Ctx_, pos, opName, BuildBinaryOp(Ctx_, pos, opName, *begin, *(begin + 1)), *(begin + 2)); } else { auto mid = begin + opCount / 2; return BuildBinaryOp(Ctx_, pos, opName, BinOperList(opName, begin, mid), BinOperList(opName, mid, end)); @@ -2086,7 +2068,7 @@ TSqlExpression::TCaseBranch TSqlExpression::ReduceCaseBranches(TVector<TCaseBran TCaseBranch result; result.Pred = new TCallNodeImpl(Ctx_.Pos(), "Or", CloneContainer(preds)); - result.Value = BuildBuiltinFunc(Ctx_, Ctx_.Pos(), "If", { left.Pred, left.Value, right.Value }); + result.Value = BuildBuiltinFunc(Ctx_, Ctx_.Pos(), "If", {left.Pred, left.Value, right.Value}); return result; } @@ -2387,15 +2369,15 @@ TNodePtr TSqlExpression::SelectSubExpr(const TRule_select_subexpr& node) { TNodePtr TSqlExpression::SelectOrExpr(const TRule_select_or_expr& node) { switch (node.Alt_case()) { - case NSQLv1Generated::TRule_select_or_expr::kAltSelectOrExpr1: { - const auto& select_kind = node.GetAlt_select_or_expr1().GetRule_select_kind_partial1(); - TSourcePtr source = TSqlSelect(Ctx_, Mode_).BuildSubSelect(select_kind); - return LangVersionedSubSelect(std::move(source)); - } - case NSQLv1Generated::TRule_select_or_expr::kAltSelectOrExpr2: - return TupleOrExpr(node.GetAlt_select_or_expr2().GetRule_tuple_or_expr1()); - case NSQLv1Generated::TRule_select_or_expr::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case NSQLv1Generated::TRule_select_or_expr::kAltSelectOrExpr1: { + const auto& select_kind = node.GetAlt_select_or_expr1().GetRule_select_kind_partial1(); + TSourcePtr source = TSqlSelect(Ctx_, Mode_).BuildSubSelect(select_kind); + return LangVersionedSubSelect(std::move(source)); + } + case NSQLv1Generated::TRule_select_or_expr::kAltSelectOrExpr2: + return TupleOrExpr(node.GetAlt_select_or_expr2().GetRule_tuple_or_expr1()); + case NSQLv1Generated::TRule_select_or_expr::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } } @@ -2436,7 +2418,7 @@ TNodePtr TSqlExpression::TupleOrExpr(const TRule_tuple_or_expr& node) { bool hasAliases = false; bool hasUnnamed = false; - for (const auto& expr: exprs) { + for (const auto& expr : exprs) { if (expr->GetLabel()) { hasAliases = true; } else { @@ -2473,12 +2455,12 @@ TNodePtr TSqlExpression::EmptyTuple() { TNodePtr TSqlExpression::SmartParenthesis(const TRule_smart_parenthesis& node) { Token(node.GetToken1()); switch (node.GetBlock2().GetAltCase()) { - case NSQLv1Generated::TRule_smart_parenthesis_TBlock2::kAlt1: - return SelectSubExpr(node.GetBlock2().GetAlt1().GetRule_select_subexpr1()); - case NSQLv1Generated::TRule_smart_parenthesis_TBlock2::kAlt2: - return EmptyTuple(); - case NSQLv1Generated::TRule_smart_parenthesis_TBlock2::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case NSQLv1Generated::TRule_smart_parenthesis_TBlock2::kAlt1: + return SelectSubExpr(node.GetBlock2().GetAlt1().GetRule_select_subexpr1()); + case NSQLv1Generated::TRule_smart_parenthesis_TBlock2::kAlt2: + return EmptyTuple(); + case NSQLv1Generated::TRule_smart_parenthesis_TBlock2::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } } diff --git a/yql/essentials/sql/v1/sql_expression.h b/yql/essentials/sql/v1/sql_expression.h index 3751d80aefd..66025de97c1 100644 --- a/yql/essentials/sql/v1/sql_expression.h +++ b/yql/essentials/sql/v1/sql_expression.h @@ -36,6 +36,7 @@ public: } TMaybe<TExprOrIdent> LiteralExpr(const TRule_literal_value& node); + private: struct TTrailingQuestions { size_t Count = 0; @@ -69,10 +70,10 @@ private: TNodePtr JsonQueryExpr(const TRule_json_query& node); TNodePtr JsonApiExpr(const TRule_json_api_expr& node); - template<typename TUnaryCasualExprRule> + template <typename TUnaryCasualExprRule> TNodePtr UnaryCasualExpr(const TUnaryCasualExprRule& node, const TTrailingQuestions& tail); - template<typename TUnarySubExprRule> + template <typename TUnarySubExprRule> TNodePtr UnaryExpr(const TUnarySubExprRule& node, const TTrailingQuestions& tail); bool SqlLambdaParams(const TNodePtr& node, TVector<TSymbolNameWithPos>& args, ui32& optionalArgumentsCount); diff --git a/yql/essentials/sql/v1/sql_group_by.cpp b/yql/essentials/sql/v1/sql_group_by.cpp index 348ce2471b8..deca5b6e534 100644 --- a/yql/essentials/sql/v1/sql_group_by.cpp +++ b/yql/essentials/sql/v1/sql_group_by.cpp @@ -68,7 +68,7 @@ bool TGroupByClause::ParseList(const TRule_grouping_element_list& groupingListNo if (!GroupingElement(groupingListNode.GetRule_grouping_element1(), featureContext)) { return false; } - for (auto b: groupingListNode.GetBlock2()) { + for (auto b : groupingListNode.GetBlock2()) { if (!GroupingElement(b.GetRule_grouping_element2(), featureContext)) { return false; } @@ -121,14 +121,14 @@ TString TGroupByClause::GetSuffix() const { TMaybe<TVector<TNodePtr>> TGroupByClause::MultiplyGroupingSets(const TVector<TNodePtr>& lhs, const TVector<TNodePtr>& rhs) const { TVector<TNodePtr> content; - for (const auto& leftNode: lhs) { + for (const auto& leftNode : lhs) { auto leftPtr = leftNode->ContentListPtr(); if (!leftPtr) { // TODO: shouldn't happen Ctx_.Error() << "Unable to multiply grouping sets"; return {}; } - for (const auto& rightNode: rhs) { + for (const auto& rightNode : rhs) { TVector<TNodePtr> mulItem(leftPtr->begin(), leftPtr->end()); auto rightPtr = rightNode->ContentListPtr(); if (!rightPtr) { @@ -196,7 +196,7 @@ bool TGroupByClause::GroupingElement(const TRule_grouping_element& node, EGroupB case TRule_grouping_element::kAltGroupingElement2: { TGroupByClause subClause(Ctx_, Mode_, GroupSetContext_); if (!subClause.OrdinaryGroupingSetList(node.GetAlt_grouping_element2().GetRule_rollup_list1().GetRule_ordinary_grouping_set_list3(), - EGroupByFeatures::Rollup)) + EGroupByFeatures::Rollup)) { return false; } @@ -215,7 +215,7 @@ bool TGroupByClause::GroupingElement(const TRule_grouping_element& node, EGroupB case TRule_grouping_element::kAltGroupingElement3: { TGroupByClause subClause(Ctx_, Mode_, GroupSetContext_); if (!subClause.OrdinaryGroupingSetList(node.GetAlt_grouping_element3().GetRule_cube_list1().GetRule_ordinary_grouping_set_list3(), - EGroupByFeatures::Cube)) + EGroupByFeatures::Cube)) { return false; } @@ -249,11 +249,11 @@ bool TGroupByClause::GroupingElement(const TRule_grouping_element& node, EGroupB auto& content = subClause.Content(); TVector<TNodePtr> collection; bool hasEmpty = false; - for (auto& elem: content) { + for (auto& elem : content) { auto elemContent = elem->ContentListPtr(); if (elemContent) { if (!elemContent->empty() && elemContent->front()->ContentListPtr()) { - for (auto& sub: *elemContent) { + for (auto& sub : *elemContent) { FeedCollection(sub, collection, hasEmpty); } } else { @@ -308,7 +308,7 @@ bool TGroupByClause::OrdinaryGroupingSet(const TRule_ordinary_grouping_set& node Ctx_.IncrementMonCounter("sql_errors", "GroupByAliasForListOfExpressions"); return false; } - for (auto& content: *contentPtr) { + for (auto& content : *contentPtr) { auto label = content->GetLabel(); if (!label) { if (content->GetColumnName()) { @@ -353,7 +353,7 @@ bool TGroupByClause::OrdinaryGroupingSetList(const TRule_ordinary_grouping_set_l if (!OrdinaryGroupingSet(node.GetRule_ordinary_grouping_set1(), featureContext)) { return false; } - for (auto& block: node.GetBlock2()) { + for (auto& block : node.GetBlock2()) { if (!OrdinaryGroupingSet(block.GetRule_ordinary_grouping_set2(), featureContext)) { return false; } @@ -375,7 +375,7 @@ bool TGroupByClause::HoppingWindow(const TRule_hopping_window_specification& nod return false; } } - auto processIntervalParam = [&] (const TRule_expr& rule) -> TNodePtr { + auto processIntervalParam = [&](const TRule_expr& rule) -> TNodePtr { TSqlExpression expr(Ctx_, Mode_); auto node = expr.Build(rule); if (!node) { @@ -384,10 +384,8 @@ bool TGroupByClause::HoppingWindow(const TRule_hopping_window_specification& nod auto literal = node->GetLiteral("String"); if (!literal) { - return new TAstListNodeImpl(Ctx_.Pos(), { - new TAstAtomNodeImpl(Ctx_.Pos(), "EvaluateExpr", TNodeFlags::Default), - node - }); + return new TAstListNodeImpl(Ctx_.Pos(), {new TAstAtomNodeImpl(Ctx_.Pos(), "EvaluateExpr", TNodeFlags::Default), + node}); } const auto out = NKikimr::NMiniKQL::ValueFromString(NKikimr::NUdf::EDataSlot::Interval, *literal); @@ -401,13 +399,9 @@ bool TGroupByClause::HoppingWindow(const TRule_hopping_window_specification& nod return nullptr; } - return new TAstListNodeImpl(Ctx_.Pos(), { - new TAstAtomNodeImpl(Ctx_.Pos(), "Interval", TNodeFlags::Default), - new TAstListNodeImpl(Ctx_.Pos(), { - new TAstAtomNodeImpl(Ctx_.Pos(), "quote", TNodeFlags::Default), - new TAstAtomNodeImpl(Ctx_.Pos(), ToString(out.Get<i64>()), TNodeFlags::Default) - }) - }); + return new TAstListNodeImpl(Ctx_.Pos(), {new TAstAtomNodeImpl(Ctx_.Pos(), "Interval", TNodeFlags::Default), + new TAstListNodeImpl(Ctx_.Pos(), {new TAstAtomNodeImpl(Ctx_.Pos(), "quote", TNodeFlags::Default), + new TAstAtomNodeImpl(Ctx_.Pos(), ToString(out.Get<i64>()), TNodeFlags::Default)})}); }; LegacyHoppingWindowSpec_->Hop = processIntervalParam(node.GetRule_expr5()); diff --git a/yql/essentials/sql/v1/sql_group_by.h b/yql/essentials/sql/v1/sql_group_by.h index 4eda3447d32..1f16b6962a2 100644 --- a/yql/essentials/sql/v1/sql_group_by.h +++ b/yql/essentials/sql/v1/sql_group_by.h @@ -33,7 +33,8 @@ public: : TSqlTranslation(ctx, mode) , GroupSetContext_(groupSetContext ? groupSetContext : TGroupByClauseCtx::TPtr(new TGroupByClauseCtx())) , CompactGroupBy_(false) - {} + { + } bool Build(const TRule_group_by_clause& node); bool ParseList(const TRule_grouping_element_list& groupingListNode, EGroupByFeatures featureContext); diff --git a/yql/essentials/sql/v1/sql_into_tables.cpp b/yql/essentials/sql/v1/sql_into_tables.cpp index 2bdd48a81d1..9ea8bd36f04 100644 --- a/yql/essentials/sql/v1/sql_into_tables.cpp +++ b/yql/essentials/sql/v1/sql_into_tables.cpp @@ -17,8 +17,7 @@ TNodePtr TSqlIntoTable::Build(const TRule_into_table_stmt& node) { {"InsertOrRevertInto", ESQLWriteColumnMode::InsertOrRevertInto}, {"UpsertInto", ESQLWriteColumnMode::UpsertInto}, {"ReplaceInto", ESQLWriteColumnMode::ReplaceInto}, - {"InsertIntoWithTruncate", ESQLWriteColumnMode::InsertIntoWithTruncate} - }; + {"InsertIntoWithTruncate", ESQLWriteColumnMode::InsertIntoWithTruncate}}; auto& modeBlock = node.GetBlock1(); @@ -31,22 +30,19 @@ TNodePtr TSqlIntoTable::Build(const TRule_into_table_stmt& node) { modeTokens = { modeBlock.GetAlt2().GetToken1(), modeBlock.GetAlt2().GetToken2(), - modeBlock.GetAlt2().GetToken3() - }; + modeBlock.GetAlt2().GetToken3()}; break; case TRule_into_table_stmt_TBlock1::AltCase::kAlt3: modeTokens = { modeBlock.GetAlt3().GetToken1(), modeBlock.GetAlt3().GetToken2(), - modeBlock.GetAlt3().GetToken3() - }; + modeBlock.GetAlt3().GetToken3()}; break; case TRule_into_table_stmt_TBlock1::AltCase::kAlt4: modeTokens = { modeBlock.GetAlt4().GetToken1(), modeBlock.GetAlt4().GetToken2(), - modeBlock.GetAlt4().GetToken3() - }; + modeBlock.GetAlt4().GetToken3()}; break; case TRule_into_table_stmt_TBlock1::AltCase::kAlt5: modeTokens = {modeBlock.GetAlt5().GetToken1()}; @@ -91,28 +87,24 @@ TNodePtr TSqlIntoTable::Build(const TRule_into_table_stmt& node) { std::pair<bool, TDeferredAtom> nameOrAt; bool isBinding = false; - const bool isClusterSpecified = ( - (tableRefCore.HasAlt_simple_table_ref_core1() && - tableRefCore.GetAlt_simple_table_ref_core1().GetRule_object_ref1().HasBlock1()) || - (tableRefCore.HasAlt_simple_table_ref_core2() && - tableRefCore.GetAlt_simple_table_ref_core2().HasBlock1()) - ); + const bool isClusterSpecified = ((tableRefCore.HasAlt_simple_table_ref_core1() && + tableRefCore.GetAlt_simple_table_ref_core1().GetRule_object_ref1().HasBlock1()) || + (tableRefCore.HasAlt_simple_table_ref_core2() && + tableRefCore.GetAlt_simple_table_ref_core2().HasBlock1())); - const bool hasAt = ( - (tableRefCore.HasAlt_simple_table_ref_core1() && - tableRefCore.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetRule_id_or_at2().HasBlock1()) || - (tableRefCore.HasAlt_simple_table_ref_core2() && - tableRefCore.GetAlt_simple_table_ref_core2().HasBlock2()) - ); + const bool hasAt = ((tableRefCore.HasAlt_simple_table_ref_core1() && + tableRefCore.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetRule_id_or_at2().HasBlock1()) || + (tableRefCore.HasAlt_simple_table_ref_core2() && + tableRefCore.GetAlt_simple_table_ref_core2().HasBlock2())); if (isClusterSpecified) { const auto& clusterExpr = tableRefCore.HasAlt_simple_table_ref_core1() - ? tableRefCore.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetBlock1().GetRule_cluster_expr1() - : tableRefCore.GetAlt_simple_table_ref_core2().GetBlock1().GetRule_cluster_expr1(); + ? tableRefCore.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetBlock1().GetRule_cluster_expr1() + : tableRefCore.GetAlt_simple_table_ref_core2().GetBlock1().GetRule_cluster_expr1(); const bool result = !hasAt - ? ClusterExprOrBinding(clusterExpr, service, cluster, isBinding) - : ClusterExpr(clusterExpr, false, service, cluster); + ? ClusterExprOrBinding(clusterExpr, service, cluster, isBinding) + : ClusterExpr(clusterExpr, false, service, cluster); if (!result) { return nullptr; @@ -164,7 +156,7 @@ TNodePtr TSqlIntoTable::Build(const TRule_into_table_stmt& node) { withTruncate = true; } } - std::erase_if(*hints, [](const auto &hint) { return to_upper(hint.first) == "TRUNCATE"; }); + std::erase_if(*hints, [](const auto& hint) { return to_upper(hint.first) == "TRUNCATE"; }); tableHints = std::move(*hints); } @@ -176,8 +168,7 @@ TNodePtr TSqlIntoTable::Build(const TRule_into_table_stmt& node) { } PureColumnListStr( - intoTableRef.GetBlock2().GetRule_pure_column_list3(), *this, eraseColumns - ); + intoTableRef.GetBlock2().GetRule_pure_column_list3(), *this, eraseColumns); } if (withTruncate) { @@ -228,7 +219,7 @@ TNodePtr TSqlIntoTable::Build(const TRule_into_table_stmt& node) { } bool TSqlIntoTable::ValidateServiceName(const TRule_into_table_stmt& node, const TTableRef& table, - ESQLWriteColumnMode mode, const TPosition& pos) { + ESQLWriteColumnMode mode, const TPosition& pos) { Y_UNUSED(node); auto serviceName = table.Service; if (serviceName == UnknownProviderName) { diff --git a/yql/essentials/sql/v1/sql_into_tables.h b/yql/essentials/sql/v1/sql_into_tables.h index 03cfc9d994d..7fb3e01897b 100644 --- a/yql/essentials/sql/v1/sql_into_tables.h +++ b/yql/essentials/sql/v1/sql_into_tables.h @@ -16,12 +16,12 @@ public: TNodePtr Build(const TRule_into_table_stmt& node); private: - //bool BuildValuesRow(const TRule_values_source_row& inRow, TVector<TNodePtr>& outRow); - //TSourcePtr ValuesSource(const TRule_values_source& node, TVector<TString>& columnsHint); - //TSourcePtr IntoValuesSource(const TRule_into_values_source& node); + // bool BuildValuesRow(const TRule_values_source_row& inRow, TVector<TNodePtr>& outRow); + // TSourcePtr ValuesSource(const TRule_values_source& node, TVector<TString>& columnsHint); + // TSourcePtr IntoValuesSource(const TRule_into_values_source& node); bool ValidateServiceName(const TRule_into_table_stmt& node, const TTableRef& table, ESQLWriteColumnMode mode, - const TPosition& pos); + const TPosition& pos); TString SqlIntoModeStr_; TString SqlIntoUserModeStr_; }; diff --git a/yql/essentials/sql/v1/sql_match_recognize.cpp b/yql/essentials/sql/v1/sql_match_recognize.cpp index 9591b468ac5..d23d7911c9f 100644 --- a/yql/essentials/sql/v1/sql_match_recognize.cpp +++ b/yql/essentials/sql/v1/sql_match_recognize.cpp @@ -7,9 +7,12 @@ namespace NSQLTranslationV1 { -TSqlMatchRecognizeClause::TSqlMatchRecognizeClause(TContext& ctx, NSQLTranslation::ESqlMode mode) : TSqlTranslation(ctx, mode) {} +TSqlMatchRecognizeClause::TSqlMatchRecognizeClause(TContext& ctx, NSQLTranslation::ESqlMode mode) + : TSqlTranslation(ctx, mode) +{ +} -TMatchRecognizeBuilderPtr TSqlMatchRecognizeClause::CreateBuilder(const NSQLv1Generated::TRule_row_pattern_recognition_clause &matchRecognizeClause) { +TMatchRecognizeBuilderPtr TSqlMatchRecognizeClause::CreateBuilder(const NSQLv1Generated::TRule_row_pattern_recognition_clause& matchRecognizeClause) { auto pos = GetPos(matchRecognizeClause.GetToken1()); if (!Ctx_.FeatureR010) { Ctx_.Error(pos, TIssuesIds::CORE) << "Unexpected MATCH_RECOGNIZE"; @@ -20,14 +23,12 @@ TMatchRecognizeBuilderPtr TSqlMatchRecognizeClause::CreateBuilder(const NSQLv1Ge pos, matchRecognizeClause.HasBlock3() ? std::addressof(matchRecognizeClause.GetBlock3().GetRule_window_partition_clause1()) - : nullptr - ); + : nullptr); auto sortSpecs = ParseOrderBy( matchRecognizeClause.HasBlock4() ? std::addressof(matchRecognizeClause.GetBlock4().GetRule_order_by_clause1()) - : nullptr - ); + : nullptr); if (!sortSpecs) { return {}; } @@ -35,15 +36,13 @@ TMatchRecognizeBuilderPtr TSqlMatchRecognizeClause::CreateBuilder(const NSQLv1Ge auto measures = ParseMeasures( matchRecognizeClause.HasBlock5() ? std::addressof(matchRecognizeClause.GetBlock5().GetRule_row_pattern_measures1().GetRule_row_pattern_measure_list2()) - : nullptr - ); + : nullptr); auto rowsPerMatch = ParseRowsPerMatch( pos, matchRecognizeClause.HasBlock6() ? std::addressof(matchRecognizeClause.GetBlock6().GetRule_row_pattern_rows_per_match1()) - : nullptr - ); + : nullptr); if (!rowsPerMatch) { return {}; } @@ -67,8 +66,7 @@ TMatchRecognizeBuilderPtr TSqlMatchRecognizeClause::CreateBuilder(const NSQLv1Ge pos, commonSyntax.HasBlock1() ? std::addressof(commonSyntax.GetBlock1().GetRule_row_pattern_skip_to3()) - : nullptr - ); + : nullptr); if (!skipTo) { return {}; } @@ -77,14 +75,13 @@ TMatchRecognizeBuilderPtr TSqlMatchRecognizeClause::CreateBuilder(const NSQLv1Ge pos, commonSyntax.HasBlock7() ? std::addressof(commonSyntax.GetBlock7().GetRule_row_pattern_subset_clause1()) - : nullptr - ); + : nullptr); if (!subset) { return {}; } auto definitions = ParseDefinitions(commonSyntax.GetRule_row_pattern_definition_list9()); - for (const auto& [callable, name]: definitions) { + for (const auto& [callable, name] : definitions) { if (!PatternVarNames_.contains(name)) { Ctx_.Error(callable->GetPos()) << "ROW PATTERN VARIABLE " << name << " is defined, but not mentioned in the PATTERN"; return {}; @@ -102,8 +99,7 @@ TMatchRecognizeBuilderPtr TSqlMatchRecognizeClause::CreateBuilder(const NSQLv1Ge std::move(pattern), std::move(PatternVars_), std::move(*subset), - std::move(definitions) - ); + std::move(definitions)); } std::tuple<TNodePtr, TNodePtr> TSqlMatchRecognizeClause::ParsePartitionBy(TPosition pos, const TRule_window_partition_clause* node) { @@ -130,8 +126,7 @@ std::tuple<TNodePtr, TNodePtr> TSqlMatchRecognizeClause::ParsePartitionBy(TPosit }(); return { BuildLambda(pos, BuildList(pos, {BuildAtom(pos, "row")}), BuildQuote(pos, std::move(partitionKeySelector))), - BuildQuote(pos, std::move(partitionColumns)) - }; + BuildQuote(pos, std::move(partitionColumns))}; } TMaybe<TVector<TSortSpecificationPtr>> TSqlMatchRecognizeClause::ParseOrderBy(const TRule_order_by_clause* node) { @@ -160,7 +155,7 @@ TVector<TNamedFunction> TSqlMatchRecognizeClause::ParseMeasures(const TRule_row_ return {}; } TVector<TNamedFunction> result{ParseOneMeasure(node->GetRule_row_pattern_measure_definition1())}; - for (const auto& m: node->GetBlock2()) { + for (const auto& m : node->GetBlock2()) { result.push_back(ParseOneMeasure(m.GetRule_row_pattern_measure_definition2())); } return result; @@ -172,18 +167,18 @@ TNodePtr TSqlMatchRecognizeClause::ParseRowsPerMatch(TPosition pos, const TRule_ return NYql::NMatchRecognize::ERowsPerMatch::OneRow; } switch (node->GetAltCase()) { - case TRule_row_pattern_rows_per_match::kAltRowPatternRowsPerMatch1: { - const auto& rowsPerMatch = node->GetAlt_row_pattern_rows_per_match1(); - pos = GetPos(rowsPerMatch.GetToken1()); - return NYql::NMatchRecognize::ERowsPerMatch::OneRow; - } - case TRule_row_pattern_rows_per_match::kAltRowPatternRowsPerMatch2: { - const auto& rowsPerMatch = node->GetAlt_row_pattern_rows_per_match2(); - pos = GetPos(rowsPerMatch.GetToken1()); - return NYql::NMatchRecognize::ERowsPerMatch::AllRows; - } - case TRule_row_pattern_rows_per_match::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_row_pattern_rows_per_match::kAltRowPatternRowsPerMatch1: { + const auto& rowsPerMatch = node->GetAlt_row_pattern_rows_per_match1(); + pos = GetPos(rowsPerMatch.GetToken1()); + return NYql::NMatchRecognize::ERowsPerMatch::OneRow; + } + case TRule_row_pattern_rows_per_match::kAltRowPatternRowsPerMatch2: { + const auto& rowsPerMatch = node->GetAlt_row_pattern_rows_per_match2(); + pos = GetPos(rowsPerMatch.GetToken1()); + return NYql::NMatchRecognize::ERowsPerMatch::AllRows; + } + case TRule_row_pattern_rows_per_match::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } }(); return BuildQuotedAtom(pos, "RowsPerMatch_" + ToString(result)); @@ -197,67 +192,65 @@ TNodePtr TSqlMatchRecognizeClause::ParseAfterMatchSkipTo(TPosition pos, const TR return NYql::NMatchRecognize::TAfterMatchSkipTo{NYql::NMatchRecognize::EAfterMatchSkipTo::PastLastRow, ""}; } switch (node->GetAltCase()) { - case TRule_row_pattern_skip_to::kAltRowPatternSkipTo1: { - const auto& skipTo = node->GetAlt_row_pattern_skip_to1(); - skipToPos = GetPos(skipTo.GetToken1()); - return NYql::NMatchRecognize::TAfterMatchSkipTo{NYql::NMatchRecognize::EAfterMatchSkipTo::NextRow, ""}; - } - case TRule_row_pattern_skip_to::kAltRowPatternSkipTo2: { - const auto& skipTo = node->GetAlt_row_pattern_skip_to2(); - skipToPos = GetPos(skipTo.GetToken1()); - return NYql::NMatchRecognize::TAfterMatchSkipTo{NYql::NMatchRecognize::EAfterMatchSkipTo::PastLastRow, ""}; - } - case TRule_row_pattern_skip_to::kAltRowPatternSkipTo3: { - const auto& skipTo = node->GetAlt_row_pattern_skip_to3(); - skipToPos = GetPos(skipTo.GetToken1()); - const auto& identifier = skipTo.GetRule_row_pattern_skip_to_variable_name4().GetRule_row_pattern_variable_name1().GetRule_identifier1(); - auto var = identifier.GetToken1().GetValue(); - varPos = GetPos(identifier.GetToken1()); - if (!PatternVarNames_.contains(var)) { - Ctx_.Error(varPos) << "Unknown pattern variable in AFTER MATCH SKIP TO FIRST"; - return {}; + case TRule_row_pattern_skip_to::kAltRowPatternSkipTo1: { + const auto& skipTo = node->GetAlt_row_pattern_skip_to1(); + skipToPos = GetPos(skipTo.GetToken1()); + return NYql::NMatchRecognize::TAfterMatchSkipTo{NYql::NMatchRecognize::EAfterMatchSkipTo::NextRow, ""}; } - return NYql::NMatchRecognize::TAfterMatchSkipTo{NYql::NMatchRecognize::EAfterMatchSkipTo::ToFirst, std::move(var)}; - } - case TRule_row_pattern_skip_to::kAltRowPatternSkipTo4: { - const auto& skipTo = node->GetAlt_row_pattern_skip_to4(); - skipToPos = GetPos(skipTo.GetToken1()); - const auto& identifier = skipTo.GetRule_row_pattern_skip_to_variable_name4().GetRule_row_pattern_variable_name1().GetRule_identifier1(); - auto var = identifier.GetToken1().GetValue(); - varPos = GetPos(identifier.GetToken1()); - if (!PatternVarNames_.contains(var)) { - Ctx_.Error(varPos) << "Unknown pattern variable in AFTER MATCH SKIP TO LAST"; - return {}; + case TRule_row_pattern_skip_to::kAltRowPatternSkipTo2: { + const auto& skipTo = node->GetAlt_row_pattern_skip_to2(); + skipToPos = GetPos(skipTo.GetToken1()); + return NYql::NMatchRecognize::TAfterMatchSkipTo{NYql::NMatchRecognize::EAfterMatchSkipTo::PastLastRow, ""}; } - return NYql::NMatchRecognize::TAfterMatchSkipTo{NYql::NMatchRecognize::EAfterMatchSkipTo::ToLast, std::move(var)}; - } - case TRule_row_pattern_skip_to::kAltRowPatternSkipTo5: { - const auto& skipTo = node->GetAlt_row_pattern_skip_to5(); - skipToPos = GetPos(skipTo.GetToken1()); - const auto& identifier = skipTo.GetRule_row_pattern_skip_to_variable_name3().GetRule_row_pattern_variable_name1().GetRule_identifier1(); - auto var = identifier.GetToken1().GetValue(); - varPos = GetPos(identifier.GetToken1()); - if (!PatternVarNames_.contains(var)) { - Ctx_.Error(varPos) << "Unknown pattern variable in AFTER MATCH SKIP TO"; - return {}; + case TRule_row_pattern_skip_to::kAltRowPatternSkipTo3: { + const auto& skipTo = node->GetAlt_row_pattern_skip_to3(); + skipToPos = GetPos(skipTo.GetToken1()); + const auto& identifier = skipTo.GetRule_row_pattern_skip_to_variable_name4().GetRule_row_pattern_variable_name1().GetRule_identifier1(); + auto var = identifier.GetToken1().GetValue(); + varPos = GetPos(identifier.GetToken1()); + if (!PatternVarNames_.contains(var)) { + Ctx_.Error(varPos) << "Unknown pattern variable in AFTER MATCH SKIP TO FIRST"; + return {}; + } + return NYql::NMatchRecognize::TAfterMatchSkipTo{NYql::NMatchRecognize::EAfterMatchSkipTo::ToFirst, std::move(var)}; } - return NYql::NMatchRecognize::TAfterMatchSkipTo{NYql::NMatchRecognize::EAfterMatchSkipTo::To, std::move(var)}; - } - case TRule_row_pattern_skip_to::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_row_pattern_skip_to::kAltRowPatternSkipTo4: { + const auto& skipTo = node->GetAlt_row_pattern_skip_to4(); + skipToPos = GetPos(skipTo.GetToken1()); + const auto& identifier = skipTo.GetRule_row_pattern_skip_to_variable_name4().GetRule_row_pattern_variable_name1().GetRule_identifier1(); + auto var = identifier.GetToken1().GetValue(); + varPos = GetPos(identifier.GetToken1()); + if (!PatternVarNames_.contains(var)) { + Ctx_.Error(varPos) << "Unknown pattern variable in AFTER MATCH SKIP TO LAST"; + return {}; + } + return NYql::NMatchRecognize::TAfterMatchSkipTo{NYql::NMatchRecognize::EAfterMatchSkipTo::ToLast, std::move(var)}; + } + case TRule_row_pattern_skip_to::kAltRowPatternSkipTo5: { + const auto& skipTo = node->GetAlt_row_pattern_skip_to5(); + skipToPos = GetPos(skipTo.GetToken1()); + const auto& identifier = skipTo.GetRule_row_pattern_skip_to_variable_name3().GetRule_row_pattern_variable_name1().GetRule_identifier1(); + auto var = identifier.GetToken1().GetValue(); + varPos = GetPos(identifier.GetToken1()); + if (!PatternVarNames_.contains(var)) { + Ctx_.Error(varPos) << "Unknown pattern variable in AFTER MATCH SKIP TO"; + return {}; + } + return NYql::NMatchRecognize::TAfterMatchSkipTo{NYql::NMatchRecognize::EAfterMatchSkipTo::To, std::move(var)}; + } + case TRule_row_pattern_skip_to::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } }(); if (!result) { return {}; } - return BuildTuple(pos, { - BuildQuotedAtom(skipToPos, "AfterMatchSkip_" + ToString(result->To)), - BuildQuotedAtom(varPos, std::move(result->Var)) - }); + return BuildTuple(pos, {BuildQuotedAtom(skipToPos, "AfterMatchSkip_" + ToString(result->To)), + BuildQuotedAtom(varPos, std::move(result->Var))}); } TNodePtr TSqlMatchRecognizeClause::BuildPatternFactor(TPosition pos, TNodePtr primary, std::tuple<ui64, ui64, bool, bool, bool> quantifier) { - return std::apply([&](const auto& ...args) { + return std::apply([&](const auto&... args) { return BuildTuple(pos, {std::move(primary), BuildQuotedAtom(pos, ToString(args))...}); }, quantifier); } @@ -270,72 +263,71 @@ TNodePtr TSqlMatchRecognizeClause::ParsePatternFactor(TPosition pos, const TRule auto primary = [&]() -> TNodePtr { const auto& primaryAlt = node.GetRule_row_pattern_primary1(); switch (primaryAlt.GetAltCase()) { - case TRule_row_pattern_primary::kAltRowPatternPrimary1: { - const auto& primary = primaryAlt.GetAlt_row_pattern_primary1(); - const auto& identifier = primary.GetRule_row_pattern_primary_variable_name1().GetRule_row_pattern_variable_name1().GetRule_identifier1(); - const auto varName = Id(identifier, *this); - const auto var = BuildQuotedAtom(GetPos(identifier.GetToken1()), varName); - if (PatternVarNames_.insert(varName).second) { - PatternVars_->Add(var); + case TRule_row_pattern_primary::kAltRowPatternPrimary1: { + const auto& primary = primaryAlt.GetAlt_row_pattern_primary1(); + const auto& identifier = primary.GetRule_row_pattern_primary_variable_name1().GetRule_row_pattern_variable_name1().GetRule_identifier1(); + const auto varName = Id(identifier, *this); + const auto var = BuildQuotedAtom(GetPos(identifier.GetToken1()), varName); + if (PatternVarNames_.insert(varName).second) { + PatternVars_->Add(var); + } + return var; } - return var; - } - case TRule_row_pattern_primary::kAltRowPatternPrimary2: { - const auto& primary = primaryAlt.GetAlt_row_pattern_primary2(); - const auto& token = primary.GetToken1(); - const auto varName = token.GetValue(); - const auto var = BuildQuotedAtom(GetPos(token), varName); - if (PatternVarNames_.insert(varName).second) { - PatternVars_->Add(var); + case TRule_row_pattern_primary::kAltRowPatternPrimary2: { + const auto& primary = primaryAlt.GetAlt_row_pattern_primary2(); + const auto& token = primary.GetToken1(); + const auto varName = token.GetValue(); + const auto var = BuildQuotedAtom(GetPos(token), varName); + if (PatternVarNames_.insert(varName).second) { + PatternVars_->Add(var); + } + return var; } - return var; - } - case TRule_row_pattern_primary::kAltRowPatternPrimary3: { - const auto& primary = primaryAlt.GetAlt_row_pattern_primary3(); - const auto& token = primary.GetToken1(); - const auto varName = token.GetValue(); - const auto var = BuildQuotedAtom(GetPos(token), varName); - if (PatternVarNames_.insert(varName).second) { - PatternVars_->Add(var); + case TRule_row_pattern_primary::kAltRowPatternPrimary3: { + const auto& primary = primaryAlt.GetAlt_row_pattern_primary3(); + const auto& token = primary.GetToken1(); + const auto varName = token.GetValue(); + const auto var = BuildQuotedAtom(GetPos(token), varName); + if (PatternVarNames_.insert(varName).second) { + PatternVars_->Add(var); + } + return var; } - return var; - } - case TRule_row_pattern_primary::kAltRowPatternPrimary4: { - const auto& primary = primaryAlt.GetAlt_row_pattern_primary4(); - return ParsePattern(pos, primary.GetBlock2().GetRule_row_pattern1(), nestingLevel + 1, output); - } - case TRule_row_pattern_primary::kAltRowPatternPrimary5: { - const auto& primary = primaryAlt.GetAlt_row_pattern_primary5(); - output = false; - return ParsePattern(pos, primary.GetRule_row_pattern3(), nestingLevel + 1, output); - } - case TRule_row_pattern_primary::kAltRowPatternPrimary6: { - const auto& primary = primaryAlt.GetAlt_row_pattern_primary6(); - std::vector<TNodePtr> items{ - ParsePattern(pos, primary.GetRule_row_pattern_permute1().GetRule_row_pattern3(), nestingLevel + 1, output) - }; - for (const auto& p: primary.GetRule_row_pattern_permute1().GetBlock4()) { - items.push_back(ParsePattern(pos, p.GetRule_row_pattern2(), nestingLevel + 1, output)); + case TRule_row_pattern_primary::kAltRowPatternPrimary4: { + const auto& primary = primaryAlt.GetAlt_row_pattern_primary4(); + return ParsePattern(pos, primary.GetBlock2().GetRule_row_pattern1(), nestingLevel + 1, output); } - if (items.size() > MaxPermutedItems) { - Ctx_.Error(GetPos(primary.GetRule_row_pattern_permute1().GetToken1())) << "Too many items in permute"; - return {}; + case TRule_row_pattern_primary::kAltRowPatternPrimary5: { + const auto& primary = primaryAlt.GetAlt_row_pattern_primary5(); + output = false; + return ParsePattern(pos, primary.GetRule_row_pattern3(), nestingLevel + 1, output); } - std::vector<size_t> indexes(items.size()); - Iota(indexes.begin(), indexes.end(), 0); - std::vector<TNodePtr> result; - do { - std::vector<TNodePtr> term; - term.reserve(items.size()); - for (auto index : indexes) { - term.push_back(BuildPatternFactor(pos, items[index], std::tuple{1, 1, true, output, false})); + case TRule_row_pattern_primary::kAltRowPatternPrimary6: { + const auto& primary = primaryAlt.GetAlt_row_pattern_primary6(); + std::vector<TNodePtr> items{ + ParsePattern(pos, primary.GetRule_row_pattern_permute1().GetRule_row_pattern3(), nestingLevel + 1, output)}; + for (const auto& p : primary.GetRule_row_pattern_permute1().GetBlock4()) { + items.push_back(ParsePattern(pos, p.GetRule_row_pattern2(), nestingLevel + 1, output)); } - result.push_back(BuildPatternTerm(pos, std::move(term))); - } while (std::next_permutation(indexes.begin(), indexes.end())); - return BuildPattern(pos, std::move(result)); - } - case TRule_row_pattern_primary::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + if (items.size() > MaxPermutedItems) { + Ctx_.Error(GetPos(primary.GetRule_row_pattern_permute1().GetToken1())) << "Too many items in permute"; + return {}; + } + std::vector<size_t> indexes(items.size()); + Iota(indexes.begin(), indexes.end(), 0); + std::vector<TNodePtr> result; + do { + std::vector<TNodePtr> term; + term.reserve(items.size()); + for (auto index : indexes) { + term.push_back(BuildPatternFactor(pos, items[index], std::tuple{1, 1, true, output, false})); + } + result.push_back(BuildPatternTerm(pos, std::move(term))); + } while (std::next_permutation(indexes.begin(), indexes.end())); + return BuildPattern(pos, std::move(result)); + } + case TRule_row_pattern_primary::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } }(); if (!primary) { @@ -349,44 +341,43 @@ TNodePtr TSqlMatchRecognizeClause::ParsePatternFactor(TPosition pos, const TRule } const auto& quantifierAlt = node.GetBlock2().GetRule_row_pattern_quantifier1(); switch (quantifierAlt.GetAltCase()) { - case TRule_row_pattern_quantifier::kAltRowPatternQuantifier1: { // * - const auto& quantifier = quantifierAlt.GetAlt_row_pattern_quantifier1(); - pos = GetPos(quantifier.GetToken1()); - return std::tuple{static_cast<ui64>(0), static_cast<ui64>(Max()), !quantifier.HasBlock2(), output, false}; - } - case TRule_row_pattern_quantifier::kAltRowPatternQuantifier2: { // + - const auto& quantifier = quantifierAlt.GetAlt_row_pattern_quantifier2(); - pos = GetPos(quantifier.GetToken1()); - return std::tuple{static_cast<ui64>(1), static_cast<ui64>(Max()), !quantifier.HasBlock2(), output, false}; - } - case TRule_row_pattern_quantifier::kAltRowPatternQuantifier3: { // ? - const auto& quantifier = quantifierAlt.GetAlt_row_pattern_quantifier3(); - pos = GetPos(quantifier.GetToken1()); - return std::tuple{static_cast<ui64>(0), static_cast<ui64>(1), !quantifier.HasBlock2(), output, false}; - } - case TRule_row_pattern_quantifier::kAltRowPatternQuantifier4: { // {n?, m?} - const auto& quantifier = quantifierAlt.GetAlt_row_pattern_quantifier4(); - pos = GetPos(quantifier.GetToken1()); - return std::tuple{ - quantifier.HasBlock2() - ? FromString(quantifier.GetBlock2().GetRule_integer1().GetToken1().GetValue()) - : static_cast<ui64>(0), - quantifier.HasBlock4() - ? FromString(quantifier.GetBlock4().GetRule_integer1().GetToken1().GetValue()) - : static_cast<ui64>(Max()), - !quantifier.HasBlock6(), - output, - false - }; - } - case TRule_row_pattern_quantifier::kAltRowPatternQuantifier5: { // {n} - const auto quantifier = quantifierAlt.GetAlt_row_pattern_quantifier5(); - pos = GetPos(quantifier.GetToken1()); - const auto quantity = static_cast<ui64>(FromString(quantifier.GetRule_integer2().GetToken1().GetValue())); - return std::tuple{quantity, quantity, true, output, false}; - } - case TRule_row_pattern_quantifier::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_row_pattern_quantifier::kAltRowPatternQuantifier1: { // * + const auto& quantifier = quantifierAlt.GetAlt_row_pattern_quantifier1(); + pos = GetPos(quantifier.GetToken1()); + return std::tuple{static_cast<ui64>(0), static_cast<ui64>(Max()), !quantifier.HasBlock2(), output, false}; + } + case TRule_row_pattern_quantifier::kAltRowPatternQuantifier2: { // + + const auto& quantifier = quantifierAlt.GetAlt_row_pattern_quantifier2(); + pos = GetPos(quantifier.GetToken1()); + return std::tuple{static_cast<ui64>(1), static_cast<ui64>(Max()), !quantifier.HasBlock2(), output, false}; + } + case TRule_row_pattern_quantifier::kAltRowPatternQuantifier3: { // ? + const auto& quantifier = quantifierAlt.GetAlt_row_pattern_quantifier3(); + pos = GetPos(quantifier.GetToken1()); + return std::tuple{static_cast<ui64>(0), static_cast<ui64>(1), !quantifier.HasBlock2(), output, false}; + } + case TRule_row_pattern_quantifier::kAltRowPatternQuantifier4: { // {n?, m?} + const auto& quantifier = quantifierAlt.GetAlt_row_pattern_quantifier4(); + pos = GetPos(quantifier.GetToken1()); + return std::tuple{ + quantifier.HasBlock2() + ? FromString(quantifier.GetBlock2().GetRule_integer1().GetToken1().GetValue()) + : static_cast<ui64>(0), + quantifier.HasBlock4() + ? FromString(quantifier.GetBlock4().GetRule_integer1().GetToken1().GetValue()) + : static_cast<ui64>(Max()), + !quantifier.HasBlock6(), + output, + false}; + } + case TRule_row_pattern_quantifier::kAltRowPatternQuantifier5: { // {n} + const auto quantifier = quantifierAlt.GetAlt_row_pattern_quantifier5(); + pos = GetPos(quantifier.GetToken1()); + const auto quantity = static_cast<ui64>(FromString(quantifier.GetRule_integer2().GetToken1().GetValue())); + return std::tuple{quantity, quantity, true, output, false}; + } + case TRule_row_pattern_quantifier::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } }(); return BuildPatternFactor(pos, std::move(primary), std::move(quantifier)); @@ -406,7 +397,7 @@ TNodePtr TSqlMatchRecognizeClause::BuildPatternTerm(TPosition pos, std::vector<T TNodePtr TSqlMatchRecognizeClause::ParsePatternTerm(TPosition pos, const TRule_row_pattern_term& node, size_t nestingLevel, bool output) { std::vector<TNodePtr> result; result.reserve(node.GetBlock1().size()); - for (const auto& factor: node.GetBlock1()) { + for (const auto& factor : node.GetBlock1()) { result.push_back(ParsePatternFactor(pos, factor.GetRule_row_pattern_factor1(), nestingLevel, output)); } return BuildPatternTerm(pos, std::move(result)); @@ -414,7 +405,7 @@ TNodePtr TSqlMatchRecognizeClause::ParsePatternTerm(TPosition pos, const TRule_r TNodePtr TSqlMatchRecognizeClause::BuildPattern(TPosition pos, std::vector<TNodePtr> pattern) { const auto result = BuildList(pos, {BuildAtom(pos, "MatchRecognizePattern")}); - for (auto& term: pattern) { + for (auto& term : pattern) { if (!term) { return {}; } @@ -427,7 +418,7 @@ TNodePtr TSqlMatchRecognizeClause::ParsePattern(TPosition pos, const TRule_row_p std::vector<TNodePtr> result; result.reserve(1 + node.GetBlock2().size()); result.push_back(ParsePatternTerm(pos, node.GetRule_row_pattern_term1(), nestingLevel, output)); - for (const auto& term: node.GetBlock2()) { + for (const auto& term : node.GetBlock2()) { result.push_back(ParsePatternTerm(pos, term.GetRule_row_pattern_term2(), nestingLevel, output)); } return BuildPattern(pos, std::move(result)); @@ -458,7 +449,7 @@ TNamedFunction TSqlMatchRecognizeClause::ParseOneDefinition(const TRule_row_patt TVector<TNamedFunction> TSqlMatchRecognizeClause::ParseDefinitions(const TRule_row_pattern_definition_list& node) { TVector<TNamedFunction> result{ParseOneDefinition(node.GetRule_row_pattern_definition1())}; - for (const auto& d: node.GetBlock2()) { + for (const auto& d : node.GetBlock2()) { result.push_back(ParseOneDefinition(d.GetRule_row_pattern_definition2())); } return result; diff --git a/yql/essentials/sql/v1/sql_match_recognize.h b/yql/essentials/sql/v1/sql_match_recognize.h index 0a0382c6213..05a8a7804ab 100644 --- a/yql/essentials/sql/v1/sql_match_recognize.h +++ b/yql/essentials/sql/v1/sql_match_recognize.h @@ -6,7 +6,7 @@ namespace NSQLTranslationV1 { -class TSqlMatchRecognizeClause final : public TSqlTranslation { +class TSqlMatchRecognizeClause final: public TSqlTranslation { public: TSqlMatchRecognizeClause(TContext& ctx, NSQLTranslation::ESqlMode mode); TMatchRecognizeBuilderPtr CreateBuilder(const TRule_row_pattern_recognition_clause& node); diff --git a/yql/essentials/sql/v1/sql_match_recognize_ut.cpp b/yql/essentials/sql/v1/sql_match_recognize_ut.cpp index 2604dc17ea2..95f83ea7ea2 100644 --- a/yql/essentials/sql/v1/sql_match_recognize_ut.cpp +++ b/yql/essentials/sql/v1/sql_match_recognize_ut.cpp @@ -38,7 +38,7 @@ bool IsListOfSize(const NYql::TAstNode* node, ui32 size) { return true; } -template<typename Proj = std::identity> +template <typename Proj = std::identity> bool IsListOfAtoms(const NYql::TAstNode* node, std::vector<std::string_view> atoms, Proj proj = {}) { UNIT_ASSERT(IsListOfSize(node, atoms.size())); for (ui32 i = 0; i < atoms.size(); ++i) { @@ -61,7 +61,7 @@ bool IsLambda(const NYql::TAstNode* node, ui32 numberOfArgs) { } Y_UNIT_TEST_SUITE(MatchRecognize) { - auto minValidMatchRecognizeSql = R"( +auto minValidMatchRecognizeSql = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -69,20 +69,20 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - Y_UNIT_TEST(EnabledWithPragma) { - UNIT_ASSERT(not SqlToYql(minValidMatchRecognizeSql).IsOk()); - UNIT_ASSERT(MatchRecognizeSqlToYql(minValidMatchRecognizeSql).IsOk()); - } +Y_UNIT_TEST(EnabledWithPragma) { + UNIT_ASSERT(not SqlToYql(minValidMatchRecognizeSql).IsOk()); + UNIT_ASSERT(MatchRecognizeSqlToYql(minValidMatchRecognizeSql).IsOk()); +} - Y_UNIT_TEST(InputTableName) { - auto r = MatchRecognizeSqlToYql(minValidMatchRecognizeSql); - UNIT_ASSERT(r.IsOk()); - auto input = FindMatchRecognizeParam(r.Root, "input"); - UNIT_ASSERT(IsAtom(input, "core")); - } +Y_UNIT_TEST(InputTableName) { + auto r = MatchRecognizeSqlToYql(minValidMatchRecognizeSql); + UNIT_ASSERT(r.IsOk()); + auto input = FindMatchRecognizeParam(r.Root, "input"); + UNIT_ASSERT(IsAtom(input, "core")); +} - Y_UNIT_TEST(MatchRecognizeAndSample) { - auto matchRecognizeAndSample = R"( +Y_UNIT_TEST(MatchRecognizeAndSample) { + auto matchRecognizeAndSample = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -90,20 +90,20 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) TABLESAMPLE BERNOULLI(1.0) )"; - UNIT_ASSERT(not MatchRecognizeSqlToYql(matchRecognizeAndSample).IsOk()); - } + UNIT_ASSERT(not MatchRecognizeSqlToYql(matchRecognizeAndSample).IsOk()); +} - Y_UNIT_TEST(NoPartitionBy) { - auto r = MatchRecognizeSqlToYql(minValidMatchRecognizeSql); - UNIT_ASSERT(r.IsOk()); - auto partitionKeySelector = FindMatchRecognizeParam(r.Root, "partitionKeySelector"); - UNIT_ASSERT(IsListOfSize(GetQuoted(partitionKeySelector->GetChild(2)), 0)); //empty tuple - auto partitionColumns = FindMatchRecognizeParam(r.Root, "partitionColumns"); - UNIT_ASSERT(IsListOfSize(GetQuoted(partitionColumns), 0)); //empty tuple - } +Y_UNIT_TEST(NoPartitionBy) { + auto r = MatchRecognizeSqlToYql(minValidMatchRecognizeSql); + UNIT_ASSERT(r.IsOk()); + auto partitionKeySelector = FindMatchRecognizeParam(r.Root, "partitionKeySelector"); + UNIT_ASSERT(IsListOfSize(GetQuoted(partitionKeySelector->GetChild(2)), 0)); // empty tuple + auto partitionColumns = FindMatchRecognizeParam(r.Root, "partitionColumns"); + UNIT_ASSERT(IsListOfSize(GetQuoted(partitionColumns), 0)); // empty tuple +} - Y_UNIT_TEST(PartitionBy) { - auto stmt = R"( +Y_UNIT_TEST(PartitionBy) { + auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -112,24 +112,24 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - auto partitionKeySelector = FindMatchRecognizeParam(r.Root, "partitionKeySelector"); - UNIT_ASSERT(IsListOfSize(GetQuoted(partitionKeySelector->GetChild(2)), 3)); - auto partitionColumns = FindMatchRecognizeParam(r.Root, "partitionColumns"); - UNIT_ASSERT(IsListOfSize(GetQuoted(partitionColumns), 3)); - //TODO check partitioner lambdas(alias/no alias) - } + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + auto partitionKeySelector = FindMatchRecognizeParam(r.Root, "partitionKeySelector"); + UNIT_ASSERT(IsListOfSize(GetQuoted(partitionKeySelector->GetChild(2)), 3)); + auto partitionColumns = FindMatchRecognizeParam(r.Root, "partitionColumns"); + UNIT_ASSERT(IsListOfSize(GetQuoted(partitionColumns), 3)); + // TODO check partitioner lambdas(alias/no alias) +} - Y_UNIT_TEST(NoOrderBy) { - auto r = MatchRecognizeSqlToYql(minValidMatchRecognizeSql); - UNIT_ASSERT(r.IsOk()); - auto sortTraits = FindMatchRecognizeParam(r.Root, "sortTraits"); - UNIT_ASSERT(IsListOfAtoms(sortTraits, {"Void"})); - } +Y_UNIT_TEST(NoOrderBy) { + auto r = MatchRecognizeSqlToYql(minValidMatchRecognizeSql); + UNIT_ASSERT(r.IsOk()); + auto sortTraits = FindMatchRecognizeParam(r.Root, "sortTraits"); + UNIT_ASSERT(IsListOfAtoms(sortTraits, {"Void"})); +} - Y_UNIT_TEST(OrderBy) { - auto stmt = R"( +Y_UNIT_TEST(OrderBy) { + auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -138,16 +138,16 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - auto sortTraits = FindMatchRecognizeParam(r.Root, "sortTraits"); - UNIT_ASSERT(IsListOfSize(sortTraits, 4)); - UNIT_ASSERT(IsAtom(sortTraits->GetChild(0), "SortTraits")); - UNIT_ASSERT(IsListOfSize(GetQuoted(sortTraits->GetChild(2)), 3)); - UNIT_ASSERT(IsListOfSize(GetQuoted(sortTraits->GetChild(3)->GetChild(2)), 3)); - } - Y_UNIT_TEST(Measures) { - auto stmt = R"( + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + auto sortTraits = FindMatchRecognizeParam(r.Root, "sortTraits"); + UNIT_ASSERT(IsListOfSize(sortTraits, 4)); + UNIT_ASSERT(IsAtom(sortTraits->GetChild(0), "SortTraits")); + UNIT_ASSERT(IsListOfSize(GetQuoted(sortTraits->GetChild(2)), 3)); + UNIT_ASSERT(IsListOfSize(GetQuoted(sortTraits->GetChild(3)->GetChild(2)), 3)); +} +Y_UNIT_TEST(Measures) { + auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -158,20 +158,20 @@ FROM Input MATCH_RECOGNIZE( DEFINE Y as true ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto measures = FindMatchRecognizeParam(r.Root, "measures"); - UNIT_ASSERT(IsListOfSize(measures, 5)); - const auto patternVars = measures->GetChild(2); - UNIT_ASSERT(IsListOfAtoms(GetQuoted(patternVars), {"Y", "Q"}, GetQuoted)); - const auto measuresNames = measures->GetChild(3); - UNIT_ASSERT(IsListOfAtoms(GetQuoted(measuresNames), {"T", "Key"}, GetQuoted)); - const auto measuresCallables = measures->GetChild(4); - UNIT_ASSERT(IsListOfSize(GetQuoted(measuresCallables), 2)); - } - Y_UNIT_TEST(RowsPerMatch) { - { - const auto stmt = R"( + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto measures = FindMatchRecognizeParam(r.Root, "measures"); + UNIT_ASSERT(IsListOfSize(measures, 5)); + const auto patternVars = measures->GetChild(2); + UNIT_ASSERT(IsListOfAtoms(GetQuoted(patternVars), {"Y", "Q"}, GetQuoted)); + const auto measuresNames = measures->GetChild(3); + UNIT_ASSERT(IsListOfAtoms(GetQuoted(measuresNames), {"T", "Key"}, GetQuoted)); + const auto measuresCallables = measures->GetChild(4); + UNIT_ASSERT(IsListOfSize(GetQuoted(measuresCallables), 2)); +} +Y_UNIT_TEST(RowsPerMatch) { + { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -180,13 +180,13 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - auto rowsPerMatch = FindMatchRecognizeParam(r.Root, "rowsPerMatch"); - UNIT_ASSERT(IsAtom(GetQuoted(rowsPerMatch), "RowsPerMatch_OneRow")); - } - { - const auto stmt = R"( + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + auto rowsPerMatch = FindMatchRecognizeParam(r.Root, "rowsPerMatch"); + UNIT_ASSERT(IsAtom(GetQuoted(rowsPerMatch), "RowsPerMatch_OneRow")); + } + { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -195,11 +195,11 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - } - { //default - const auto stmt = R"( + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + } + { // default + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -207,16 +207,15 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - auto rowsPerMatch = FindMatchRecognizeParam(r.Root, "rowsPerMatch"); - UNIT_ASSERT(IsAtom(GetQuoted(rowsPerMatch), "RowsPerMatch_OneRow")); - } - + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + auto rowsPerMatch = FindMatchRecognizeParam(r.Root, "rowsPerMatch"); + UNIT_ASSERT(IsAtom(GetQuoted(rowsPerMatch), "RowsPerMatch_OneRow")); } - Y_UNIT_TEST(SkipAfterMatch) { - { - const auto stmt = R"( +} +Y_UNIT_TEST(SkipAfterMatch) { + { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -225,13 +224,13 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - auto skipTo = FindMatchRecognizeParam(r.Root, "skipTo"); - UNIT_ASSERT(IsListOfAtoms(GetQuoted(skipTo), {"AfterMatchSkip_NextRow", ""}, GetQuoted)); - } - { - const auto stmt = R"( + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + auto skipTo = FindMatchRecognizeParam(r.Root, "skipTo"); + UNIT_ASSERT(IsListOfAtoms(GetQuoted(skipTo), {"AfterMatchSkip_NextRow", ""}, GetQuoted)); + } + { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -240,13 +239,13 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - auto skipTo = FindMatchRecognizeParam(r.Root, "skipTo"); - UNIT_ASSERT(IsListOfAtoms(GetQuoted(skipTo), {"AfterMatchSkip_PastLastRow", ""}, GetQuoted)); - } - { - const auto stmt = R"( + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + auto skipTo = FindMatchRecognizeParam(r.Root, "skipTo"); + UNIT_ASSERT(IsListOfAtoms(GetQuoted(skipTo), {"AfterMatchSkip_PastLastRow", ""}, GetQuoted)); + } + { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -255,13 +254,13 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - auto skipTo = FindMatchRecognizeParam(r.Root, "skipTo"); - UNIT_ASSERT(IsListOfAtoms(GetQuoted(skipTo), {"AfterMatchSkip_ToFirst", "Y"}, GetQuoted)); - } - { - const auto stmt = R"( + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + auto skipTo = FindMatchRecognizeParam(r.Root, "skipTo"); + UNIT_ASSERT(IsListOfAtoms(GetQuoted(skipTo), {"AfterMatchSkip_ToFirst", "Y"}, GetQuoted)); + } + { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -270,11 +269,11 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(not r.IsOk()); - } - { - const auto stmt = R"( + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(not r.IsOk()); + } + { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -283,13 +282,13 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - auto skipTo = FindMatchRecognizeParam(r.Root, "skipTo"); - UNIT_ASSERT(IsListOfAtoms(GetQuoted(skipTo), {"AfterMatchSkip_ToLast", "Y"}, GetQuoted)); - } - { - const auto stmt = R"( + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + auto skipTo = FindMatchRecognizeParam(r.Root, "skipTo"); + UNIT_ASSERT(IsListOfAtoms(GetQuoted(skipTo), {"AfterMatchSkip_ToLast", "Y"}, GetQuoted)); + } + { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -298,11 +297,11 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(not r.IsOk()); - } - { - const auto stmt = R"( + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(not r.IsOk()); + } + { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -311,13 +310,13 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - auto skipTo = FindMatchRecognizeParam(r.Root, "skipTo"); - UNIT_ASSERT(IsListOfAtoms(GetQuoted(skipTo), {"AfterMatchSkip_To", "Y"}, GetQuoted)); - } - { - const auto stmt = R"( + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + auto skipTo = FindMatchRecognizeParam(r.Root, "skipTo"); + UNIT_ASSERT(IsListOfAtoms(GetQuoted(skipTo), {"AfterMatchSkip_To", "Y"}, GetQuoted)); + } + { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -326,12 +325,12 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(not r.IsOk()); - } + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(not r.IsOk()); } - Y_UNIT_TEST(row_pattern_initial) { - const auto stmt = R"( +} +Y_UNIT_TEST(row_pattern_initial) { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -340,12 +339,12 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(not r.IsOk()); - } + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(not r.IsOk()); +} - Y_UNIT_TEST(row_pattern_seek) { - const auto stmt = R"( +Y_UNIT_TEST(row_pattern_seek) { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -354,12 +353,12 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(not r.IsOk()); - } + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(not r.IsOk()); +} - Y_UNIT_TEST(PatternSimple) { - const auto stmt = R"( +Y_UNIT_TEST(PatternSimple) { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -367,16 +366,16 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - const auto& r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& patternCallable = FindMatchRecognizeParam(r.Root, "pattern"); - UNIT_ASSERT(IsListOfSize(patternCallable, 1 + 1)); - UNIT_ASSERT(IsAtom(patternCallable->GetChild(0), "MatchRecognizePattern")); - UNIT_ASSERT(IsListOfSize(GetQuoted(patternCallable->GetChild(1)), 3)); - } + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& patternCallable = FindMatchRecognizeParam(r.Root, "pattern"); + UNIT_ASSERT(IsListOfSize(patternCallable, 1 + 1)); + UNIT_ASSERT(IsAtom(patternCallable->GetChild(0), "MatchRecognizePattern")); + UNIT_ASSERT(IsListOfSize(GetQuoted(patternCallable->GetChild(1)), 3)); +} - Y_UNIT_TEST(PatternMultiTerm) { - const auto stmt = R"( +Y_UNIT_TEST(PatternMultiTerm) { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -384,16 +383,16 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - const auto& r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& patternCallable = FindMatchRecognizeParam(r.Root, "pattern"); - UNIT_ASSERT(IsListOfSize(patternCallable, 1 + 4)); - UNIT_ASSERT(IsAtom(patternCallable->GetChild(0), "MatchRecognizePattern")); - UNIT_ASSERT(IsListOfSize(GetQuoted(patternCallable->GetChild(4)), 5)); - } + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& patternCallable = FindMatchRecognizeParam(r.Root, "pattern"); + UNIT_ASSERT(IsListOfSize(patternCallable, 1 + 4)); + UNIT_ASSERT(IsAtom(patternCallable->GetChild(0), "MatchRecognizePattern")); + UNIT_ASSERT(IsListOfSize(GetQuoted(patternCallable->GetChild(4)), 5)); +} - Y_UNIT_TEST(PatternWithParanthesis) { - const auto stmt = R"( +Y_UNIT_TEST(PatternWithParanthesis) { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -403,25 +402,25 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - const auto& r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& patternCallable = FindMatchRecognizeParam(r.Root, "pattern"); - UNIT_ASSERT(IsListOfSize(patternCallable, 1 + 2)); - UNIT_ASSERT(IsAtom(patternCallable->GetChild(0), "MatchRecognizePattern")); - const auto& firstTerm = patternCallable->GetChild(1); - UNIT_ASSERT(IsListOfSize(GetQuoted(firstTerm), 1)); - const auto& lastTerm = patternCallable->GetChild(2); - UNIT_ASSERT(IsListOfSize(GetQuoted(lastTerm), 3)); - const auto& firstFactorOfLastTerm = lastTerm->GetChild(1)->GetChild(0); - UNIT_ASSERT(IsListOfSize(GetQuoted(firstFactorOfLastTerm), 6)); - const auto nestedPattern = firstFactorOfLastTerm->GetChild(1)->GetChild(0); - UNIT_ASSERT(IsListOfSize(nestedPattern, 1 + 1)); - UNIT_ASSERT(IsAtom(nestedPattern->GetChild(0), "MatchRecognizePattern")); - UNIT_ASSERT(IsListOfSize(GetQuoted(nestedPattern->GetChild(1)), 2)); - } + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& patternCallable = FindMatchRecognizeParam(r.Root, "pattern"); + UNIT_ASSERT(IsListOfSize(patternCallable, 1 + 2)); + UNIT_ASSERT(IsAtom(patternCallable->GetChild(0), "MatchRecognizePattern")); + const auto& firstTerm = patternCallable->GetChild(1); + UNIT_ASSERT(IsListOfSize(GetQuoted(firstTerm), 1)); + const auto& lastTerm = patternCallable->GetChild(2); + UNIT_ASSERT(IsListOfSize(GetQuoted(lastTerm), 3)); + const auto& firstFactorOfLastTerm = lastTerm->GetChild(1)->GetChild(0); + UNIT_ASSERT(IsListOfSize(GetQuoted(firstFactorOfLastTerm), 6)); + const auto nestedPattern = firstFactorOfLastTerm->GetChild(1)->GetChild(0); + UNIT_ASSERT(IsListOfSize(nestedPattern, 1 + 1)); + UNIT_ASSERT(IsAtom(nestedPattern->GetChild(0), "MatchRecognizePattern")); + UNIT_ASSERT(IsListOfSize(GetQuoted(nestedPattern->GetChild(1)), 2)); +} - Y_UNIT_TEST(PatternManyAlternatives) { - const auto stmt = R"( +Y_UNIT_TEST(PatternManyAlternatives) { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -431,19 +430,21 @@ PATTERN ( DEFINE A as A ) )"; - UNIT_ASSERT(MatchRecognizeSqlToYql(stmt).IsOk()); - } + UNIT_ASSERT(MatchRecognizeSqlToYql(stmt).IsOk()); +} - Y_UNIT_TEST(PatternLimitedNesting) { - constexpr size_t MaxNesting = 20; - for (size_t extraNesting = 0; extraNesting <= 1; ++extraNesting) { - std::string pattern; - for (size_t i = 0; i != MaxNesting + extraNesting; ++i) - pattern.push_back('('); - pattern.push_back('A'); - for (size_t i = 0; i != MaxNesting + extraNesting; ++i) - pattern.push_back(')'); - const auto stmt = TString(R"( +Y_UNIT_TEST(PatternLimitedNesting) { + constexpr size_t MaxNesting = 20; + for (size_t extraNesting = 0; extraNesting <= 1; ++extraNesting) { + std::string pattern; + for (size_t i = 0; i != MaxNesting + extraNesting; ++i) { + pattern.push_back('('); + } + pattern.push_back('A'); + for (size_t i = 0; i != MaxNesting + extraNesting; ++i) { + pattern.push_back(')'); + } + const auto stmt = TString(R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -453,18 +454,18 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - const auto &r = MatchRecognizeSqlToYql(stmt); - if (not extraNesting) { - UNIT_ASSERT(r.IsOk()); - } else { - UNIT_ASSERT(not r.IsOk()); - } + const auto& r = MatchRecognizeSqlToYql(stmt); + if (not extraNesting) { + UNIT_ASSERT(r.IsOk()); + } else { + UNIT_ASSERT(not r.IsOk()); } } +} - Y_UNIT_TEST(PatternFactorQuantifiers) { - auto makeRequest = [](const TString& factor) { - return TString(R"( +Y_UNIT_TEST(PatternFactorQuantifiers) { + auto makeRequest = [](const TString& factor) { + return TString(R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -474,173 +475,173 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; + }; + auto getTheFactor = [](const NYql::TAstNode* root) { + const auto& patternCallable = FindMatchRecognizeParam(root, "pattern"); + const auto& factor = patternCallable->GetChild(1)->GetChild(1)->GetChild(0)->GetChild(1); + return NYql::NMatchRecognize::TRowPatternFactor{ + TString(), // Primary var or subexpression, not used in this test + FromString<uint64_t>(GetAtom(GetQuoted(factor->GetChild(1)))), // QuantityMin + FromString<uint64_t>(GetAtom(GetQuoted(factor->GetChild(2)))), // QuantityMax + FromString<bool>(GetAtom(GetQuoted(factor->GetChild(3)))), // Greedy + FromString<bool>(GetAtom(GetQuoted(factor->GetChild(4)))), // Output, not used in this test + FromString<bool>(GetAtom(GetQuoted(factor->GetChild(5)))), // Flag "Unused", not used in this test }; - auto getTheFactor = [](const NYql::TAstNode* root) { - const auto& patternCallable = FindMatchRecognizeParam(root, "pattern"); - const auto& factor = patternCallable->GetChild(1)->GetChild(1)->GetChild(0)->GetChild(1); - return NYql::NMatchRecognize::TRowPatternFactor{ - TString(), // Primary var or subexpression, not used in this test - FromString<uint64_t>(GetAtom(GetQuoted(factor->GetChild(1)))), // QuantityMin - FromString<uint64_t>(GetAtom(GetQuoted(factor->GetChild(2)))), // QuantityMax - FromString<bool>(GetAtom(GetQuoted(factor->GetChild(3)))), // Greedy - FromString<bool>(GetAtom(GetQuoted(factor->GetChild(4)))), // Output, not used in this test - FromString<bool>(GetAtom(GetQuoted(factor->GetChild(5)))), // Flag "Unused", not used in this test - }; - }; - { - //no quantifiers - const auto stmt = makeRequest("A"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(1, factor.QuantityMin); - UNIT_ASSERT_EQUAL(1, factor.QuantityMax); - UNIT_ASSERT(factor.Greedy); - } - { - //optional greedy(default) - const auto stmt = makeRequest("A?"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(0, factor.QuantityMin); - UNIT_ASSERT_EQUAL(1, factor.QuantityMax); - UNIT_ASSERT(factor.Greedy); - } - { - //optional reluctant - const auto stmt = makeRequest("A??"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(0, factor.QuantityMin); - UNIT_ASSERT_EQUAL(1, factor.QuantityMax); - UNIT_ASSERT(!factor.Greedy); - } - { - //+ greedy(default) - const auto stmt = makeRequest("A+"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(1, factor.QuantityMin); - UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); - UNIT_ASSERT(factor.Greedy); - } - { - //+ reluctant - const auto stmt = makeRequest("A+?"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(1, factor.QuantityMin); - UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); - UNIT_ASSERT(!factor.Greedy); - } - { - //* greedy(default) - const auto stmt = makeRequest("A*"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(0, factor.QuantityMin); - UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); - UNIT_ASSERT(factor.Greedy); - } - { - //* reluctant - const auto stmt = makeRequest("A*?"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(0, factor.QuantityMin); - UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); - UNIT_ASSERT(!factor.Greedy); - } - { - //exact n - const auto stmt = makeRequest("A{4}"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(4, factor.QuantityMin); - UNIT_ASSERT_EQUAL(4, factor.QuantityMax); - } - { - //from n to m greedy(default - const auto stmt = makeRequest("A{4, 7}"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(4, factor.QuantityMin); - UNIT_ASSERT_EQUAL(7, factor.QuantityMax); - UNIT_ASSERT(factor.Greedy); - } - { - //from n to m reluctant - const auto stmt = makeRequest("A{4,7}?"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(4, factor.QuantityMin); - UNIT_ASSERT_EQUAL(7, factor.QuantityMax); - UNIT_ASSERT(!factor.Greedy); - } - { - //at least n greedy(default) - const auto stmt = makeRequest("A{4,}"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(4, factor.QuantityMin); - UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); - UNIT_ASSERT(factor.Greedy); - } - { - //at least n reluctant - const auto stmt = makeRequest("A{4,}?"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(4, factor.QuantityMin); - UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); - UNIT_ASSERT(!factor.Greedy); - } - { - //at most m greedy(default) - const auto stmt = makeRequest("A{,7}"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(0, factor.QuantityMin); - UNIT_ASSERT_EQUAL(7, factor.QuantityMax); - UNIT_ASSERT(factor.Greedy); - } - { - //at least n reluctant - const auto stmt = makeRequest("A{,7}?"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(0, factor.QuantityMin); - UNIT_ASSERT_EQUAL(7, factor.QuantityMax); - UNIT_ASSERT(!factor.Greedy); - } + }; + { + // no quantifiers + const auto stmt = makeRequest("A"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(1, factor.QuantityMin); + UNIT_ASSERT_EQUAL(1, factor.QuantityMax); + UNIT_ASSERT(factor.Greedy); + } + { + // optional greedy(default) + const auto stmt = makeRequest("A?"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(0, factor.QuantityMin); + UNIT_ASSERT_EQUAL(1, factor.QuantityMax); + UNIT_ASSERT(factor.Greedy); + } + { + // optional reluctant + const auto stmt = makeRequest("A??"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(0, factor.QuantityMin); + UNIT_ASSERT_EQUAL(1, factor.QuantityMax); + UNIT_ASSERT(!factor.Greedy); + } + { + //+ greedy(default) + const auto stmt = makeRequest("A+"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(1, factor.QuantityMin); + UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); + UNIT_ASSERT(factor.Greedy); + } + { + //+ reluctant + const auto stmt = makeRequest("A+?"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(1, factor.QuantityMin); + UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); + UNIT_ASSERT(!factor.Greedy); + } + { + //* greedy(default) + const auto stmt = makeRequest("A*"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(0, factor.QuantityMin); + UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); + UNIT_ASSERT(factor.Greedy); + } + { + //* reluctant + const auto stmt = makeRequest("A*?"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(0, factor.QuantityMin); + UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); + UNIT_ASSERT(!factor.Greedy); + } + { + // exact n + const auto stmt = makeRequest("A{4}"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(4, factor.QuantityMin); + UNIT_ASSERT_EQUAL(4, factor.QuantityMax); + } + { + // from n to m greedy(default + const auto stmt = makeRequest("A{4, 7}"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(4, factor.QuantityMin); + UNIT_ASSERT_EQUAL(7, factor.QuantityMax); + UNIT_ASSERT(factor.Greedy); + } + { + // from n to m reluctant + const auto stmt = makeRequest("A{4,7}?"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(4, factor.QuantityMin); + UNIT_ASSERT_EQUAL(7, factor.QuantityMax); + UNIT_ASSERT(!factor.Greedy); + } + { + // at least n greedy(default) + const auto stmt = makeRequest("A{4,}"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(4, factor.QuantityMin); + UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); + UNIT_ASSERT(factor.Greedy); + } + { + // at least n reluctant + const auto stmt = makeRequest("A{4,}?"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(4, factor.QuantityMin); + UNIT_ASSERT_EQUAL(std::numeric_limits<uint64_t>::max(), factor.QuantityMax); + UNIT_ASSERT(!factor.Greedy); + } + { + // at most m greedy(default) + const auto stmt = makeRequest("A{,7}"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(0, factor.QuantityMin); + UNIT_ASSERT_EQUAL(7, factor.QuantityMax); + UNIT_ASSERT(factor.Greedy); + } + { + // at least n reluctant + const auto stmt = makeRequest("A{,7}?"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(0, factor.QuantityMin); + UNIT_ASSERT_EQUAL(7, factor.QuantityMax); + UNIT_ASSERT(!factor.Greedy); + } - { - //quantifiers on subexpression - const auto stmt = makeRequest("(A B+ C | D | ^){4,7}?"); - const auto &r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto& factor = getTheFactor(r.Root); - UNIT_ASSERT_EQUAL(4, factor.QuantityMin); - UNIT_ASSERT_EQUAL(7, factor.QuantityMax); - UNIT_ASSERT(!factor.Greedy); - } + { + // quantifiers on subexpression + const auto stmt = makeRequest("(A B+ C | D | ^){4,7}?"); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto& factor = getTheFactor(r.Root); + UNIT_ASSERT_EQUAL(4, factor.QuantityMin); + UNIT_ASSERT_EQUAL(7, factor.QuantityMax); + UNIT_ASSERT(!factor.Greedy); } +} - Y_UNIT_TEST(Permute) { - const auto stmt = R"( +Y_UNIT_TEST(Permute) { + const auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -650,50 +651,48 @@ FROM Input MATCH_RECOGNIZE( DEFINE A as A ) )"; - const auto& r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); + const auto& r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); - const auto& patternCallable = FindMatchRecognizeParam(r.Root, "pattern"); - const auto permutePattern = patternCallable->GetChild(1)->GetChild(1)->GetChild(0)->GetChild(1)->GetChild(0); - UNIT_ASSERT(IsListOfSize(permutePattern, 1 + 120)); //CallableName + 5! - } + const auto& patternCallable = FindMatchRecognizeParam(r.Root, "pattern"); + const auto permutePattern = patternCallable->GetChild(1)->GetChild(1)->GetChild(0)->GetChild(1)->GetChild(0); + UNIT_ASSERT(IsListOfSize(permutePattern, 1 + 120)); // CallableName + 5! +} - Y_UNIT_TEST(PermuteTooMuch) { - for (size_t n = 1; n <= 6 + 1; ++n) { - std::vector<std::string> vars(n); - std::generate(begin(vars), end(vars), [n = 0] () mutable { return "A" + std::to_string(n++);}); - const auto stmt = TString(R"( +Y_UNIT_TEST(PermuteTooMuch) { + for (size_t n = 1; n <= 6 + 1; ++n) { + std::vector<std::string> vars(n); + std::generate(begin(vars), end(vars), [n = 0]() mutable { return "A" + std::to_string(n++); }); + const auto stmt = TString(R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( PATTERN ( PERMUTE( )" + std::accumulate(cbegin(vars) + 1, cend(vars), vars.front(), - [](const std::string& acc, const std::string& v) { - return acc + ", " + v; - }) + - R"( + [](const std::string& acc, const std::string& v) { + return acc + ", " + v; + }) + + R"( ) ) DEFINE A0 as A0 ) -)" - ); - const auto &r = MatchRecognizeSqlToYql(stmt); - if (n <= 6) { - UNIT_ASSERT(r.IsOk()); - } else { - UNIT_ASSERT(!r.IsOk()); - } +)"); + const auto& r = MatchRecognizeSqlToYql(stmt); + if (n <= 6) { + UNIT_ASSERT(r.IsOk()); + } else { + UNIT_ASSERT(!r.IsOk()); } } +} +Y_UNIT_TEST(row_pattern_subset_clause) { + // TODO https://st.yandex-team.ru/YQL-16186 +} - Y_UNIT_TEST(row_pattern_subset_clause) { - //TODO https://st.yandex-team.ru/YQL-16186 - } - - Y_UNIT_TEST(Defines) { - auto stmt = R"( +Y_UNIT_TEST(Defines) { + auto stmt = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -704,34 +703,34 @@ FROM Input MATCH_RECOGNIZE( L as L.V = LAST(Q.T) ) )"; - auto r = MatchRecognizeSqlToYql(stmt); - UNIT_ASSERT(r.IsOk()); - const auto defines = FindMatchRecognizeParam(r.Root, "define"); - UNIT_ASSERT(IsListOfSize(defines, 7)); - const auto varNames = defines->GetChild(3); - UNIT_ASSERT(IsListOfAtoms(GetQuoted(varNames), {"Y", "Q", "L"}, GetQuoted)); - - UNIT_ASSERT(IsLambda(defines->GetChild(4), 3)); - UNIT_ASSERT(IsLambda(defines->GetChild(5), 3)); - UNIT_ASSERT(IsLambda(defines->GetChild(6), 3)); - } + auto r = MatchRecognizeSqlToYql(stmt); + UNIT_ASSERT(r.IsOk()); + const auto defines = FindMatchRecognizeParam(r.Root, "define"); + UNIT_ASSERT(IsListOfSize(defines, 7)); + const auto varNames = defines->GetChild(3); + UNIT_ASSERT(IsListOfAtoms(GetQuoted(varNames), {"Y", "Q", "L"}, GetQuoted)); + + UNIT_ASSERT(IsLambda(defines->GetChild(4), 3)); + UNIT_ASSERT(IsLambda(defines->GetChild(5), 3)); + UNIT_ASSERT(IsLambda(defines->GetChild(6), 3)); +} - Y_UNIT_TEST(AbsentRowPatternVariableInDefines) { - auto getStatement = [](const TString &var) { - return TStringBuilder() << R"( +Y_UNIT_TEST(AbsentRowPatternVariableInDefines) { + auto getStatement = [](const TString& var) { + return TStringBuilder() << R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( PATTERN ( Q ) DEFINE )" << var << " AS TRUE )"; - }; - UNIT_ASSERT(MatchRecognizeSqlToYql(getStatement("Q")).IsOk()); - UNIT_ASSERT(!MatchRecognizeSqlToYql(getStatement("Y")).IsOk()); - } + }; + UNIT_ASSERT(MatchRecognizeSqlToYql(getStatement("Q")).IsOk()); + UNIT_ASSERT(!MatchRecognizeSqlToYql(getStatement("Y")).IsOk()); +} - Y_UNIT_TEST(CheckRequiredNavigationFunction) { - TString stmtPrefix = R"( +Y_UNIT_TEST(CheckRequiredNavigationFunction) { + TString stmtPrefix = R"( USE plato; SELECT * FROM Input MATCH_RECOGNIZE( @@ -739,9 +738,9 @@ FROM Input MATCH_RECOGNIZE( DEFINE L as L.V = )"; - //Be aware that right parenthesis is added at the end of the query as required - UNIT_ASSERT(MatchRecognizeSqlToYql(stmtPrefix + "LAST(Q.dt) )").IsOk()); - UNIT_ASSERT(!MatchRecognizeSqlToYql(stmtPrefix + "Q.dt )").IsOk()); - } - + // Be aware that right parenthesis is added at the end of the query as required + UNIT_ASSERT(MatchRecognizeSqlToYql(stmtPrefix + "LAST(Q.dt) )").IsOk()); + UNIT_ASSERT(!MatchRecognizeSqlToYql(stmtPrefix + "Q.dt )").IsOk()); } + +} // Y_UNIT_TEST_SUITE(MatchRecognize) diff --git a/yql/essentials/sql/v1/sql_query.cpp b/yql/essentials/sql/v1/sql_query.cpp index 3f31663f8b1..bb846e93012 100644 --- a/yql/essentials/sql/v1/sql_query.cpp +++ b/yql/essentials/sql/v1/sql_query.cpp @@ -11,7 +11,7 @@ #include <util/generic/scope.h> #include <util/string/join.h> #ifdef GetMessage -#undef GetMessage + #undef GetMessage #endif namespace NSQLTranslationV1 { @@ -23,7 +23,7 @@ using namespace NSQLv1Generated; void FillTargetList(TTranslation& ctx, const TRule_set_target_list& node, TVector<TString>& targetList) { targetList.push_back(ColumnNameAsSingleStr(ctx, node.GetRule_set_target2().GetRule_column_name1())); - for (auto& block: node.GetBlock3()) { + for (auto& block : node.GetBlock3()) { targetList.push_back(ColumnNameAsSingleStr(ctx, block.GetRule_set_target2().GetRule_column_name1())); } } @@ -45,7 +45,7 @@ void TSqlQuery::AddStatementToBlocks(TVector<TNodePtr>& blocks, TNodePtr node) { } static bool AsyncReplicationSettingsEntry(std::map<TString, TNodePtr>& out, - const TRule_replication_settings_entry& in, TSqlExpression& ctx, bool create) + const TRule_replication_settings_entry& in, TSqlExpression& ctx, bool create) { auto key = IdEx(in.GetRule_an_id1(), ctx); auto value = ctx.Build(in.GetRule_expr3()); @@ -117,7 +117,7 @@ static bool AsyncReplicationSettingsEntry(std::map<TString, TNodePtr>& out, } static bool AsyncReplicationSettings(std::map<TString, TNodePtr>& out, - const TRule_replication_settings& in, TSqlExpression& ctx, bool create) + const TRule_replication_settings& in, TSqlExpression& ctx, bool create) { if (!AsyncReplicationSettingsEntry(out, in.GetRule_replication_settings_entry1(), ctx, create)) { return false; @@ -133,7 +133,7 @@ static bool AsyncReplicationSettings(std::map<TString, TNodePtr>& out, } static bool AsyncReplicationTarget(std::vector<std::pair<TString, TString>>& out, TStringBuf prefixPath, - const TRule_replication_target& in, TTranslation& ctx) + const TRule_replication_target& in, TTranslation& ctx) { const TString remote = Id(in.GetRule_object_ref1().GetRule_id_or_at2(), ctx).second; const TString local = Id(in.GetRule_object_ref3().GetRule_id_or_at2(), ctx).second; @@ -142,14 +142,14 @@ static bool AsyncReplicationTarget(std::vector<std::pair<TString, TString>>& out } static bool AsyncReplicationAlterAction(std::map<TString, TNodePtr>& settings, - const TRule_alter_replication_action& in, TSqlExpression& ctx) + const TRule_alter_replication_action& in, TSqlExpression& ctx) { // TODO(ilnaz): support other actions return AsyncReplicationSettings(settings, in.GetRule_alter_replication_set_setting1().GetRule_replication_settings3(), ctx, false); } static bool TransferSettingsEntry(std::map<TString, TNodePtr>& out, - const TRule_transfer_settings_entry& in, TSqlExpression& ctx, bool create) + const TRule_transfer_settings_entry& in, TSqlExpression& ctx, bool create) { auto key = IdEx(in.GetRule_an_id1(), ctx); auto value = ctx.Build(in.GetRule_expr3()); @@ -211,7 +211,7 @@ static bool TransferSettingsEntry(std::map<TString, TNodePtr>& out, } static bool TransferSettings(std::map<TString, TNodePtr>& out, - const TRule_transfer_settings& in, TSqlExpression& ctx, bool create) + const TRule_transfer_settings& in, TSqlExpression& ctx, bool create) { if (!TransferSettingsEntry(out, in.GetRule_transfer_settings_entry1(), ctx, create)) { return false; @@ -232,14 +232,14 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& ParseStatementName(core, internalStatementName, humanStatementName); const auto& altCase = core.Alt_case(); if (Mode_ == NSQLTranslation::ESqlMode::LIMITED_VIEW && (altCase >= TRule_sql_stmt_core::kAltSqlStmtCore4 && - altCase != TRule_sql_stmt_core::kAltSqlStmtCore13 && altCase != TRule_sql_stmt_core::kAltSqlStmtCore18)) { + altCase != TRule_sql_stmt_core::kAltSqlStmtCore13 && altCase != TRule_sql_stmt_core::kAltSqlStmtCore18)) { Error() << humanStatementName << " statement is not supported in limited views"; return false; } if (Mode_ == NSQLTranslation::ESqlMode::SUBQUERY && (altCase >= TRule_sql_stmt_core::kAltSqlStmtCore4 && - altCase != TRule_sql_stmt_core::kAltSqlStmtCore13 && altCase != TRule_sql_stmt_core::kAltSqlStmtCore6 && - altCase != TRule_sql_stmt_core::kAltSqlStmtCore18)) { + altCase != TRule_sql_stmt_core::kAltSqlStmtCore13 && altCase != TRule_sql_stmt_core::kAltSqlStmtCore6 && + altCase != TRule_sql_stmt_core::kAltSqlStmtCore18)) { Error() << humanStatementName << " statement is not supported in subqueries"; return false; } @@ -274,8 +274,8 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& return false; } blocks.emplace_back(BuildSelectResult(pos, std::move(source), - Mode_ != NSQLTranslation::ESqlMode::LIMITED_VIEW && Mode_ != NSQLTranslation::ESqlMode::SUBQUERY, Mode_ == NSQLTranslation::ESqlMode::SUBQUERY, - Ctx_.Scoped)); + Mode_ != NSQLTranslation::ESqlMode::LIMITED_VIEW && Mode_ != NSQLTranslation::ESqlMode::SUBQUERY, Mode_ == NSQLTranslation::ESqlMode::SUBQUERY, + Ctx_.Scoped)); break; } case TRule_sql_stmt_core::kAltSqlStmtCore3: { @@ -295,7 +295,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& const auto alias = Ctx_.MakeName("subquerynode"); const auto ref = Ctx_.MakeName("subquery"); blocks.push_back(BuildSubquery(subquery, alias, - Mode_ == NSQLTranslation::ESqlMode::SUBQUERY, names.size() == 1 ? -1 : names.size(), Ctx_.Scoped)); + Mode_ == NSQLTranslation::ESqlMode::SUBQUERY, names.size() == 1 ? -1 : names.size(), Ctx_.Scoped)); blocks.back()->SetLabel(ref); for (size_t i = 0; i < names.size(); ++i) { @@ -337,8 +337,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& replaceIfExists = true; Y_DEBUG_ABORT_UNLESS( (IS_TOKEN(Ctx_.Settings.Antlr4Parser, rule.GetBlock2().GetToken1().GetId(), OR) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, rule.GetBlock2().GetToken2().GetId(), REPLACE)) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, rule.GetBlock2().GetToken2().GetId(), REPLACE))); } const bool isCreateTableAs = rule.HasBlock15(); @@ -346,8 +345,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& ETableType tableType = ETableType::Table; bool temporary = false; if (block.HasAlt2() && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, block.GetAlt2().GetToken1().GetId(), TABLESTORE) - ) { + IS_TOKEN(Ctx_.Settings.Antlr4Parser, block.GetAlt2().GetToken1().GetId(), TABLESTORE)) { tableType = ETableType::TableStore; if (isCreateTableAs) { Context().Error(GetPos(block.GetAlt2().GetToken1())) @@ -355,8 +353,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& return false; } } else if (block.HasAlt3() && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, block.GetAlt3().GetToken1().GetId(), EXTERNAL) - ) { + IS_TOKEN(Ctx_.Settings.Antlr4Parser, block.GetAlt3().GetToken1().GetId(), EXTERNAL)) { tableType = ETableType::ExternalTable; if (isCreateTableAs) { Context().Error(GetPos(block.GetAlt3().GetToken1())) @@ -374,8 +371,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, rule.GetBlock4().GetToken1().GetId(), IF) && IS_TOKEN(Ctx_.Settings.Antlr4Parser, rule.GetBlock4().GetToken2().GetId(), NOT) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, rule.GetBlock4().GetToken3().GetId(), EXISTS) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, rule.GetBlock4().GetToken3().GetId(), EXISTS)); } if (replaceIfExists && tableType != ETableType::ExternalTable) { @@ -389,11 +385,11 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& return false; } - TCreateTableParameters params{.TableType=tableType, .Temporary=temporary}; + TCreateTableParameters params{.TableType = tableType, .Temporary = temporary}; if (!CreateTableEntry(rule.GetRule_create_table_entry7(), params, isCreateTableAs)) { return false; } - for (auto& block: rule.GetBlock8()) { + for (auto& block : rule.GetBlock8()) { if (!CreateTableEntry(block.GetRule_create_table_entry2(), params, isCreateTableAs)) { return false; } @@ -462,8 +458,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& missingOk = true; Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, rule.GetBlock3().GetToken1().GetId(), IF) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, rule.GetBlock3().GetToken2().GetId(), EXISTS) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, rule.GetBlock3().GetToken2().GetId(), EXISTS)); } TTableRef tr; @@ -665,8 +660,8 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& return false; } blocks.emplace_back(BuildSelectResult(pos, std::move(source), - Mode_ != NSQLTranslation::ESqlMode::LIMITED_VIEW && Mode_ != NSQLTranslation::ESqlMode::SUBQUERY, Mode_ == NSQLTranslation::ESqlMode::SUBQUERY, - Ctx_.Scoped)); + Mode_ != NSQLTranslation::ESqlMode::LIMITED_VIEW && Mode_ != NSQLTranslation::ESqlMode::SUBQUERY, Mode_ == NSQLTranslation::ESqlMode::SUBQUERY, + Ctx_.Scoped)); break; } case TRule_sql_stmt_core::kAltSqlStmtCore22: { @@ -890,8 +885,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& missingOk = true; Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken1().GetId(), IF) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken2().GetId(), EXISTS) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken2().GetId(), EXISTS)); } TVector<TDeferredAtom> roles; @@ -917,7 +911,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref4().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref4().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -928,8 +922,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken1().GetId(), IF) && IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken2().GetId(), NOT) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken3().GetId(), EXISTS) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken3().GetId(), EXISTS)); } const TString& objectId = Id(node.GetRule_object_ref4().GetRule_id_or_at2(), *this).second; @@ -950,7 +943,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref3().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -971,7 +964,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref4().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref4().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -981,8 +974,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& missingOk = true; Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken1().GetId(), IF) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken2().GetId(), EXISTS) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken2().GetId(), EXISTS)); } const TString& objectId = Id(node.GetRule_object_ref4().GetRule_id_or_at2(), *this).second; @@ -1003,7 +995,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref7().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref7().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1013,8 +1005,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& replaceIfExists = true; Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock2().GetToken1().GetId(), OR) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock2().GetToken2().GetId(), REPLACE) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock2().GetToken2().GetId(), REPLACE)); } bool existingOk = false; @@ -1023,8 +1014,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock6().GetToken1().GetId(), IF) && IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock6().GetToken2().GetId(), NOT) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock6().GetToken3().GetId(), EXISTS) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock6().GetToken3().GetId(), EXISTS)); } const TString& objectId = Id(node.GetRule_object_ref7().GetRule_id_or_at2(), *this).second; @@ -1043,7 +1033,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref5().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref5().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1070,7 +1060,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref6().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref6().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1080,8 +1070,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& missingOk = true; Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock5().GetToken1().GetId(), IF) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock5().GetToken2().GetId(), EXISTS) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock5().GetToken2().GetId(), EXISTS)); } const TString& objectId = Id(node.GetRule_object_ref6().GetRule_id_or_at2(), *this).second; @@ -1119,7 +1108,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& const TString id = Id(node.GetRule_object_ref4().GetRule_id_or_at2(), *this).second; AddStatementToBlocks(blocks, BuildCreateAsyncReplication(Ctx_.Pos(), BuildTablePath(prefixPath, id), - std::move(targets), std::move(settings), context)); + std::move(targets), std::move(settings), context)); break; } case TRule_sql_stmt_core::kAltSqlStmtCore34: { @@ -1135,8 +1124,8 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& const TString id = Id(node.GetRule_object_ref4().GetRule_id_or_at2(), *this).second; AddStatementToBlocks(blocks, BuildDropAsyncReplication(Ctx_.Pos(), - BuildTablePath(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster), id), - node.HasBlock5(), context)); + BuildTablePath(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster), id), + node.HasBlock5(), context)); break; } case TRule_sql_stmt_core::kAltSqlStmtCore35: { @@ -1154,7 +1143,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TCreateTopicParameters params; params.ExistingOk = existingOk; - if (rule.HasBlock5()) { //create_topic_entry (consumers) + if (rule.HasBlock5()) { // create_topic_entry (consumers) auto& entries = rule.GetBlock5().GetRule_create_topic_entries1(); auto& firstEntry = entries.GetRule_create_topic_entry2(); if (!CreateTopicEntry(firstEntry, params)) { @@ -1166,7 +1155,6 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& return false; } } - } if (rule.HasBlock6()) { // with_topic_settings auto& topic_settings_node = rule.GetBlock6().GetRule_with_topic_settings1().GetRule_topic_settings3(); @@ -1177,8 +1165,8 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& break; } case TRule_sql_stmt_core::kAltSqlStmtCore36: { -// alter_topic_stmt: ALTER TOPIC topic_ref alter_topic_action (COMMA alter_topic_action)*; -// alter_topic_stmt: ALTER TOPIC IF EXISTS topic_ref alter_topic_action (COMMA alter_topic_action)*; + // alter_topic_stmt: ALTER TOPIC topic_ref alter_topic_action (COMMA alter_topic_action)*; + // alter_topic_stmt: ALTER TOPIC IF EXISTS topic_ref alter_topic_action (COMMA alter_topic_action)*; Ctx_.BodyPart(); auto& rule = core.GetAlt_sql_stmt_core36().GetRule_alter_topic_stmt1(); @@ -1268,8 +1256,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& AddStatementToBlocks(blocks, BuildGrantPermissions(pos, service, cluster, permissions, schemaPaths, roleNames, Ctx_.Scoped)); break; } - case TRule_sql_stmt_core::kAltSqlStmtCore39: - { + case TRule_sql_stmt_core::kAltSqlStmtCore39: { // REVOKE (GRANT OPTION FOR)? permission_name_target ON an_id_schema (COMMA an_id_schema)* FROM role_name (COMMA role_name)*; Ctx_.BodyPart(); auto& node = core.GetAlt_sql_stmt_core39().GetRule_revoke_permissions_stmt1(); @@ -1311,15 +1298,14 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& AddStatementToBlocks(blocks, BuildRevokePermissions(pos, service, cluster, permissions, schemaPaths, roleNames, Ctx_.Scoped)); break; } - case TRule_sql_stmt_core::kAltSqlStmtCore40: - { + case TRule_sql_stmt_core::kAltSqlStmtCore40: { // ALTER TABLESTORE object_ref alter_table_store_action (COMMA alter_table_store_action)*; auto& node = core.GetAlt_sql_stmt_core40().GetRule_alter_table_store_stmt1(); TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref3().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1334,14 +1320,13 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& AddStatementToBlocks(blocks, BuildAlterObjectOperation(Ctx_.Pos(), objectId, typeId, false, std::move(kv), std::set<TString>(), context)); break; } - case TRule_sql_stmt_core::kAltSqlStmtCore41: - { + case TRule_sql_stmt_core::kAltSqlStmtCore41: { // create_object_stmt: UPSERT OBJECT name (TYPE type [WITH k=v,...]); auto& node = core.GetAlt_sql_stmt_core41().GetRule_upsert_object_stmt1(); TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref3().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1445,8 +1430,8 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& const TString id = Id(node.GetRule_object_ref4().GetRule_id_or_at2(), *this).second; AddStatementToBlocks(blocks, BuildAlterAsyncReplication(Ctx_.Pos(), - BuildTablePath(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster), id), - std::move(settings), context)); + BuildTablePath(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster), id), + std::move(settings), context)); break; } case TRule_sql_stmt_core::kAltSqlStmtCore45: { @@ -1455,7 +1440,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref4().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref4().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1476,7 +1461,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref4().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref4().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1503,7 +1488,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref4().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref4().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1527,26 +1512,26 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& std::map<TString, TDeferredAtom> kv; if (!ParseBackupCollectionSettings(kv, node.GetRule_backup_collection_settings6())) { - return false; + return false; } bool database = false; TVector<TDeferredAtom> tables; if (node.HasBlock3()) { - database = node.GetBlock3().GetRule_create_backup_collection_entries1().has_alt_create_backup_collection_entries1(); - if (node.GetBlock3().GetRule_create_backup_collection_entries1().has_alt_create_backup_collection_entries2()) { - if (!ParseBackupCollectionTables( - tables, - node - .GetBlock3() - .GetRule_create_backup_collection_entries1() - .alt_create_backup_collection_entries2() - .GetRule_create_backup_collection_entries_many1() - .GetRule_table_list2())) - { - return false; - } - } + database = node.GetBlock3().GetRule_create_backup_collection_entries1().has_alt_create_backup_collection_entries1(); + if (node.GetBlock3().GetRule_create_backup_collection_entries1().has_alt_create_backup_collection_entries2()) { + if (!ParseBackupCollectionTables( + tables, + node + .GetBlock3() + .GetRule_create_backup_collection_entries1() + .alt_create_backup_collection_entries2() + .GetRule_create_backup_collection_entries_many1() + .GetRule_table_list2())) + { + return false; + } + } } const TString& objectId = Id(node.GetRule_backup_collection2().GetRule_object_ref3().GetRule_id_or_at2(), *this).second; @@ -1554,11 +1539,11 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& BuildCreateBackupCollection(Ctx_.Pos(), TString(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster)), objectId, - TCreateBackupCollectionParameters { - .Settings = std::move(kv), - .Database = database, - .Tables = tables, - .ExistingOk = false, + TCreateBackupCollectionParameters{ + .Settings = std::move(kv), + .Database = database, + .Tables = tables, + .ExistingOk = false, }, context)); break; @@ -1585,39 +1570,37 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TVector<TDeferredAtom> removeTables; switch (node.GetBlock3().Alt_case()) { - case TRule_alter_backup_collection_stmt_TBlock3::kAlt1: { - if (!ParseBackupCollectionSettings(kv, toReset, node.GetBlock3().GetAlt1().GetRule_alter_backup_collection_actions1())) { - return false; + case TRule_alter_backup_collection_stmt_TBlock3::kAlt1: { + if (!ParseBackupCollectionSettings(kv, toReset, node.GetBlock3().GetAlt1().GetRule_alter_backup_collection_actions1())) { + return false; + } + break; } - break; - } - case TRule_alter_backup_collection_stmt_TBlock3::kAlt2: { - if (!ParseBackupCollectionEntries( - addDatabase, - dropDatabase, - addTables, - removeTables, - node.GetBlock3().GetAlt2().GetRule_alter_backup_collection_entries1())) - { - return false; + case TRule_alter_backup_collection_stmt_TBlock3::kAlt2: { + if (!ParseBackupCollectionEntries( + addDatabase, + dropDatabase, + addTables, + removeTables, + node.GetBlock3().GetAlt2().GetRule_alter_backup_collection_entries1())) + { + return false; + } + break; } - break; - } - case TRule_alter_backup_collection_stmt_TBlock3::ALT_NOT_SET: {} // do nothing + case TRule_alter_backup_collection_stmt_TBlock3::ALT_NOT_SET: { + } // do nothing } - auto database = addDatabase ? - TAlterBackupCollectionParameters::EDatabase::Add : - dropDatabase ? - TAlterBackupCollectionParameters::EDatabase::Drop : - TAlterBackupCollectionParameters::EDatabase::Unchanged; + auto database = addDatabase ? TAlterBackupCollectionParameters::EDatabase::Add : dropDatabase ? TAlterBackupCollectionParameters::EDatabase::Drop + : TAlterBackupCollectionParameters::EDatabase::Unchanged; const TString& objectId = Id(node.GetRule_backup_collection2().GetRule_object_ref3().GetRule_id_or_at2(), *this).second; AddStatementToBlocks(blocks, BuildAlterBackupCollection(Ctx_.Pos(), TString(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster)), objectId, - TAlterBackupCollectionParameters { + TAlterBackupCollectionParameters{ .Settings = std::move(kv), .SettingsToReset = std::move(toReset), .Database = database, @@ -1646,7 +1629,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& BuildDropBackupCollection(Ctx_.Pos(), TString(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster)), objectId, - TDropBackupCollectionParameters { + TDropBackupCollectionParameters{ .MissingOk = false, }, context)); @@ -1670,7 +1653,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& if (columnsNode.HasRule_column_name1()) { columns.push_back(Id(columnsNode.GetRule_column_name1().GetRule_an_id2(), *this)); - for (const auto& columnNode: columnsNode.GetBlock2()) { + for (const auto& columnNode : columnsNode.GetBlock2()) { columns.push_back(Id(columnNode.GetRule_column_name2().GetRule_an_id2(), *this)); } } @@ -1691,7 +1674,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref5().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref5().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1712,7 +1695,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref5().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref5().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1739,7 +1722,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref5().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref5().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1754,7 +1737,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref2().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref2().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1779,7 +1762,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref2().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref2().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1824,7 +1807,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& if (node.GetRule_object_ref4().HasBlock1()) { if (!ClusterExpr(node.GetRule_object_ref4().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster)) { + false, context.ServiceId, context.Cluster)) { return false; } } @@ -1837,8 +1820,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& params.MissingOk = true; Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken1().GetId(), IF) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken2().GetId(), EXISTS) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock3().GetToken2().GetId(), EXISTS)); } for (const auto& block : node.GetBlock5()) { @@ -1850,7 +1832,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& AddStatementToBlocks(blocks, BuildAlterSequence(pos, service, cluster, id, params, Ctx_.Scoped)); break; } - case TRule_sql_stmt_core::kAltSqlStmtCore58: { + case TRule_sql_stmt_core::kAltSqlStmtCore58: { // create_transfer_stmt: CREATE TRANSFER auto& node = core.GetAlt_sql_stmt_core58().GetRule_create_transfer_stmt1(); @@ -1879,7 +1861,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& } AddStatementToBlocks(blocks, BuildCreateTransfer(Ctx_.Pos(), BuildTablePath(prefixPath, id), - std::move(source), std::move(target), std::move(transformLambda), std::move(settings), context)); + std::move(source), std::move(target), std::move(transformLambda), std::move(settings), context)); break; } case TRule_sql_stmt_core::kAltSqlStmtCore59: { @@ -1924,8 +1906,8 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& const TString id = Id(node.GetRule_object_ref3().GetRule_id_or_at2(), *this).second; AddStatementToBlocks(blocks, BuildAlterTransfer(Ctx_.Pos(), - BuildTablePath(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster), id), - std::move(transformLambda), std::move(settings), context)); + BuildTablePath(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster), id), + std::move(transformLambda), std::move(settings), context)); break; } case TRule_sql_stmt_core::kAltSqlStmtCore60: { @@ -1941,8 +1923,8 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& const TString id = Id(node.GetRule_object_ref3().GetRule_id_or_at2(), *this).second; AddStatementToBlocks(blocks, BuildDropTransfer(Ctx_.Pos(), - BuildTablePath(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster), id), - node.HasBlock4(), context)); + BuildTablePath(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster), id), + node.HasBlock4(), context)); break; } case TRule_sql_stmt_core::kAltSqlStmtCore61: { @@ -2029,8 +2011,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& if (replaceIfExists) { Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock2().GetToken1().GetId(), OR) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock2().GetToken2().GetId(), REPLACE) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock2().GetToken2().GetId(), REPLACE)); } // IF NOT EXISTS @@ -2039,8 +2020,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock5().GetToken1().GetId(), IF) && IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock5().GetToken2().GetId(), NOT) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock5().GetToken3().GetId(), EXISTS) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock5().GetToken3().GetId(), EXISTS)); } // WITH streaming_query_settings @@ -2080,8 +2060,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& if (missingOk) { Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock4().GetToken1().GetId(), IF) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock4().GetToken2().GetId(), EXISTS) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock4().GetToken2().GetId(), EXISTS)); } // alter_streaming_query_action @@ -2110,8 +2089,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& if (missingOk) { Y_DEBUG_ABORT_UNLESS( IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock4().GetToken1().GetId(), IF) && - IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock4().GetToken2().GetId(), EXISTS) - ); + IS_TOKEN(Ctx_.Settings.Antlr4Parser, node.GetBlock4().GetToken2().GetId(), EXISTS)); } AddStatementToBlocks(blocks, BuildDropObjectOperation(Ctx_.Pos(), *objectPath, "STREAMING_QUERY", missingOk, {}, context)); @@ -2126,9 +2104,8 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref3().HasBlock1()) { if (!ClusterExpr( - node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster - )) { + node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(), + false, context.ServiceId, context.Cluster)) { return false; } } @@ -2154,8 +2131,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& BuildTablePath(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster), objectId), secretParams, context, - Ctx_.Scoped) - ); + Ctx_.Scoped)); break; } case TRule_sql_stmt_core::kAltSqlStmtCore67: { @@ -2167,9 +2143,8 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref3().HasBlock1()) { if (!ClusterExpr( - node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster - )) { + node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(), + false, context.ServiceId, context.Cluster)) { return false; } } @@ -2195,8 +2170,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& BuildTablePath(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster), objectId), secretParams, context, - Ctx_.Scoped) - ); + Ctx_.Scoped)); break; } case TRule_sql_stmt_core::kAltSqlStmtCore68: { @@ -2208,9 +2182,8 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& TObjectOperatorContext context(Ctx_.Scoped); if (node.GetRule_object_ref3().HasBlock1()) { if (!ClusterExpr( - node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(), - false, context.ServiceId, context.Cluster - )) { + node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(), + false, context.ServiceId, context.Cluster)) { return false; } } @@ -2226,8 +2199,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& Ctx_.Pos(), BuildTablePath(Ctx_.GetPrefixPath(context.ServiceId, context.Cluster), objectId), context, - Ctx_.Scoped) - ); + Ctx_.Scoped)); break; } case TRule_sql_stmt_core::ALT_NOT_SET: @@ -2279,8 +2251,8 @@ bool TSqlQuery::DeclareStatement(const TRule_declare_stmt& stmt) { if (Ctx_.IsAlreadyDeclared(varName)) { if (!Ctx_.Warning(varPos, TIssuesIds::YQL_DUPLICATE_DECLARE, [&](auto& out) { - out << "Duplicate declaration of '" << varName << "' will be ignored"; - })) { + out << "Duplicate declaration of '" << varName << "' will be ignored"; + })) { return false; } } else { @@ -2317,164 +2289,163 @@ bool TSqlQuery::AlterTableAction(const TRule_alter_table_action& node, TAlterTab } switch (node.Alt_case()) { - case TRule_alter_table_action::kAltAlterTableAction1: { - // ADD COLUMN - const auto& addRule = node.GetAlt_alter_table_action1().GetRule_alter_table_add_column1(); - if (!AlterTableAddColumn(addRule, params)) { - return false; + case TRule_alter_table_action::kAltAlterTableAction1: { + // ADD COLUMN + const auto& addRule = node.GetAlt_alter_table_action1().GetRule_alter_table_add_column1(); + if (!AlterTableAddColumn(addRule, params)) { + return false; + } + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction2: { - // DROP COLUMN - const auto& dropRule = node.GetAlt_alter_table_action2().GetRule_alter_table_drop_column1(); - if (!AlterTableDropColumn(dropRule, params)) { - return false; + case TRule_alter_table_action::kAltAlterTableAction2: { + // DROP COLUMN + const auto& dropRule = node.GetAlt_alter_table_action2().GetRule_alter_table_drop_column1(); + if (!AlterTableDropColumn(dropRule, params)) { + return false; + } + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction3: { - // ALTER COLUMN - const auto& alterRule = node.GetAlt_alter_table_action3().GetRule_alter_table_alter_column1(); - if (!AlterTableAlterColumn(alterRule, params)) { - return false; + case TRule_alter_table_action::kAltAlterTableAction3: { + // ALTER COLUMN + const auto& alterRule = node.GetAlt_alter_table_action3().GetRule_alter_table_alter_column1(); + if (!AlterTableAlterColumn(alterRule, params)) { + return false; + } + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction4: { - // ADD FAMILY - const auto& familyEntry = node.GetAlt_alter_table_action4().GetRule_alter_table_add_column_family1() - .GetRule_family_entry2(); - if (!AlterTableAddFamily(familyEntry, params)) { - return false; + case TRule_alter_table_action::kAltAlterTableAction4: { + // ADD FAMILY + const auto& familyEntry = node.GetAlt_alter_table_action4().GetRule_alter_table_add_column_family1().GetRule_family_entry2(); + if (!AlterTableAddFamily(familyEntry, params)) { + return false; + } + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction5: { - // ALTER FAMILY - const auto& alterRule = node.GetAlt_alter_table_action5().GetRule_alter_table_alter_column_family1(); - if (!AlterTableAlterFamily(alterRule, params)) { - return false; + case TRule_alter_table_action::kAltAlterTableAction5: { + // ALTER FAMILY + const auto& alterRule = node.GetAlt_alter_table_action5().GetRule_alter_table_alter_column_family1(); + if (!AlterTableAlterFamily(alterRule, params)) { + return false; + } + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction6: { - // SET (uncompat) - const auto& setRule = node.GetAlt_alter_table_action6().GetRule_alter_table_set_table_setting_uncompat1(); - if (!AlterTableSetTableSetting(setRule, params.TableSettings, params.TableType)) { - return false; + case TRule_alter_table_action::kAltAlterTableAction6: { + // SET (uncompat) + const auto& setRule = node.GetAlt_alter_table_action6().GetRule_alter_table_set_table_setting_uncompat1(); + if (!AlterTableSetTableSetting(setRule, params.TableSettings, params.TableType)) { + return false; + } + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction7: { - // SET (compat) - const auto& setRule = node.GetAlt_alter_table_action7().GetRule_alter_table_set_table_setting_compat1(); - if (!AlterTableSetTableSetting(setRule, params.TableSettings, params.TableType)) { - return false; + case TRule_alter_table_action::kAltAlterTableAction7: { + // SET (compat) + const auto& setRule = node.GetAlt_alter_table_action7().GetRule_alter_table_set_table_setting_compat1(); + if (!AlterTableSetTableSetting(setRule, params.TableSettings, params.TableType)) { + return false; + } + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction8: { - // RESET - const auto& setRule = node.GetAlt_alter_table_action8().GetRule_alter_table_reset_table_setting1(); - if (!AlterTableResetTableSetting(setRule, params.TableSettings, params.TableType)) { - return false; + case TRule_alter_table_action::kAltAlterTableAction8: { + // RESET + const auto& setRule = node.GetAlt_alter_table_action8().GetRule_alter_table_reset_table_setting1(); + if (!AlterTableResetTableSetting(setRule, params.TableSettings, params.TableType)) { + return false; + } + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction9: { - // ADD INDEX - const auto& addIndex = node.GetAlt_alter_table_action9().GetRule_alter_table_add_index1(); - if (!AlterTableAddIndex(addIndex, params)) { - return false; + case TRule_alter_table_action::kAltAlterTableAction9: { + // ADD INDEX + const auto& addIndex = node.GetAlt_alter_table_action9().GetRule_alter_table_add_index1(); + if (!AlterTableAddIndex(addIndex, params)) { + return false; + } + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction10: { - // DROP INDEX - const auto& dropIndex = node.GetAlt_alter_table_action10().GetRule_alter_table_drop_index1(); - AlterTableDropIndex(dropIndex, params); - break; - } - case TRule_alter_table_action::kAltAlterTableAction11: { - // RENAME TO - if (!params.IsEmpty()) { - // rename action follows some other actions - Error() << "RENAME TO can not be used together with another table action"; - return false; + case TRule_alter_table_action::kAltAlterTableAction10: { + // DROP INDEX + const auto& dropIndex = node.GetAlt_alter_table_action10().GetRule_alter_table_drop_index1(); + AlterTableDropIndex(dropIndex, params); + break; } + case TRule_alter_table_action::kAltAlterTableAction11: { + // RENAME TO + if (!params.IsEmpty()) { + // rename action follows some other actions + Error() << "RENAME TO can not be used together with another table action"; + return false; + } - const auto& renameTo = node.GetAlt_alter_table_action11().GetRule_alter_table_rename_to1(); - AlterTableRenameTo(renameTo, params); - break; - } - case TRule_alter_table_action::kAltAlterTableAction12: { - // ADD CHANGEFEED - const auto& rule = node.GetAlt_alter_table_action12().GetRule_alter_table_add_changefeed1(); - if (!AlterTableAddChangefeed(rule, params)) { - return false; + const auto& renameTo = node.GetAlt_alter_table_action11().GetRule_alter_table_rename_to1(); + AlterTableRenameTo(renameTo, params); + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction13: { - // ALTER CHANGEFEED - const auto& rule = node.GetAlt_alter_table_action13().GetRule_alter_table_alter_changefeed1(); - if (!AlterTableAlterChangefeed(rule, params)) { - return false; + case TRule_alter_table_action::kAltAlterTableAction12: { + // ADD CHANGEFEED + const auto& rule = node.GetAlt_alter_table_action12().GetRule_alter_table_add_changefeed1(); + if (!AlterTableAddChangefeed(rule, params)) { + return false; + } + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction14: { - // DROP CHANGEFEED - const auto& rule = node.GetAlt_alter_table_action14().GetRule_alter_table_drop_changefeed1(); - AlterTableDropChangefeed(rule, params); - break; - } - case TRule_alter_table_action::kAltAlterTableAction15: { - // RENAME INDEX TO - if (!params.IsEmpty()) { - // rename action follows some other actions - Error() << "RENAME INDEX TO can not be used together with another table action"; - return false; + case TRule_alter_table_action::kAltAlterTableAction13: { + // ALTER CHANGEFEED + const auto& rule = node.GetAlt_alter_table_action13().GetRule_alter_table_alter_changefeed1(); + if (!AlterTableAlterChangefeed(rule, params)) { + return false; + } + break; } - - const auto& renameTo = node.GetAlt_alter_table_action15().GetRule_alter_table_rename_index_to1(); - AlterTableRenameIndexTo(renameTo, params); - break; - } - case TRule_alter_table_action::kAltAlterTableAction16: { - // ALTER INDEX - const auto& rule = node.GetAlt_alter_table_action16().GetRule_alter_table_alter_index1(); - if (!AlterTableAlterIndex(rule, params)) { - return false; + case TRule_alter_table_action::kAltAlterTableAction14: { + // DROP CHANGEFEED + const auto& rule = node.GetAlt_alter_table_action14().GetRule_alter_table_drop_changefeed1(); + AlterTableDropChangefeed(rule, params); + break; } - break; - } - case TRule_alter_table_action::kAltAlterTableAction17: { - // ALTER COLUMN id DROP NOT NULL - const auto& alterRule = node.GetAlt_alter_table_action17().GetRule_alter_table_alter_column_drop_not_null1(); + case TRule_alter_table_action::kAltAlterTableAction15: { + // RENAME INDEX TO + if (!params.IsEmpty()) { + // rename action follows some other actions + Error() << "RENAME INDEX TO can not be used together with another table action"; + return false; + } - if (!AlterTableAlterColumnDropNotNull(alterRule, params)) { - return false; + const auto& renameTo = node.GetAlt_alter_table_action15().GetRule_alter_table_rename_index_to1(); + AlterTableRenameIndexTo(renameTo, params); + break; + } + case TRule_alter_table_action::kAltAlterTableAction16: { + // ALTER INDEX + const auto& rule = node.GetAlt_alter_table_action16().GetRule_alter_table_alter_index1(); + if (!AlterTableAlterIndex(rule, params)) { + return false; + } + break; } + case TRule_alter_table_action::kAltAlterTableAction17: { + // ALTER COLUMN id DROP NOT NULL + const auto& alterRule = node.GetAlt_alter_table_action17().GetRule_alter_table_alter_column_drop_not_null1(); - break; - } - case TRule_alter_table_action::kAltAlterTableAction18: { - // ALTER COLUMN id SET NOT NULL - const auto& alterRule = node.GetAlt_alter_table_action18().GetRule_alter_table_alter_column_set_not_null1(); + if (!AlterTableAlterColumnDropNotNull(alterRule, params)) { + return false; + } - if (!AlterTableAlterColumnSetNotNull(alterRule, params)) { - return false; + break; } + case TRule_alter_table_action::kAltAlterTableAction18: { + // ALTER COLUMN id SET NOT NULL + const auto& alterRule = node.GetAlt_alter_table_action18().GetRule_alter_table_alter_column_set_not_null1(); - break; - } + if (!AlterTableAlterColumnSetNotNull(alterRule, params)) { + return false; + } - case TRule_alter_table_action::ALT_NOT_SET: { - AltNotImplemented("alter_table_action", node); - return false; - } + break; + } + + case TRule_alter_table_action::ALT_NOT_SET: { + AltNotImplemented("alter_table_action", node); + return false; + } } return true; } @@ -2487,50 +2458,50 @@ bool TSqlQuery::AlterExternalTableAction(const TRule_alter_external_table_action } switch (node.Alt_case()) { - case TRule_alter_external_table_action::kAltAlterExternalTableAction1: { - // ADD COLUMN - const auto& addRule = node.GetAlt_alter_external_table_action1().GetRule_alter_table_add_column1(); - if (!AlterTableAddColumn(addRule, params)) { - return false; + case TRule_alter_external_table_action::kAltAlterExternalTableAction1: { + // ADD COLUMN + const auto& addRule = node.GetAlt_alter_external_table_action1().GetRule_alter_table_add_column1(); + if (!AlterTableAddColumn(addRule, params)) { + return false; + } + break; } - break; - } - case TRule_alter_external_table_action::kAltAlterExternalTableAction2: { - // DROP COLUMN - const auto& dropRule = node.GetAlt_alter_external_table_action2().GetRule_alter_table_drop_column1(); - if (!AlterTableDropColumn(dropRule, params)) { - return false; + case TRule_alter_external_table_action::kAltAlterExternalTableAction2: { + // DROP COLUMN + const auto& dropRule = node.GetAlt_alter_external_table_action2().GetRule_alter_table_drop_column1(); + if (!AlterTableDropColumn(dropRule, params)) { + return false; + } + break; } - break; - } - case TRule_alter_external_table_action::kAltAlterExternalTableAction3: { - // SET (uncompat) - const auto& setRule = node.GetAlt_alter_external_table_action3().GetRule_alter_table_set_table_setting_uncompat1(); - if (!AlterTableSetTableSetting(setRule, params.TableSettings, params.TableType)) { - return false; + case TRule_alter_external_table_action::kAltAlterExternalTableAction3: { + // SET (uncompat) + const auto& setRule = node.GetAlt_alter_external_table_action3().GetRule_alter_table_set_table_setting_uncompat1(); + if (!AlterTableSetTableSetting(setRule, params.TableSettings, params.TableType)) { + return false; + } + break; } - break; - } - case TRule_alter_external_table_action::kAltAlterExternalTableAction4: { - // SET (compat) - const auto& setRule = node.GetAlt_alter_external_table_action4().GetRule_alter_table_set_table_setting_compat1(); - if (!AlterTableSetTableSetting(setRule, params.TableSettings, params.TableType)) { - return false; + case TRule_alter_external_table_action::kAltAlterExternalTableAction4: { + // SET (compat) + const auto& setRule = node.GetAlt_alter_external_table_action4().GetRule_alter_table_set_table_setting_compat1(); + if (!AlterTableSetTableSetting(setRule, params.TableSettings, params.TableType)) { + return false; + } + break; } - break; - } - case TRule_alter_external_table_action::kAltAlterExternalTableAction5: { - // RESET - const auto& setRule = node.GetAlt_alter_external_table_action5().GetRule_alter_table_reset_table_setting1(); - if (!AlterTableResetTableSetting(setRule, params.TableSettings, params.TableType)) { - return false; + case TRule_alter_external_table_action::kAltAlterExternalTableAction5: { + // RESET + const auto& setRule = node.GetAlt_alter_external_table_action5().GetRule_alter_table_reset_table_setting1(); + if (!AlterTableResetTableSetting(setRule, params.TableSettings, params.TableType)) { + return false; + } + break; } - break; - } - case TRule_alter_external_table_action::ALT_NOT_SET: - AltNotImplemented("alter_external_table_action", node); - return false; + case TRule_alter_external_table_action::ALT_NOT_SET: + AltNotImplemented("alter_external_table_action", node); + return false; } return true; } @@ -2555,7 +2526,7 @@ bool TSqlQuery::AlterTableDropColumn(const TRule_alter_table_drop_column& node, } bool TSqlQuery::AlterTableAlterColumn(const TRule_alter_table_alter_column& node, - TAlterTableParameters& params) + TAlterTableParameters& params) { TString name = Id(node.GetRule_an_id3(), *this); const TPosition pos(Context().Pos()); @@ -2576,7 +2547,7 @@ bool TSqlQuery::AlterTableAddFamily(const TRule_family_entry& node, TAlterTableP } bool TSqlQuery::AlterTableAlterFamily(const TRule_alter_table_alter_column_family& node, - TAlterTableParameters& params) + TAlterTableParameters& params) { TFamilyEntry* entry = nullptr; TIdentifier name = IdEx(node.GetRule_an_id3(), *this); @@ -2594,7 +2565,7 @@ bool TSqlQuery::AlterTableAlterFamily(const TRule_alter_table_alter_column_famil if (to_lower(settingName.Name) == "data") { if (entry->Data) { Ctx_.Error() << "Redefinition of " << to_upper(settingName.Name) << " setting for column family '" << name.Name - << "' in one alter"; + << "' in one alter"; return false; } if (!StoreString(value, entry->Data, Ctx_)) { @@ -2604,7 +2575,7 @@ bool TSqlQuery::AlterTableAlterFamily(const TRule_alter_table_alter_column_famil } else if (to_lower(settingName.Name) == "compression") { if (entry->Compression) { Ctx_.Error() << "Redefinition of " << to_upper(settingName.Name) << " setting for column family '" << name.Name - << "' in one alter"; + << "' in one alter"; return false; } if (!StoreString(value, entry->Compression, Ctx_)) { @@ -2623,7 +2594,7 @@ bool TSqlQuery::AlterTableAlterFamily(const TRule_alter_table_alter_column_famil } else if (to_lower(settingName.Name) == "cache_mode") { if (entry->CacheMode) { Ctx_.Error() << "Redefinition of " << to_upper(settingName.Name) << " setting for column family '" << name.Name - << "' in one alter"; + << "' in one alter"; return false; } if (!StoreString(value, entry->CacheMode, Ctx_)) { @@ -2638,28 +2609,24 @@ bool TSqlQuery::AlterTableAlterFamily(const TRule_alter_table_alter_column_famil } bool TSqlQuery::AlterTableSetTableSetting( - const TRule_alter_table_set_table_setting_uncompat& node, TTableSettings& tableSettings, ETableType tableType -) { + const TRule_alter_table_set_table_setting_uncompat& node, TTableSettings& tableSettings, ETableType tableType) { return StoreTableSettingsEntry( IdEx(node.GetRule_an_id2(), *this), node.GetRule_table_setting_value3(), tableSettings, tableType, - true - ); + true); } bool TSqlQuery::AlterTableSetTableSetting( - const TRule_alter_table_set_table_setting_compat& node, TTableSettings& tableSettings, ETableType tableType -) { + const TRule_alter_table_set_table_setting_compat& node, TTableSettings& tableSettings, ETableType tableType) { const auto storeSetting = [&](const TRule_alter_table_setting_entry& entry) { return StoreTableSettingsEntry( IdEx(entry.GetRule_an_id1(), *this), entry.GetRule_table_setting_value3(), tableSettings, tableType, - true - ); + true); }; const auto& firstEntry = node.GetRule_alter_table_setting_entry3(); @@ -2676,8 +2643,7 @@ bool TSqlQuery::AlterTableSetTableSetting( } bool TSqlQuery::AlterTableResetTableSetting( - const TRule_alter_table_reset_table_setting& node, TTableSettings& tableSettings, ETableType tableType -) { + const TRule_alter_table_reset_table_setting& node, TTableSettings& tableSettings, ETableType tableType) { const auto resetSetting = [&](const TRule_an_id& id) { return ResetTableSettingsEntry(IdEx(id, *this), tableSettings, tableType); }; @@ -2725,33 +2691,33 @@ bool TSqlQuery::AlterTableAlterIndex(const TRule_alter_table_alter_index& node, const auto& action = node.GetRule_alter_table_alter_index_action4(); switch (action.Alt_case()) { - case TRule_alter_table_alter_index_action::kAltAlterTableAlterIndexAction1: { - // SET setting value - const auto& rule = action.GetAlt_alter_table_alter_index_action1().GetRule_alter_table_set_table_setting_uncompat1(); - if (!AlterTableSetTableSetting(rule, indexTableSettings, params.TableType)) { - return false; + case TRule_alter_table_alter_index_action::kAltAlterTableAlterIndexAction1: { + // SET setting value + const auto& rule = action.GetAlt_alter_table_alter_index_action1().GetRule_alter_table_set_table_setting_uncompat1(); + if (!AlterTableSetTableSetting(rule, indexTableSettings, params.TableType)) { + return false; + } + break; } - break; - } - case TRule_alter_table_alter_index_action::kAltAlterTableAlterIndexAction2: { - // SET (setting1 = value1, ...) - const auto& rule = action.GetAlt_alter_table_alter_index_action2().GetRule_alter_table_set_table_setting_compat1(); - if (!AlterTableSetTableSetting(rule, indexTableSettings, params.TableType)) { - return false; + case TRule_alter_table_alter_index_action::kAltAlterTableAlterIndexAction2: { + // SET (setting1 = value1, ...) + const auto& rule = action.GetAlt_alter_table_alter_index_action2().GetRule_alter_table_set_table_setting_compat1(); + if (!AlterTableSetTableSetting(rule, indexTableSettings, params.TableType)) { + return false; + } + break; } - break; - } - case TRule_alter_table_alter_index_action::kAltAlterTableAlterIndexAction3: { - // RESET (setting1, ...) - const auto& rule = action.GetAlt_alter_table_alter_index_action3().GetRule_alter_table_reset_table_setting1(); - if (!AlterTableResetTableSetting(rule, indexTableSettings, params.TableType)) { - return false; + case TRule_alter_table_alter_index_action::kAltAlterTableAlterIndexAction3: { + // RESET (setting1, ...) + const auto& rule = action.GetAlt_alter_table_alter_index_action3().GetRule_alter_table_reset_table_setting1(); + if (!AlterTableResetTableSetting(rule, indexTableSettings, params.TableType)) { + return false; + } + break; } - break; - } - case TRule_alter_table_alter_index_action::ALT_NOT_SET: - AltNotImplemented("alter_table_alter_index_action", action); - return false; + case TRule_alter_table_alter_index_action::ALT_NOT_SET: + AltNotImplemented("alter_table_alter_index_action", action); + return false; } return true; @@ -2866,7 +2832,7 @@ void TSqlQuery::AlterTableDropChangefeed(const TRule_alter_table_drop_changefeed } namespace { -#define CB_SIG TVector<TDeferredAtom>& values [[maybe_unused]], bool pragmaValueDefault [[maybe_unused]], TStringBuf pragma [[maybe_unused]], TSqlQuery& query [[maybe_unused]] +#define CB_SIG TVector<TDeferredAtom>&values [[maybe_unused]], bool pragmaValueDefault [[maybe_unused]], TStringBuf pragma [[maybe_unused]], TSqlQuery &query [[maybe_unused]] using PragmaStatementCb = std::function<TMaybe<TNodePtr>(CB_SIG)>; @@ -2875,8 +2841,10 @@ struct TPragmaDescr { PragmaStatementCb Cb; }; -template<typename T, std::convertible_to<T> U> -PragmaStatementCb SetCtxField(T TContext::* ParamPtr, U ParamValue) requires std::movable<U> { +template <typename T, std::convertible_to<T> U> +PragmaStatementCb SetCtxField(T TContext::*ParamPtr, U ParamValue) + requires std::movable<U> +{ return [ParamPtr, ParamValue = std::move(ParamValue)](CB_SIG) { auto& Ctx_ = query.Context(); Ctx_.*ParamPtr = std::move(ParamValue); @@ -3237,8 +3205,8 @@ THashMap<TString, TPragmaDescr> PragmaDescrs{ return {}; } if (!ctx.Warning(ctx.Pos(), TIssuesIds::YQL_PRAGMA_WARNING_MSG, [&](auto& out) { - out << *values[0].GetLiteral(); - })) { + out << *values[0].GetLiteral(); + })) { return {}; } return TNodePtr{}; @@ -3271,8 +3239,8 @@ THashMap<TString, TPragmaDescr> PragmaDescrs{ TableElemExt("DisableUnordered", [](CB_SIG) -> TMaybe<TNodePtr> { auto& ctx = query.Context(); if (!ctx.Warning(ctx.Pos(), TIssuesIds::YQL_DEPRECATED_PRAGMA, [](auto& out) { - out << "Use of deprecated DisableUnordered pragma. It will be dropped soon"; - })) { + out << "Use of deprecated DisableUnordered pragma. It will be dropped soon"; + })) { return {}; } return TNodePtr{}; @@ -3386,9 +3354,9 @@ THashMap<TString, TPragmaDescr> PragmaDescrs{ TableElemExt("DisableFlexibleTypes", [](CB_SIG) -> TMaybe<TNodePtr> { auto& ctx = query.Context(); if (!ctx.Warning(ctx.Pos(), TIssuesIds::YQL_DEPRECATED_PRAGMA, [](auto& out) { - out << "Deprecated pragma DisableFlexibleTypes - it will be removed soon. " - << "Consider submitting bug report if FlexibleTypes doesn't work for you"; - })) { + out << "Deprecated pragma DisableFlexibleTypes - it will be removed soon. " + << "Consider submitting bug report if FlexibleTypes doesn't work for you"; + })) { return {}; } ctx.FlexibleTypes = false; @@ -3423,9 +3391,9 @@ THashMap<TString, TPragmaDescr> PragmaDescrs{ TableElemExt("DisableCompactNamedExprs", [](CB_SIG) -> TMaybe<TNodePtr> { auto& ctx = query.Context(); if (!ctx.Warning(ctx.Pos(), TIssuesIds::YQL_DEPRECATED_PRAGMA, [](auto& out) { - out << "Deprecated pragma DisableCompactNamedExprs - it will be removed soon. " - << "Consider submitting bug report if CompactNamedExprs doesn't work for you"; - })) { + out << "Deprecated pragma DisableCompactNamedExprs - it will be removed soon. " + << "Consider submitting bug report if CompactNamedExprs doesn't work for you"; + })) { return {}; } ctx.CompactNamedExprs = false; @@ -3538,8 +3506,7 @@ TMaybe<TNodePtr> TSqlQuery::PragmaStatement(const TRule_pragma_stmt& stmt) { if (stmt.GetBlock4().HasAlt1()) { // pragma=value pragmaValues.push_back(&stmt.GetBlock4().GetAlt1().GetRule_pragma_value2()); - } - else if (stmt.GetBlock4().HasAlt2()) { + } else if (stmt.GetBlock4().HasAlt2()) { // pragma(value,value...) pragmaValues.push_back(&stmt.GetBlock4().GetAlt2().GetRule_pragma_value2()); for (auto& additionalValue : stmt.GetBlock4().GetAlt2().GetBlock3()) { @@ -3576,15 +3543,11 @@ TMaybe<TNodePtr> TSqlQuery::PragmaStatement(const TRule_pragma_stmt& stmt) { } values.push_back(TDeferredAtom(Ctx_.Pos(), prefix + parsed->Content)); - } - else if (pragmaValue->HasAlt_pragma_value2() - && pragmaValue->GetAlt_pragma_value2().GetRule_id1().HasAlt_id2() - && "default" == to_lower(Id(pragmaValue->GetAlt_pragma_value2().GetRule_id1(), *this))) + } else if (pragmaValue->HasAlt_pragma_value2() && pragmaValue->GetAlt_pragma_value2().GetRule_id1().HasAlt_id2() && "default" == to_lower(Id(pragmaValue->GetAlt_pragma_value2().GetRule_id1(), *this))) { // 'DEFAULT' keyword. pragmaValueDefault = true; - } - else if (withConfigure && pragmaValue->HasAlt_pragma_value5()) { + } else if (withConfigure && pragmaValue->HasAlt_pragma_value5()) { // Bind parameter. TString bindName; if (!NamedNodeImpl(pragmaValue->GetAlt_pragma_value5().GetRule_bind_parameter1(), bindName, *this)) { @@ -3614,7 +3577,7 @@ TMaybe<TNodePtr> TSqlQuery::PragmaStatement(const TRule_pragma_stmt& stmt) { if (!allowTopLevelPragmas && !hasLexicalScope) { Error() << "This pragma '" << pragma << "' is not allowed to be used in actions or subqueries"; Ctx_.IncrementMonCounter("sql_errors", "BadPragmaValue"); - return{}; + return {}; } if (auto descr = PragmaDescrs.FindPtr(normalizedPragma)) { @@ -3629,8 +3592,7 @@ TMaybe<TNodePtr> TSqlQuery::PragmaStatement(const TRule_pragma_stmt& stmt) { return result; } else if (normalizedPragma == "dqengine" || normalizedPragma == "blockengine") { Ctx_.IncrementMonCounter("sql_pragma", "DqEngine"); - if (values.size() != 1 || !values[0].GetLiteral() - || ! (*values[0].GetLiteral() == "disable" || *values[0].GetLiteral() == "auto" || *values[0].GetLiteral() == "force")) + if (values.size() != 1 || !values[0].GetLiteral() || !(*values[0].GetLiteral() == "disable" || *values[0].GetLiteral() == "auto" || *values[0].GetLiteral() == "force")) { Error() << "Expected `disable|auto|force' argument for: " << pragma; Ctx_.IncrementMonCounter("sql_errors", "BadPragmaValue"); @@ -3638,7 +3600,7 @@ TMaybe<TNodePtr> TSqlQuery::PragmaStatement(const TRule_pragma_stmt& stmt) { } const bool isDqEngine = normalizedPragma == "dqengine"; auto& enable = isDqEngine ? Ctx_.DqEngineEnable : Ctx_.BlockEngineEnable; - auto& force = isDqEngine ? Ctx_.DqEngineForce : Ctx_.BlockEngineForce; + auto& force = isDqEngine ? Ctx_.DqEngineForce : Ctx_.BlockEngineForce; if (*values[0].GetLiteral() == "disable") { enable = false; force = false; @@ -3654,7 +3616,7 @@ TMaybe<TNodePtr> TSqlQuery::PragmaStatement(const TRule_pragma_stmt& stmt) { if (*Ctx_.Engine == "ytflow") { if (force) { Error() << "Expected `disable|auto` argument for: " << pragma << " pragma " - << "with Engine pragma argument `ytflow`"; + << "with Engine pragma argument `ytflow`"; Ctx_.IncrementMonCounter("sql_errors", "BadPragmaValue"); return {}; @@ -3679,8 +3641,8 @@ TMaybe<TNodePtr> TSqlQuery::PragmaStatement(const TRule_pragma_stmt& stmt) { } if (normalizedPragma == "fast") { if (!Ctx_.Warning(Ctx_.Pos(), TIssuesIds::YQL_DEPRECATED_PRAGMA, [](auto& out) { - out << "Use of deprecated yson.Fast pragma. It will be dropped soon"; - })) { + out << "Use of deprecated yson.Fast pragma. It will be dropped soon"; + })) { return {}; } return TNodePtr{}; @@ -3733,8 +3695,7 @@ TMaybe<TNodePtr> TSqlQuery::PragmaStatement(const TRule_pragma_stmt& stmt) { } else if (std::find(Providers.cbegin(), Providers.cend(), lowerPrefix) == Providers.cend()) { if (!Ctx_.HasCluster(prefix)) { - Error() << "Unknown pragma prefix: " << prefix << ", please use cluster name or one of provider " << - JoinRange(", ", Providers.cbegin(), Providers.cend()); + Error() << "Unknown pragma prefix: " << prefix << ", please use cluster name or one of provider " << JoinRange(", ", Providers.cbegin(), Providers.cend()); Ctx_.IncrementMonCounter("sql_errors", "UnknownPragma"); return {}; } @@ -3779,9 +3740,9 @@ TNodePtr TSqlQuery::Build(const TRule_delete_stmt& stmt) { if (stmt.HasBlock6()) { if (isBatch) { - Ctx_.Error(GetPos(stmt.GetToken2())) - << "BATCH DELETE is unsupported with RETURNING"; - return nullptr; + Ctx_.Error(GetPos(stmt.GetToken2())) + << "BATCH DELETE is unsupported with RETURNING"; + return nullptr; } options = ReturningList(stmt.GetBlock6().GetRule_returning_columns_list1()); @@ -3931,7 +3892,7 @@ TSourcePtr TSqlQuery::Build(const TRule_set_clause_list& stmt) { if (!FillSetClause(stmt.GetRule_set_clause1(), targetList, values)) { return nullptr; } - for (auto& block: stmt.GetBlock2()) { + for (auto& block : stmt.GetBlock2()) { if (!FillSetClause(block.GetRule_set_clause2(), targetList, values)) { return nullptr; } @@ -3978,7 +3939,7 @@ TNodePtr TSqlQuery::Build(const TSQLv1ParserAST& ast) { return nullptr; } - TNodePtr typeNode = BuildBuiltinFunc(Ctx_, Ctx_.Pos(), "ParseType", { BuildLiteralRawString(Ctx_.Pos(), type) }); + TNodePtr typeNode = BuildBuiltinFunc(Ctx_, Ctx_.Pos(), "ParseType", {BuildLiteralRawString(Ctx_.Pos(), type)}); PushNamedAtom(Ctx_.Pos(), varName); // no duplicates are possible at this stage bool isWeak = true; @@ -4000,7 +3961,7 @@ TNodePtr TSqlQuery::Build(const TSQLv1ParserAST& ast) { if (!Statement(blocks, statements.GetRule_sql_stmt2().GetRule_sql_stmt_core2(), statementNumber++)) { return nullptr; } - for (auto block: statements.GetBlock3()) { + for (auto block : statements.GetBlock3()) { if (!Statement(blocks, block.GetRule_sql_stmt2().GetRule_sql_stmt_core2(), statementNumber++)) { return nullptr; } @@ -4023,11 +3984,11 @@ TNodePtr TSqlQuery::Build(const TSQLv1ParserAST& ast) { if ((Mode_ == NSQLTranslation::ESqlMode::SUBQUERY || Mode_ == NSQLTranslation::ESqlMode::LIMITED_VIEW) && (topLevelSelects != 1 || hasTailOps)) { Error() << "Strictly one select/process/reduce statement is expected at the end of " - << (Mode_ == NSQLTranslation::ESqlMode::LIMITED_VIEW ? "view" : "subquery"); + << (Mode_ == NSQLTranslation::ESqlMode::LIMITED_VIEW ? "view" : "subquery"); return nullptr; } - if (!Ctx_.PragmaAutoCommit && Ctx_.Settings.EndOfQueryCommit && IsQueryMode(Mode_)) { + if (!Ctx_.PragmaAutoCommit && Ctx_.Settings.EndOfQueryCommit && IsQueryMode(Mode_)) { AddStatementToBlocks(blocks, BuildCommitClusters(Ctx_.Pos())); } @@ -4058,7 +4019,7 @@ TNodePtr TSqlQuery::Build(const std::vector<::NSQLv1Generated::TRule_sql_stmt_co return nullptr; } - TNodePtr typeNode = BuildBuiltinFunc(Ctx_, Ctx_.Pos(), "ParseType", { BuildLiteralRawString(Ctx_.Pos(), type) }); + TNodePtr typeNode = BuildBuiltinFunc(Ctx_, Ctx_.Pos(), "ParseType", {BuildLiteralRawString(Ctx_.Pos(), type)}); PushNamedAtom(Ctx_.Pos(), varName); // no duplicates are possible at this stage bool isWeak = true; @@ -4097,11 +4058,11 @@ TNodePtr TSqlQuery::Build(const std::vector<::NSQLv1Generated::TRule_sql_stmt_co if ((Mode_ == NSQLTranslation::ESqlMode::SUBQUERY || Mode_ == NSQLTranslation::ESqlMode::LIMITED_VIEW) && (topLevelSelects != 1 || hasTailOps)) { Error() << "Strictly one select/process/reduce statement is expected at the end of " - << (Mode_ == NSQLTranslation::ESqlMode::LIMITED_VIEW ? "view" : "subquery"); + << (Mode_ == NSQLTranslation::ESqlMode::LIMITED_VIEW ? "view" : "subquery"); return nullptr; } - if (!Ctx_.PragmaAutoCommit && Ctx_.Settings.EndOfQueryCommit && IsQueryMode(Mode_)) { + if (!Ctx_.PragmaAutoCommit && Ctx_.Settings.EndOfQueryCommit && IsQueryMode(Mode_)) { AddStatementToBlocks(blocks, BuildCommitClusters(Ctx_.Pos())); } @@ -4110,49 +4071,48 @@ TNodePtr TSqlQuery::Build(const std::vector<::NSQLv1Generated::TRule_sql_stmt_co } namespace { - static bool BuildColumnFeatures(std::map<TString, TDeferredAtom>& result, const TRule_column_schema& columnSchema, const NYql::TPosition& pos, TSqlTranslation& translation) { - const TString columnName(Id(columnSchema.GetRule_an_id_schema1(), translation)); - TString columnType; +static bool BuildColumnFeatures(std::map<TString, TDeferredAtom>& result, const TRule_column_schema& columnSchema, const NYql::TPosition& pos, TSqlTranslation& translation) { + const TString columnName(Id(columnSchema.GetRule_an_id_schema1(), translation)); + TString columnType; - const auto options = ColumnOptions(columnSchema, translation); - if (!options) { - return false; - } + const auto options = ColumnOptions(columnSchema, translation); + if (!options) { + return false; + } - auto& typeBind = columnSchema.GetRule_type_name_or_bind2(); - switch (typeBind.Alt_case()) { - case TRule_type_name_or_bind::kAltTypeNameOrBind1: - { - auto& typeNameOrBind = typeBind.GetAlt_type_name_or_bind1().GetRule_type_name1(); - if (typeNameOrBind.Alt_case() != TRule_type_name::kAltTypeName2) { - return false; - } - auto& alt = typeNameOrBind.GetAlt_type_name2(); - auto& block = alt.GetBlock1(); - auto& simpleType = block.GetAlt2().GetRule_type_name_simple1(); - columnType = Id(simpleType.GetRule_an_id_pure1(), translation); - if (columnType.empty()) { - return false; - } - break; + auto& typeBind = columnSchema.GetRule_type_name_or_bind2(); + switch (typeBind.Alt_case()) { + case TRule_type_name_or_bind::kAltTypeNameOrBind1: { + auto& typeNameOrBind = typeBind.GetAlt_type_name_or_bind1().GetRule_type_name1(); + if (typeNameOrBind.Alt_case() != TRule_type_name::kAltTypeName2) { + return false; } - case TRule_type_name_or_bind::kAltTypeNameOrBind2: + auto& alt = typeNameOrBind.GetAlt_type_name2(); + auto& block = alt.GetBlock1(); + auto& simpleType = block.GetAlt2().GetRule_type_name_simple1(); + columnType = Id(simpleType.GetRule_an_id_pure1(), translation); + if (columnType.empty()) { return false; - case TRule_type_name_or_bind::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + } + break; } + case TRule_type_name_or_bind::kAltTypeNameOrBind2: + return false; + case TRule_type_name_or_bind::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); + } - result["NAME"] = TDeferredAtom(pos, columnName); - YQL_ENSURE(columnType, "Unknown column type"); - result["TYPE"] = TDeferredAtom(pos, columnType); - if (!options->Nullable) { - result["NOT_NULL"] = TDeferredAtom(pos, "true"); - } - return true; + result["NAME"] = TDeferredAtom(pos, columnName); + YQL_ENSURE(columnType, "Unknown column type"); + result["TYPE"] = TDeferredAtom(pos, columnType); + if (!options->Nullable) { + result["NOT_NULL"] = TDeferredAtom(pos, "true"); } + return true; } +} // namespace -bool TSqlQuery::ParseTableStoreFeatures(std::map<TString, TDeferredAtom> & result, const TRule_alter_table_store_action & actions) { +bool TSqlQuery::ParseTableStoreFeatures(std::map<TString, TDeferredAtom>& result, const TRule_alter_table_store_action& actions) { switch (actions.Alt_case()) { case TRule_alter_table_store_action::kAltAlterTableStoreAction1: { // ADD COLUMN diff --git a/yql/essentials/sql/v1/sql_query.h b/yql/essentials/sql/v1/sql_query.h index 95061d7262a..67237557c35 100644 --- a/yql/essentials/sql/v1/sql_query.h +++ b/yql/essentials/sql/v1/sql_query.h @@ -22,6 +22,7 @@ public: TNodePtr Build(const std::vector<::NSQLv1Generated::TRule_sql_stmt_core>& ast); bool Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core& core, size_t statementNumber); + private: bool DeclareStatement(const TRule_declare_stmt& stmt); bool ExportStatement(const TRule_export_stmt& stmt); @@ -46,7 +47,7 @@ private: bool AlterSequenceAction(const TRule_alter_sequence_action& node, TSequenceParameters& params); TMaybe<TNodePtr> PragmaStatement(const TRule_pragma_stmt& stmt); void AddStatementToBlocks(TVector<TNodePtr>& blocks, TNodePtr node); - bool ParseTableStoreFeatures(std::map<TString, TDeferredAtom> & result, const TRule_alter_table_store_action & actions); + bool ParseTableStoreFeatures(std::map<TString, TDeferredAtom>& result, const TRule_alter_table_store_action& actions); bool AlterTableAlterColumnDropNotNull(const TRule_alter_table_alter_column_drop_not_null& node, TAlterTableParameters& params); bool AlterTableAlterColumnSetNotNull(const TRule_alter_table_alter_column_set_not_null& node, TAlterTableParameters& params); @@ -58,7 +59,7 @@ private: TSourcePtr Build(const TRule_set_clause_list& stmt); TSourcePtr Build(const TRule_multiple_column_assignment& stmt); - template<class TNode> + template <class TNode> void ParseStatementName(const TNode& node, TString& internalStatementName, TString& humanStatementName) { internalStatementName.clear(); humanStatementName.clear(); @@ -73,7 +74,7 @@ private: } Y_DEBUG_ABORT_UNLESS(parts.size() > 1); parts.pop_back(); - for (auto& part: parts) { + for (auto& part : parts) { part.to_upper(0, 1); internalStatementName += part; if (!humanStatementName.empty()) { diff --git a/yql/essentials/sql/v1/sql_select.cpp b/yql/essentials/sql/v1/sql_select.cpp index 3d84bc9f532..b07b0ed7ab4 100644 --- a/yql/essentials/sql/v1/sql_select.cpp +++ b/yql/essentials/sql/v1/sql_select.cpp @@ -12,7 +12,7 @@ using namespace NSQLv1Generated; namespace { bool IsColumnsOnly(const TVector<TSortSpecificationPtr>& container) { - for (const auto& elem: container) { + for (const auto& elem : container) { if (!elem->OrderExpr->GetColumnName()) { return false; } @@ -23,9 +23,9 @@ bool IsColumnsOnly(const TVector<TSortSpecificationPtr>& container) { bool CollectJoinLinkSettings(TPosition pos, TJoinLinkSettings& linkSettings, TContext& ctx) { linkSettings = {}; auto hints = ctx.PullHintForToken(pos); - for (const auto& hint: hints) { + for (const auto& hint : hints) { const auto canonizedName = to_lower(hint.Name); - auto newStrategy = TJoinLinkSettings::EStrategy::Default; + auto newStrategy = TJoinLinkSettings::EStrategy::Default; if (canonizedName == "merge") { newStrategy = TJoinLinkSettings::EStrategy::SortedMerge; } else if (canonizedName == "streamlookup") { @@ -39,8 +39,8 @@ bool CollectJoinLinkSettings(TPosition pos, TJoinLinkSettings& linkSettings, TCo continue; } else { if (!ctx.Warning(hint.Pos, TIssuesIds::YQL_UNUSED_HINT, [&](auto& out) { - out << "Unsupported join hint: " << hint.Name; - })) { + out << "Unsupported join hint: " << hint.Name; + })) { return false; } } @@ -100,33 +100,33 @@ bool TSqlSelect::JoinOp(ISource* join, const TRule_join_source::TBlock3& block, if (alt.GetBlock2().GetAlt1().HasBlock1()) { auto block = alt.GetBlock2().GetAlt1().GetBlock1(); switch (block.Alt_case()) { - case TRule_join_op_TAlt2_TBlock2_TAlt1_TBlock1::kAlt1: - // left - joinOp = Token(block.GetAlt1().GetToken1()); - if (block.GetAlt1().HasBlock2()) { - joinOp += " " + Token(block.GetAlt1().GetBlock2().GetToken1()); - } - break; - case TRule_join_op_TAlt2_TBlock2_TAlt1_TBlock1::kAlt2: - // right - joinOp = Token(block.GetAlt2().GetToken1()); - if (block.GetAlt2().HasBlock2()) { - joinOp += " " + Token(block.GetAlt2().GetBlock2().GetToken1()); - } - - break; - case TRule_join_op_TAlt2_TBlock2_TAlt1_TBlock1::kAlt3: - // exclusion - joinOp = Token(block.GetAlt3().GetToken1()); - break; - case TRule_join_op_TAlt2_TBlock2_TAlt1_TBlock1::kAlt4: - // full - joinOp = Token(block.GetAlt4().GetToken1()); - break; - case TRule_join_op_TAlt2_TBlock2_TAlt1_TBlock1::ALT_NOT_SET: - Ctx_.IncrementMonCounter("sql_errors", "UnknownJoinOperation"); - AltNotImplemented("join_op", node); - return false; + case TRule_join_op_TAlt2_TBlock2_TAlt1_TBlock1::kAlt1: + // left + joinOp = Token(block.GetAlt1().GetToken1()); + if (block.GetAlt1().HasBlock2()) { + joinOp += " " + Token(block.GetAlt1().GetBlock2().GetToken1()); + } + break; + case TRule_join_op_TAlt2_TBlock2_TAlt1_TBlock1::kAlt2: + // right + joinOp = Token(block.GetAlt2().GetToken1()); + if (block.GetAlt2().HasBlock2()) { + joinOp += " " + Token(block.GetAlt2().GetBlock2().GetToken1()); + } + + break; + case TRule_join_op_TAlt2_TBlock2_TAlt1_TBlock1::kAlt3: + // exclusion + joinOp = Token(block.GetAlt3().GetToken1()); + break; + case TRule_join_op_TAlt2_TBlock2_TAlt1_TBlock1::kAlt4: + // full + joinOp = Token(block.GetAlt4().GetToken1()); + break; + case TRule_join_op_TAlt2_TBlock2_TAlt1_TBlock1::ALT_NOT_SET: + Ctx_.IncrementMonCounter("sql_errors", "UnknownJoinOperation"); + AltNotImplemented("join_op", node); + return false; } } if (alt.GetBlock2().GetAlt1().HasBlock2()) { @@ -164,8 +164,8 @@ bool TSqlSelect::JoinOp(ISource* join, const TRule_join_source::TBlock3& block, joinOp = NormalizeJoinOp(joinOp); if (linkSettings.Strategy != TJoinLinkSettings::EStrategy::Default && joinOp == "Cross") { if (!Ctx_.Warning(Ctx_.Pos(), TIssuesIds::YQL_UNUSED_HINT, [](auto& out) { - out << "Non-default join strategy will not be used for CROSS JOIN"; - })) { + out << "Non-default join strategy will not be used for CROSS JOIN"; + })) { return false; } linkSettings.Strategy = TJoinLinkSettings::EStrategy::Default; @@ -184,8 +184,7 @@ bool TSqlSelect::JoinOp(ISource* join, const TRule_join_source::TBlock3& block, Ctx_.IncrementMonCounter("sql_errors", "BadJoinExpr"); return false; } - } - else { + } else { if (joinOp != "Cross") { Error() << "Expected ON or USING expression"; Ctx_.IncrementMonCounter("sql_errors", "BadJoinExpr"); @@ -326,39 +325,39 @@ TSourcePtr TSqlSelect::FlattenSource(const TRule_flatten_source& node) { auto flatten = node.GetBlock2(); auto flatten2 = flatten.GetBlock2(); switch (flatten2.Alt_case()) { - case TRule_flatten_source::TBlock2::TBlock2::kAlt1: { - TString mode = "auto"; - if (flatten2.GetAlt1().HasBlock1()) { - mode = to_lower(Token(flatten2.GetAlt1().GetBlock1().GetToken1())); - } + case TRule_flatten_source::TBlock2::TBlock2::kAlt1: { + TString mode = "auto"; + if (flatten2.GetAlt1().HasBlock1()) { + mode = to_lower(Token(flatten2.GetAlt1().GetBlock1().GetToken1())); + } - TVector<TNodePtr> flattenByColumns; - TVector<TNodePtr> flattenByExprs; - if (!FlattenByArg(source->GetLabel(), flattenByColumns, flattenByExprs, flatten2.GetAlt1().GetRule_flatten_by_arg3())) { - return nullptr; - } + TVector<TNodePtr> flattenByColumns; + TVector<TNodePtr> flattenByExprs; + if (!FlattenByArg(source->GetLabel(), flattenByColumns, flattenByExprs, flatten2.GetAlt1().GetRule_flatten_by_arg3())) { + return nullptr; + } - Ctx_.IncrementMonCounter("sql_features", "FlattenByColumns"); - if (!source->AddExpressions(Ctx_, flattenByColumns, EExprSeat::FlattenBy)) { - return nullptr; - } + Ctx_.IncrementMonCounter("sql_features", "FlattenByColumns"); + if (!source->AddExpressions(Ctx_, flattenByColumns, EExprSeat::FlattenBy)) { + return nullptr; + } - if (!source->AddExpressions(Ctx_, flattenByExprs, EExprSeat::FlattenByExpr)) { - return nullptr; - } + if (!source->AddExpressions(Ctx_, flattenByExprs, EExprSeat::FlattenByExpr)) { + return nullptr; + } - source->SetFlattenByMode(mode); - break; - } - case TRule_flatten_source::TBlock2::TBlock2::kAlt2: { - Ctx_.IncrementMonCounter("sql_features", "FlattenColumns"); - source->MarkFlattenColumns(); - break; - } + source->SetFlattenByMode(mode); + break; + } + case TRule_flatten_source::TBlock2::TBlock2::kAlt2: { + Ctx_.IncrementMonCounter("sql_features", "FlattenColumns"); + source->MarkFlattenColumns(); + break; + } - case TRule_flatten_source::TBlock2::TBlock2::ALT_NOT_SET: - Ctx_.IncrementMonCounter("sql_errors", "UnknownOrdinaryNamedColumn"); - AltNotImplemented("flatten_source", flatten2); + case TRule_flatten_source::TBlock2::TBlock2::ALT_NOT_SET: + Ctx_.IncrementMonCounter("sql_errors", "UnknownOrdinaryNamedColumn"); + AltNotImplemented("flatten_source", flatten2); } } return source; @@ -386,7 +385,7 @@ TSourcePtr TSqlSelect::JoinSource(const TRule_join_source& node) { anyPositions.emplace_back(node.HasBlock1() ? Ctx_.TokenPosition(node.GetBlock1().GetToken1()) : TMaybe<TPosition>()); anyFlags.push_back(bool(anyPositions.back())); - for (auto& block: node.GetBlock3()) { + for (auto& block : node.GetBlock3()) { sources.emplace_back(FlattenSource(block.GetRule_flatten_source3())); if (!sources.back()) { Ctx_.IncrementMonCounter("sql_errors", "NoJoinWith"); @@ -399,7 +398,7 @@ TSourcePtr TSqlSelect::JoinSource(const TRule_join_source& node) { source = BuildEquiJoin(pos, std::move(sources), std::move(anyFlags), Ctx_.Scoped->StrictJoinKeyTypes); size_t idx = 1; - for (auto& block: node.GetBlock3()) { + for (auto& block : node.GetBlock3()) { YQL_ENSURE(idx < anyPositions.size()); TMaybe<TPosition> leftAny = (idx == 1) ? anyPositions[0] : Nothing(); TMaybe<TPosition> rightAny = anyPositions[idx]; @@ -475,7 +474,7 @@ bool TSqlSelect::SelectTerm(TVector<TNodePtr>& terms, const TRule_result_column& bool TSqlSelect::ValidateSelectColumns(const TVector<TNodePtr>& terms) { TSet<TString> labels; TSet<TString> asteriskSources; - for (const auto& term: terms) { + for (const auto& term : terms) { const auto& label = term->GetLabel(); if (!Ctx_.PragmaAllowDotInAlias && label.find('.') != TString::npos) { Ctx_.Error(term->GetPos()) << "Unable to use '.' in column name. Invalid column name: " << label; @@ -585,8 +584,8 @@ TSourcePtr TSqlSelect::NamedSingleSource(const TRule_named_single_source& node, } if (node.HasBlock2()) { if (node.HasBlock4()) { - //CAN/CSA-ISO/IEC 9075-2:18 7.6 <table reference> - //4) TF shall not simply contain both a <sample clause> and a <row pattern recognition clause and name>. + // CAN/CSA-ISO/IEC 9075-2:18 7.6 <table reference> + // 4) TF shall not simply contain both a <sample clause> and a <row pattern recognition clause and name>. Ctx_.Error() << "Source shall not simply contain both a sample clause and a row pattern recognition clause"; return {}; } @@ -622,8 +621,7 @@ TSourcePtr TSqlSelect::NamedSingleSource(const TRule_named_single_source& node, const auto& sampleBlock = node.GetBlock4(); TPosition pos; switch (sampleBlock.Alt_case()) { - case TRule_named_single_source::TBlock4::kAlt1: - { + case TRule_named_single_source::TBlock4::kAlt1: { sampleClause = ESampleClause::Sample; mode = ESampleMode::Bernoulli; const auto& sampleExpr = sampleBlock.GetAlt1().GetRule_sample_clause1().GetRule_expr2(); @@ -633,10 +631,8 @@ TSourcePtr TSqlSelect::NamedSingleSource(const TRule_named_single_source& node, } pos = GetPos(sampleBlock.GetAlt1().GetRule_sample_clause1().GetToken1()); Ctx_.IncrementMonCounter("sql_features", "SampleClause"); - } - break; - case TRule_named_single_source::TBlock4::kAlt2: - { + } break; + case TRule_named_single_source::TBlock4::kAlt2: { sampleClause = ESampleClause::TableSample; const auto& tableSampleClause = sampleBlock.GetAlt2().GetRule_tablesample_clause1(); const auto& modeToken = tableSampleClause.GetRule_sampling_mode2().GetToken1(); @@ -664,10 +660,9 @@ TSourcePtr TSqlSelect::NamedSingleSource(const TRule_named_single_source& node, } pos = GetPos(sampleBlock.GetAlt2().GetRule_tablesample_clause1().GetToken1()); Ctx_.IncrementMonCounter("sql_features", "SampleClause"); - } - break; - case TRule_named_single_source::TBlock4::ALT_NOT_SET: - Y_ABORT("SampleClause: does not corresond to grammar changes"); + } break; + case TRule_named_single_source::TBlock4::ALT_NOT_SET: + Y_ABORT("SampleClause: does not corresond to grammar changes"); } if (!singleSource->SetSamplingOptions(Ctx_, pos, sampleClause, mode, samplingRateNode, samplingSeedNode)) { Ctx_.IncrementMonCounter("sql_errors", "IncorrectSampleClause"); @@ -718,7 +713,7 @@ bool TSqlSelect::ColumnName(TVector<TNodePtr>& keys, const TRule_without_column_ return true; } -template<typename TRule> +template <typename TRule> bool TSqlSelect::ColumnList(TVector<TNodePtr>& keys, const TRule& node) { bool result; if constexpr (std::is_same_v<TRule, TRule_column_list>) { @@ -731,7 +726,7 @@ bool TSqlSelect::ColumnList(TVector<TNodePtr>& keys, const TRule& node) { return false; } - for (auto b: node.GetBlock2()) { + for (auto b : node.GetBlock2()) { Token(b.GetToken1()); if constexpr (std::is_same_v<TRule, TRule_column_list>) { result = ColumnName(keys, b.GetRule_column_name2()); @@ -776,7 +771,7 @@ TSourcePtr TSqlSelect::ProcessCore(const TRule_process_core& node, const TWriteS } if (node.GetBlock4().size()) { TVector<TSourcePtr> sources(1, source); - for (auto& s: node.GetBlock4()) { + for (auto& s : node.GetBlock4()) { sources.push_back(NamedSingleSource(s.GetRule_named_single_source2(), unorderedSubquery)); if (!sources.back()) { return nullptr; @@ -822,7 +817,7 @@ TSourcePtr TSqlSelect::ProcessCore(const TRule_process_core& node, const TWriteS } auto args = call.GetArgs(); - for (auto& arg: args) { + for (auto& arg : args) { if (/* auto placeholder = */ dynamic_cast<TTableRows*>(arg.Get())) { if (listCall) { Ctx_.Error() << "Only one TableRows() argument is allowed."; @@ -850,8 +845,9 @@ TSourcePtr TSqlSelect::ProcessCore(const TRule_process_core& node, const TWriteS return {}; } args = finalCall.GetArgs(); - if (call.IsExternal()) + if (call.IsExternal()) { listCall = true; + } if (block5.HasBlock3()) { with->SetLabel(Id(block5.GetBlock3().GetRule_an_id2(), *this)); @@ -889,7 +885,7 @@ TSourcePtr TSqlSelect::ReduceCore(const TRule_reduce_core& node, const TWriteSet } if (node.GetBlock3().size()) { TVector<TSourcePtr> sources(1, source); - for (auto& s: node.GetBlock3()) { + for (auto& s : node.GetBlock3()) { sources.push_back(NamedSingleSource(s.GetRule_named_single_source2(), true)); if (!sources.back()) { return nullptr; @@ -945,7 +941,7 @@ TSourcePtr TSqlSelect::ReduceCore(const TRule_reduce_core& node, const TWriteSet } auto args = call.GetArgs(); - for (auto& arg: args) { + for (auto& arg : args) { if (/* auto placeholder = */ dynamic_cast<TTableRows*>(arg.Get())) { if (listCall) { Ctx_.Error() << "Only one TableRows() argument is allowed."; @@ -977,11 +973,11 @@ TSourcePtr TSqlSelect::ReduceCore(const TRule_reduce_core& node, const TWriteSet } return BuildReduce(startPos, reduceMode, std::move(source), std::move(orderBy), std::move(keys), std::move(args), udf, having, - settings, assumeOrderBy, listCall); + settings, assumeOrderBy, listCall); } TSourcePtr TSqlSelect::SelectCore(const TRule_select_core& node, const TWriteSettings& settings, TPosition& selectPos, - TMaybe<TSelectKindPlacement> placement, TVector<TSortSpecificationPtr>& selectOpOrderBy, bool& selectOpAssumeOrderBy) + TMaybe<TSelectKindPlacement> placement, TVector<TSortSpecificationPtr>& selectOpOrderBy, bool& selectOpAssumeOrderBy) { // (FROM join_source)? SELECT STREAM? opt_set_quantifier result_column (COMMA result_column)* COMMA? (WITHOUT column_list)? (FROM join_source)? (WHERE expr)? // group_by_clause? (HAVING expr)? window_clause? ext_order_by_clause? @@ -1001,15 +997,15 @@ TSourcePtr TSqlSelect::SelectCore(const TRule_select_core& node, const TWriteSet const auto hints = Ctx_.PullHintForToken(selectPos); TColumnsSets uniqueSets, distinctSets; for (const auto& hint : hints) { - if (const auto& name = to_lower(hint.Name); name == "unique") + if (const auto& name = to_lower(hint.Name); name == "unique") { uniqueSets.insert_unique(NSorted::TSimpleSet<TString>(hint.Values.cbegin(), hint.Values.cend())); - else if (name == "distinct") { + } else if (name == "distinct") { uniqueSets.insert_unique(NSorted::TSimpleSet<TString>(hint.Values.cbegin(), hint.Values.cend())); distinctSets.insert_unique(NSorted::TSimpleSet<TString>(hint.Values.cbegin(), hint.Values.cend())); } else { if (!Ctx_.Warning(hint.Pos, TIssuesIds::YQL_UNUSED_HINT, [&](auto& out) { - out << "Hint " << hint.Name << " will not be used"; - })) { + out << "Hint " << hint.Name << " will not be used"; + })) { return nullptr; } } @@ -1078,7 +1074,7 @@ TSourcePtr TSqlSelect::SelectCore(const TRule_select_core& node, const TWriteSet return nullptr; } bool hasHopping = (bool)clause.GetLegacyHoppingWindow(); - for (const auto& exprAlias: clause.Aliases()) { + for (const auto& exprAlias : clause.Aliases()) { YQL_ENSURE(exprAlias.first == exprAlias.second->GetLabel()); groupByExpr.emplace_back(exprAlias.second); hasHopping |= (bool)dynamic_cast<THoppingWindow*>(exprAlias.second.Get()); @@ -1139,9 +1135,8 @@ TSourcePtr TSqlSelect::SelectCore(const TRule_select_core& node, const TWriteSet return nullptr; } Ctx_.IncrementMonCounter("sql_features", IsColumnsOnly(orderBy) - ? (assumeSorted ? "AssumeOrderBy" : "OrderBy") - : (assumeSorted ? "AssumeOrderByExpr" : "OrderByExpr") - ); + ? (assumeSorted ? "AssumeOrderBy" : "OrderBy") + : (assumeSorted ? "AssumeOrderByExpr" : "OrderByExpr")); if (!NeedPassLimitOrderByToUnderlyingSelect(placement)) { selectOpOrderBy.swap(orderBy); @@ -1161,27 +1156,26 @@ TSourcePtr TSqlSelect::SelectCore(const TRule_select_core& node, const TWriteSet ~TScopedWinSpecs() { Ctx_.WinSpecsScopes.pop_back(); } + private: TContext& Ctx_; }; - TScopedWinSpecs scoped(Ctx_, windowSpec); if (!SelectTerm(terms, node.GetRule_result_column5())) { return nullptr; } - for (auto block: node.GetBlock6()) { + for (auto block : node.GetBlock6()) { if (!SelectTerm(terms, block.GetRule_result_column2())) { return nullptr; } } - } if (!ValidateSelectColumns(terms)) { return nullptr; } return BuildSelectCore(Ctx_, startPos, std::move(source), groupByExpr, groupBy, compactGroupBy, groupBySuffix, assumeSorted, orderBy, having, - std::move(windowSpec), legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); + std::move(windowSpec), legacyHoppingWindowSpec, std::move(terms), distinct, std::move(without), forceWithout, selectStream, settings, std::move(uniqueSets), std::move(distinctSets)); } bool TSqlSelect::WindowDefinition(const TRule_window_definition& rule, TWinSpecs& winSpecs) { @@ -1203,7 +1197,7 @@ bool TSqlSelect::WindowClause(const TRule_window_clause& rule, TWinSpecs& winSpe if (!WindowDefinition(windowList.GetRule_window_definition1(), winSpecs)) { return false; } - for (auto& block: windowList.GetBlock2()) { + for (auto& block : windowList.GetBlock2()) { if (!WindowDefinition(block.GetRule_window_definition2(), winSpecs)) { return false; } @@ -1233,7 +1227,7 @@ bool TSqlSelect::NeedPassLimitOrderByToUnderlyingSelect(TMaybe<TSelectKindPlacem } TSqlSelect::TSelectKindResult TSqlSelect::SelectKind(const TRule_select_kind_partial& node, TPosition& selectPos, - TMaybe<TSelectKindPlacement> placement) + TMaybe<TSelectKindPlacement> placement) { auto res = SelectKind(node.GetRule_select_kind1(), selectPos, placement); if (!res) { @@ -1255,7 +1249,7 @@ TSqlSelect::TSelectKindResult TSqlSelect::SelectKind(const TRule_select_kind_par TSqlExpression takeExpr(Ctx_, Mode_); auto take = takeExpr.Build(block.GetRule_expr2()); if (!take) { - return{}; + return {}; } TNodePtr skip; @@ -1289,7 +1283,7 @@ TSqlSelect::TSelectKindResult TSqlSelect::SelectKind(const TRule_select_kind_par } TSqlSelect::TSelectKindResult TSqlSelect::SelectKind(const TRule_select_kind& node, TPosition& selectPos, - TMaybe<TSelectKindPlacement> placement) + TMaybe<TSelectKindPlacement> placement) { const bool discard = node.HasBlock1(); const bool hasLabel = node.HasBlock3(); @@ -1343,7 +1337,7 @@ TSqlSelect::TSelectKindResult TSqlSelect::SelectKind(const TRule_select_kind& no break; case TRule_select_kind_TBlock2::kAlt3: { res.Source = SelectCore(node.GetBlock2().GetAlt3().GetRule_select_core1(), settings, selectPos, - placement, res.SelectOpOrderBy, res.SelectOpAssumeOrderBy); + placement, res.SelectOpOrderBy, res.SelectOpAssumeOrderBy); break; } case TRule_select_kind_TBlock2::ALT_NOT_SET: @@ -1354,7 +1348,7 @@ TSqlSelect::TSelectKindResult TSqlSelect::SelectKind(const TRule_select_kind& no } TSqlSelect::TSelectKindResult TSqlSelect::SelectKind(const TRule_select_kind_parenthesis& node, TPosition& selectPos, - TMaybe<TSelectKindPlacement> placement) + TMaybe<TSelectKindPlacement> placement) { if (node.Alt_case() == TRule_select_kind_parenthesis::kAltSelectKindParenthesis1) { return SelectKind(node.GetAlt_select_kind_parenthesis1().GetRule_select_kind_partial1(), selectPos, placement); @@ -1429,11 +1423,11 @@ TSourcePtr TSqlSelect::BuildStmt(TSourcePtr result, TBuildExtra extra) { YQL_ENSURE(!orderBy.empty()); if (!Ctx_.Warning(orderBy[0]->OrderExpr->GetPos(), TIssuesIds::WARNING, [](auto& out) { - out << "ASSUME ORDER BY is used, " - << "but UNION, INTERSECT and EXCEPT " - << "operators have no ordering guarantees, " - << "therefore consider using ORDER BY"; - })) { + out << "ASSUME ORDER BY is used, " + << "but UNION, INTERSECT and EXCEPT " + << "operators have no ordering guarantees, " + << "therefore consider using ORDER BY"; + })) { return nullptr; } } @@ -1455,8 +1449,8 @@ TSourcePtr TSqlSelect::BuildStmt(TSourcePtr result, TBuildExtra extra) { terms.push_back(BuildColumn(pos, "*", "")); result = BuildSelectCore(Ctx_, pos, std::move(result), groupByExpr, groupBy, compactGroupBy, groupBySuffix, - assumeOrderBy, orderBy, having, std::move(winSpecs), legacyHoppingWindowSpec, std::move(terms), - distinct, std::move(without), forceWithout, stream, outermostSettings, {}, {}); + assumeOrderBy, orderBy, having, std::move(winSpecs), legacyHoppingWindowSpec, std::move(terms), + distinct, std::move(without), forceWithout, stream, outermostSettings, {}, {}); result = BuildSelect(pos, std::move(result), skipTake); } else if (skipTake) { @@ -1653,17 +1647,17 @@ TSqlSelect::TSelectKindResult TSqlSelect::BuildAtom( TSqlSelect::TSelectKindResult result; if constexpr (std::is_same_v<TRule, TRule_select_or_expr>) { switch (node.Alt_case()) { - case NSQLv1Generated::TRule_select_or_expr::kAltSelectOrExpr1: { - const auto& select_kind = node.GetAlt_select_or_expr1().GetRule_select_kind_partial1(); - result = SelectKind(select_kind, pos, placement); - break; - } - case NSQLv1Generated::TRule_select_or_expr::kAltSelectOrExpr2: { - result.Source = TSqlExpression(Ctx_, Mode_).BuildSource(node); - break; - } - case NSQLv1Generated::TRule_select_or_expr::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case NSQLv1Generated::TRule_select_or_expr::kAltSelectOrExpr1: { + const auto& select_kind = node.GetAlt_select_or_expr1().GetRule_select_kind_partial1(); + result = SelectKind(select_kind, pos, placement); + break; + } + case NSQLv1Generated::TRule_select_or_expr::kAltSelectOrExpr2: { + result.Source = TSqlExpression(Ctx_, Mode_).BuildSource(node); + break; + } + case NSQLv1Generated::TRule_select_or_expr::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } } else if (placement.IsFirstInSelectOp && placement.IsLastInSelectOp) { result = SelectKind(node, pos, /* placement = */ Nothing()); diff --git a/yql/essentials/sql/v1/sql_select.h b/yql/essentials/sql/v1/sql_select.h index 9bd553d49ab..65b5c66f6bd 100644 --- a/yql/essentials/sql/v1/sql_select.h +++ b/yql/essentials/sql/v1/sql_select.h @@ -24,7 +24,7 @@ private: bool ValidateSelectColumns(const TVector<TNodePtr>& terms); bool ColumnName(TVector<TNodePtr>& keys, const TRule_column_name& node); bool ColumnName(TVector<TNodePtr>& keys, const TRule_without_column_name& node); - template<typename TRule> + template <typename TRule> bool ColumnList(TVector<TNodePtr>& keys, const TRule& node); bool NamedColumn(TVector<TNodePtr>& columnList, const TRule_named_column& node); TSourcePtr SingleSource(const TRule_single_source& node, const TVector<TString>& derivedColumns, TPosition derivedColumnsPos, bool unorderedSubquery); @@ -43,7 +43,7 @@ private: }; TSourcePtr SelectCore(const TRule_select_core& node, const TWriteSettings& settings, TPosition& selectPos, - TMaybe<TSelectKindPlacement> placement, TVector<TSortSpecificationPtr>& selectOpOrederBy, bool& selectOpAssumeOrderBy); + TMaybe<TSelectKindPlacement> placement, TVector<TSortSpecificationPtr>& selectOpOrederBy, bool& selectOpAssumeOrderBy); bool WindowDefinition(const TRule_window_definition& node, TWinSpecs& winSpecs); bool WindowClause(const TRule_window_clause& node, TWinSpecs& winSpecs); @@ -108,4 +108,4 @@ private: TSelectKindResult SelectKind(const TRule_select_kind_parenthesis& node, TPosition& selectPos, TMaybe<TSelectKindPlacement> placement); }; -} //namespace NSQLTranslationV1 +} // namespace NSQLTranslationV1 diff --git a/yql/essentials/sql/v1/sql_translation.cpp b/yql/essentials/sql/v1/sql_translation.cpp index 8675f9e1308..8b8f8211691 100644 --- a/yql/essentials/sql/v1/sql_translation.cpp +++ b/yql/essentials/sql/v1/sql_translation.cpp @@ -79,7 +79,8 @@ public: TModeGuard(ESqlMode& mode, ESqlMode newMode) : Mode_(mode) , OriginalMode_(std::exchange(mode, newMode)) - {} + { + } ~TModeGuard() { Mode_ = OriginalMode_; @@ -99,11 +100,10 @@ TNodePtr BuildViewSelect(const TRule_select_stmt& selectStatement, TContext& con source, false, /* write result */ false, /* in subquery */ - context.Scoped - ); + context.Scoped); } -} +} // namespace namespace NSQLTranslationV1 { @@ -191,16 +191,16 @@ TString Id(const TRule_an_id_as_compat& node, TTranslation& ctx) { } TString Id(const TRule_id_schema& node, TTranslation& ctx) { - //id_schema: - // identifier - // | keyword_compat - // | keyword_expr_uncompat - // // | keyword_table_uncompat - // | keyword_select_uncompat - // // | keyword_alter_uncompat - // | keyword_in_uncompat - // | keyword_window_uncompat - // | keyword_hint_uncompat + // id_schema: + // identifier + // | keyword_compat + // | keyword_expr_uncompat + // // | keyword_table_uncompat + // | keyword_select_uncompat + // // | keyword_alter_uncompat + // | keyword_in_uncompat + // | keyword_window_uncompat + // | keyword_hint_uncompat //; switch (node.Alt_case()) { case TRule_id_schema::kAltIdSchema1: @@ -236,20 +236,20 @@ TString Id(const TRule_an_id_or_type& node, TTranslation& ctx) { std::pair<bool, TString> Id(const TRule_id_or_at& node, TTranslation& ctx) { bool hasAt = node.HasBlock1(); - return std::make_pair(hasAt, Id(node.GetRule_an_id_or_type2(), ctx) ); + return std::make_pair(hasAt, Id(node.GetRule_an_id_or_type2(), ctx)); } TString Id(const TRule_id_table& node, TTranslation& ctx) { - //id_table: - // identifier - // | keyword_compat - // | keyword_expr_uncompat - // // | keyword_table_uncompat - // | keyword_select_uncompat - // // | keyword_alter_uncompat - // | keyword_in_uncompat - // | keyword_window_uncompat - // | keyword_hint_uncompat + // id_table: + // identifier + // | keyword_compat + // | keyword_expr_uncompat + // // | keyword_table_uncompat + // | keyword_select_uncompat + // // | keyword_alter_uncompat + // | keyword_in_uncompat + // | keyword_window_uncompat + // | keyword_hint_uncompat //; switch (node.Alt_case()) { case TRule_id_table::kAltIdTable1: @@ -295,16 +295,16 @@ TString Id(const TRule_id_table_or_type& node, TTranslation& ctx) { } TString Id(const TRule_id_expr& node, TTranslation& ctx) { - //id_expr: - // identifier - // | keyword_compat - // // | keyword_expr_uncompat - // // | keyword_table_uncompat - // // | keyword_select_uncompat - // | keyword_alter_uncompat - // | keyword_in_uncompat - // | keyword_window_uncompat - // | keyword_hint_uncompat + // id_expr: + // identifier + // | keyword_compat + // // | keyword_expr_uncompat + // // | keyword_table_uncompat + // // | keyword_select_uncompat + // | keyword_alter_uncompat + // | keyword_in_uncompat + // | keyword_window_uncompat + // | keyword_hint_uncompat //; switch (node.Alt_case()) { case TRule_id_expr::kAltIdExpr1: @@ -334,16 +334,16 @@ bool IsQuotedId(const TRule_id_expr& node, TTranslation& ctx) { } TString Id(const TRule_id_expr_in& node, TTranslation& ctx) { - //id_expr_in: - // identifier - // | keyword_compat - // // | keyword_expr_uncompat - // // | keyword_table_uncompat - // // | keyword_select_uncompat - // | keyword_alter_uncompat - // // | keyword_in_uncompat - // | keyword_window_uncompat - // | keyword_hint_uncompat + // id_expr_in: + // identifier + // | keyword_compat + // // | keyword_expr_uncompat + // // | keyword_table_uncompat + // // | keyword_select_uncompat + // | keyword_alter_uncompat + // // | keyword_in_uncompat + // | keyword_window_uncompat + // | keyword_hint_uncompat //; switch (node.Alt_case()) { case TRule_id_expr_in::kAltIdExprIn1: @@ -362,16 +362,16 @@ TString Id(const TRule_id_expr_in& node, TTranslation& ctx) { } TString Id(const TRule_id_window& node, TTranslation& ctx) { - //id_window: - // identifier - // | keyword_compat - // | keyword_expr_uncompat - // | keyword_table_uncompat - // | keyword_select_uncompat - // | keyword_alter_uncompat - // | keyword_in_uncompat - // // | keyword_window_uncompat - // | keyword_hint_uncompat + // id_window: + // identifier + // | keyword_compat + // | keyword_expr_uncompat + // | keyword_table_uncompat + // | keyword_select_uncompat + // | keyword_alter_uncompat + // | keyword_in_uncompat + // // | keyword_window_uncompat + // | keyword_hint_uncompat //; switch (node.Alt_case()) { case TRule_id_window::kAltIdWindow1: @@ -396,16 +396,16 @@ TString Id(const TRule_id_window& node, TTranslation& ctx) { } TString Id(const TRule_id_without& node, TTranslation& ctx) { - //id_without: - // identifier - // | keyword_compat - // // | keyword_expr_uncompat - // | keyword_table_uncompat - // // | keyword_select_uncompat - // | keyword_alter_uncompat - // | keyword_in_uncompat - // | keyword_window_uncompat - // | keyword_hint_uncompat + // id_without: + // identifier + // | keyword_compat + // // | keyword_expr_uncompat + // | keyword_table_uncompat + // // | keyword_select_uncompat + // | keyword_alter_uncompat + // | keyword_in_uncompat + // | keyword_window_uncompat + // | keyword_hint_uncompat //; switch (node.Alt_case()) { case TRule_id_without::kAltIdWithout1: @@ -428,16 +428,16 @@ TString Id(const TRule_id_without& node, TTranslation& ctx) { } TString Id(const TRule_id_hint& node, TTranslation& ctx) { - //id_hint: - // identifier - // | keyword_compat - // | keyword_expr_uncompat - // | keyword_table_uncompat - // | keyword_select_uncompat - // | keyword_alter_uncompat - // | keyword_in_uncompat - // | keyword_window_uncompat - // // | keyword_hint_uncompat + // id_hint: + // identifier + // | keyword_compat + // | keyword_expr_uncompat + // | keyword_table_uncompat + // | keyword_select_uncompat + // | keyword_alter_uncompat + // | keyword_in_uncompat + // | keyword_window_uncompat + // // | keyword_hint_uncompat //; switch (node.Alt_case()) { case TRule_id_hint::kAltIdHint1: @@ -598,7 +598,7 @@ TString OptIdPrefixAsStr(const TRule_opt_id_prefix_or_type& node, TTranslation& void PureColumnListStr(const TRule_pure_column_list& node, TTranslation& ctx, TVector<TString>& outList) { outList.push_back(Id(node.GetRule_an_id2(), ctx)); - for (auto& block: node.GetBlock3()) { + for (auto& block : node.GetBlock3()) { outList.push_back(Id(block.GetRule_an_id2(), ctx)); } } @@ -615,23 +615,23 @@ bool NamedNodeImpl(const TRule_opt_bind_parameter& node, TString& name, bool& is TDeferredAtom PureColumnOrNamed(const TRule_pure_column_or_named& node, TTranslation& ctx) { switch (node.Alt_case()) { - case TRule_pure_column_or_named::kAltPureColumnOrNamed1: { - TString named; - if (!NamedNodeImpl(node.GetAlt_pure_column_or_named1().GetRule_bind_parameter1(), named, ctx)) { - return {}; - } - auto namedNode = ctx.GetNamedNode(named); - if (!namedNode) { - return {}; - } + case TRule_pure_column_or_named::kAltPureColumnOrNamed1: { + TString named; + if (!NamedNodeImpl(node.GetAlt_pure_column_or_named1().GetRule_bind_parameter1(), named, ctx)) { + return {}; + } + auto namedNode = ctx.GetNamedNode(named); + if (!namedNode) { + return {}; + } - return TDeferredAtom(namedNode, ctx.Context()); - } + return TDeferredAtom(namedNode, ctx.Context()); + } - case TRule_pure_column_or_named::kAltPureColumnOrNamed2: - return TDeferredAtom(ctx.Context().Pos(), Id(node.GetAlt_pure_column_or_named2().GetRule_an_id1(), ctx)); - case TRule_pure_column_or_named::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_pure_column_or_named::kAltPureColumnOrNamed2: + return TDeferredAtom(ctx.Context().Pos(), Id(node.GetAlt_pure_column_or_named2().GetRule_an_id1(), ctx)); + case TRule_pure_column_or_named::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } } @@ -687,8 +687,7 @@ bool TSqlTranslation::CreateTableIndex(const TRule_table_index& node, TVector<TI } indexes.back().Type = TIndexDescription::EType::GlobalAsync; } - } - break; + } break; // "LOCAL" case TRule_table_index_type_TBlock1::kAlt2: AltNotImplemented("local", indexType); @@ -698,7 +697,7 @@ bool TSqlTranslation::CreateTableIndex(const TRule_table_index& node, TVector<TI } if (node.GetRule_table_index_type3().HasBlock2()) { - const TString subType = to_upper(IdEx(node.GetRule_table_index_type3().GetBlock2().GetRule_index_subtype2().GetRule_an_id1(), *this).Name) ; + const TString subType = to_upper(IdEx(node.GetRule_table_index_type3().GetBlock2().GetRule_index_subtype2().GetRule_an_id1(), *this).Name); if (subType == "VECTOR_KMEANS_TREE" || subType == "FULLTEXT") { if (indexes.back().Type != TIndexDescription::EType::GlobalSync) { Ctx_.Error() << subType << " index can only be GLOBAL [SYNC]"; @@ -720,7 +719,7 @@ bool TSqlTranslation::CreateTableIndex(const TRule_table_index& node, TVector<TI // WITH if (node.HasBlock10()) { - //const auto& with = node.GetBlock4(); + // const auto& with = node.GetBlock4(); auto& index = indexes.back(); if (index.Type == TIndexDescription::EType::GlobalVectorKmeansTree || index.Type == TIndexDescription::EType::GlobalFulltext) { if (!FillIndexSettings(node.GetBlock10().GetRule_with_index_settings1(), index.IndexSettings)) { @@ -812,7 +811,7 @@ TNodePtr ParseDatabaseSettingValue(TContext& ctx, const TRule_database_setting_v } } -} +} // namespace bool TSqlTranslation::ParseDatabaseSetting(const TRule_database_setting& in, THashMap<TString, TNodePtr>& out) { const auto setting = to_upper(Id(in.GetRule_an_id1(), *this)); @@ -831,7 +830,7 @@ bool TSqlTranslation::ParseDatabaseSetting(const TRule_database_setting& in, THa } bool TSqlTranslation::FillIndexSettings(const TRule_with_index_settings& settingsNode, - TIndexDescription::TIndexSettings& indexSettings) { + TIndexDescription::TIndexSettings& indexSettings) { const auto& firstEntry = settingsNode.GetRule_index_setting_entry3(); if (!AddIndexSetting(IdEx(firstEntry.GetRule_an_id1(), *this), firstEntry.GetRule_index_setting_value3(), indexSettings)) { return false; @@ -863,20 +862,18 @@ TString TSqlTranslation::GetIndexSettingStringValue(const TRule_index_setting_va } } -bool TSqlTranslation::AddIndexSetting(const TIdentifier &id, - const TRule_index_setting_value& node, - TIndexDescription::TIndexSettings& indexSettings) { - +bool TSqlTranslation::AddIndexSetting(const TIdentifier& id, + const TRule_index_setting_value& node, + TIndexDescription::TIndexSettings& indexSettings) { // TODO: remove to_lower transformation after the next release to keep backward compatibility const auto name = to_lower(id.Name); const auto value = to_lower(GetIndexSettingStringValue(node)); - TIndexDescription::TIndexSetting indexSetting { + TIndexDescription::TIndexSetting indexSetting{ .Name = name, .NamePosition = id.Pos, .Value = value, - .ValuePosition = Ctx_.Pos() - }; + .ValuePosition = Ctx_.Pos()}; if (!indexSettings.emplace(name, indexSetting).second) { Ctx_.Error() << "Duplicated " << name; @@ -884,7 +881,6 @@ bool TSqlTranslation::AddIndexSetting(const TIdentifier &id, } return true; - } std::pair<TString, TViewDescription> TableKeyImpl(const std::pair<bool, TString>& nameWithAt, TViewDescription view, TTranslation& ctx) { @@ -982,7 +978,7 @@ bool TSqlTranslation::NamedExprList(const TRule_named_expr_list& node, TVector<T if (!exprs.back()) { return false; } - for (auto& b: node.GetBlock2()) { + for (auto& b : node.GetBlock2()) { exprs.emplace_back(NamedExpr(b.GetRule_named_expr2(), exprMode)); if (!exprs.back()) { return false; @@ -1000,7 +996,7 @@ bool TSqlTranslation::BindList(const TRule_bind_parameter_list& node, TVector<TS } bindNames.emplace_back(TSymbolNameWithPos{name, Ctx_.Pos()}); - for (auto& b: node.GetBlock2()) { + for (auto& b : node.GetBlock2()) { if (!NamedNodeImpl(b.GetRule_bind_parameter2(), name, *this)) { return false; } @@ -1025,7 +1021,7 @@ bool TSqlTranslation::ActionOrSubqueryArgs(const TRule_action_or_subquery_args& } bindNames.emplace_back(TSymbolNameWithPos{name, Ctx_.Pos()}); - for (auto& b: node.GetBlock2()) { + for (auto& b : node.GetBlock2()) { if (!NamedNodeImpl(b.GetRule_opt_bind_parameter2(), name, isOptional, *this)) { return false; } @@ -1046,14 +1042,14 @@ bool TSqlTranslation::ModulePath(const TRule_module_path& node, TVector<TString> path.emplace_back(TString()); } path.emplace_back(Id(node.GetRule_an_id2(), *this)); - for (auto& b: node.GetBlock3()) { + for (auto& b : node.GetBlock3()) { path.emplace_back(Id(b.GetRule_an_id2(), *this)); } return true; } bool TSqlTranslation::NamedBindList(const TRule_named_bind_parameter_list& node, TVector<TSymbolNameWithPos>& names, - TVector<TSymbolNameWithPos>& aliases) + TVector<TSymbolNameWithPos>& aliases) { names.clear(); aliases.clear(); @@ -1066,7 +1062,7 @@ bool TSqlTranslation::NamedBindList(const TRule_named_bind_parameter_list& node, names.push_back(name); aliases.push_back(alias); - for (auto& b: node.GetBlock2()) { + for (auto& b : node.GetBlock2()) { if (!NamedBindParam(b.GetRule_named_bind_parameter2(), name, alias)) { return false; } @@ -1121,7 +1117,7 @@ bool TSqlTranslation::ClusterExprOrBinding(const TRule_cluster_expr& node, TStri } bool TSqlTranslation::ClusterExpr(const TRule_cluster_expr& node, bool allowWildcard, bool allowBinding, TString& service, - TDeferredAtom& cluster, bool& isBinding) + TDeferredAtom& cluster, bool& isBinding) { service = ""; cluster = TDeferredAtom(); @@ -1138,82 +1134,81 @@ bool TSqlTranslation::ClusterExpr(const TRule_cluster_expr& node, bool allowWild } switch (node.GetBlock2().Alt_case()) { - case TRule_cluster_expr::TBlock2::kAlt1: { - auto value = PureColumnOrNamed(node.GetBlock2().GetAlt1().GetRule_pure_column_or_named1(), *this); - if (value.Empty()) { - return false; - } + case TRule_cluster_expr::TBlock2::kAlt1: { + auto value = PureColumnOrNamed(node.GetBlock2().GetAlt1().GetRule_pure_column_or_named1(), *this); + if (value.Empty()) { + return false; + } - if (value.GetLiteral()) { - TString clusterName = *value.GetLiteral(); - if (allowBinding && to_lower(clusterName) == "bindings") { - switch (Ctx_.Settings.BindingsMode) { - case NSQLTranslation::EBindingsMode::DISABLED: - Ctx_.Error(Ctx_.Pos(), TIssuesIds::YQL_DISABLED_BINDINGS) << "Please remove 'bindings.' from your query, the support for this syntax has ended"; - Ctx_.IncrementMonCounter("sql_errors", "DisabledBinding"); - return false; - case NSQLTranslation::EBindingsMode::ENABLED: - isBinding = true; - break; - case NSQLTranslation::EBindingsMode::DROP_WITH_WARNING: - if (!Ctx_.Warning(Ctx_.Pos(), TIssuesIds::YQL_DEPRECATED_BINDINGS, [](auto& out) { - out << "Please remove 'bindings.' from your query, " - << "the support for this syntax will be dropped soon"; - })) { - return false; + if (value.GetLiteral()) { + TString clusterName = *value.GetLiteral(); + if (allowBinding && to_lower(clusterName) == "bindings") { + switch (Ctx_.Settings.BindingsMode) { + case NSQLTranslation::EBindingsMode::DISABLED: + Ctx_.Error(Ctx_.Pos(), TIssuesIds::YQL_DISABLED_BINDINGS) << "Please remove 'bindings.' from your query, the support for this syntax has ended"; + Ctx_.IncrementMonCounter("sql_errors", "DisabledBinding"); + return false; + case NSQLTranslation::EBindingsMode::ENABLED: + isBinding = true; + break; + case NSQLTranslation::EBindingsMode::DROP_WITH_WARNING: + if (!Ctx_.Warning(Ctx_.Pos(), TIssuesIds::YQL_DEPRECATED_BINDINGS, [](auto& out) { + out << "Please remove 'bindings.' from your query, " + << "the support for this syntax will be dropped soon"; + })) { + return false; + } + Ctx_.IncrementMonCounter("sql_errors", "DeprecatedBinding"); + [[fallthrough]]; + case NSQLTranslation::EBindingsMode::DROP: + service = Context().Scoped->CurrService; + cluster = Context().Scoped->CurrCluster; + break; } - Ctx_.IncrementMonCounter("sql_errors", "DeprecatedBinding"); - [[fallthrough]]; - case NSQLTranslation::EBindingsMode::DROP: - service = Context().Scoped->CurrService; - cluster = Context().Scoped->CurrCluster; - break; + + return true; + } + TString normalizedClusterName; + auto foundProvider = Ctx_.GetClusterProvider(clusterName, normalizedClusterName); + if (!foundProvider) { + Ctx_.Error() << "Unknown cluster: " << clusterName; + return false; } - return true; - } - TString normalizedClusterName; - auto foundProvider = Ctx_.GetClusterProvider(clusterName, normalizedClusterName); - if (!foundProvider) { - Ctx_.Error() << "Unknown cluster: " << clusterName; - return false; - } + if (service && *foundProvider != service) { + Ctx_.Error() << "Mismatch of cluster " << clusterName << " service, expected: " + << *foundProvider << ", got: " << service; + return false; + } - if (service && *foundProvider != service) { - Ctx_.Error() << "Mismatch of cluster " << clusterName << " service, expected: " - << *foundProvider << ", got: " << service; - return false; - } + if (!service) { + service = *foundProvider; + } - if (!service) { - service = *foundProvider; + value = TDeferredAtom(Ctx_.Pos(), normalizedClusterName); + } else { + if (!service) { + Ctx_.Error() << "Cluster service is not set"; + return false; + } } - value = TDeferredAtom(Ctx_.Pos(), normalizedClusterName); - } else { - if (!service) { - Ctx_.Error() << "Cluster service is not set"; + cluster = value; + return true; + } + case TRule_cluster_expr::TBlock2::kAlt2: { + if (!allowWildcard) { + Ctx_.Error() << "Cluster wildcards allowed only in USE statement"; return false; } - } - cluster = value; - return true; - } - case TRule_cluster_expr::TBlock2::kAlt2: { - if (!allowWildcard) { - Ctx_.Error() << "Cluster wildcards allowed only in USE statement"; - return false; + return true; } - - return true; - } - case TRule_cluster_expr::TBlock2::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_cluster_expr::TBlock2::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } } - bool TSqlTranslation::ApplyTableBinding(const TString& binding, TTableRef& tr, TTableHints& hints) { NSQLTranslation::TBindingInfo bindingInfo; if (const auto& error = ExtractBindingInfo(Context().Settings, binding, bindingInfo)) { @@ -1224,10 +1219,10 @@ bool TSqlTranslation::ApplyTableBinding(const TString& binding, TTableRef& tr, T if (bindingInfo.Schema) { TNodePtr schema = BuildQuotedAtom(Ctx_.Pos(), bindingInfo.Schema); - TNodePtr type = new TCallNodeImpl(Ctx_.Pos(), "SqlTypeFromYson", { schema }); - TNodePtr columns = new TCallNodeImpl(Ctx_.Pos(), "SqlColumnOrderFromYson", { schema }); + TNodePtr type = new TCallNodeImpl(Ctx_.Pos(), "SqlTypeFromYson", {schema}); + TNodePtr columns = new TCallNodeImpl(Ctx_.Pos(), "SqlColumnOrderFromYson", {schema}); - hints["user_schema"] = { type, columns }; + hints["user_schema"] = {type, columns}; } for (auto& [key, values] : bindingInfo.Attributes) { @@ -1263,8 +1258,7 @@ bool TSqlTranslation::TableRefImpl(const TRule_table_ref& node, TTableRef& resul bool isBinding = false; if (node.HasBlock1()) { const auto& clusterExpr = node.GetBlock1().GetRule_cluster_expr1(); - bool result = !hasAt ? - ClusterExprOrBinding(clusterExpr, service, cluster, isBinding) : ClusterExpr(clusterExpr, false, service, cluster); + bool result = !hasAt ? ClusterExprOrBinding(clusterExpr, service, cluster, isBinding) : ClusterExpr(clusterExpr, false, service, cluster); if (!result) { return false; } @@ -1398,7 +1392,7 @@ bool TSqlTranslation::TableRefImpl(const TRule_table_ref& node, TTableRef& resul TNodePtr apply = new TAstListNodeImpl(Ctx_.Pos(), std::move(values)); if (unorderedSubquery && Ctx_.UnorderedSubqueries) { - apply = new TCallNodeImpl(Ctx_.Pos(), "UnorderedSubquery", { apply }); + apply = new TCallNodeImpl(Ctx_.Pos(), "UnorderedSubquery", {apply}); } result.Source = BuildNodeSource(Ctx_.Pos(), apply); return true; @@ -1411,8 +1405,8 @@ bool TSqlTranslation::TableRefImpl(const TRule_table_ref& node, TTableRef& resul auto view = Id(alt.GetBlock3().GetRule_view_name2(), *this); Ctx_.IncrementMonCounter("sql_features", "View"); bool result = view.PrimaryFlag - ? ret->SetPrimaryView(Ctx_, Ctx_.Pos()) - : ret->SetViewName(Ctx_, Ctx_.Pos(), view.ViewName); + ? ret->SetPrimaryView(Ctx_, Ctx_.Pos()) + : ret->SetViewName(Ctx_, Ctx_.Pos(), view.ViewName); if (!result) { return false; } @@ -1559,7 +1553,6 @@ TMaybe<TColumnOptions> ColumnOptions(const TRule_column_schema& node, TTranslati Y_ABORT("You should change implementation according to grammar changes"); } } - } { @@ -1612,8 +1605,8 @@ TMaybe<TColumnOptions> ColumnOptions(const TRule_column_schema& node, TTranslati defaultExpr = expr.Build(rule.GetAlt_column_option3().GetRule_default_value1().GetRule_expr2()); if (AnyOf(ctx.Context().Issues.begin(), ctx.Context().Issues.end(), [](const auto& issue) { - return issue.GetCode() == TIssuesIds::YQL_MISSING_IS_BEFORE_NOT_NULL; - })) { + return issue.GetCode() == TIssuesIds::YQL_MISSING_IS_BEFORE_NOT_NULL; + })) { ctx.Context().Error() << "'DEFAULT' option can not use expr which contains literall 'NOT NULL'." << " If you wanted to use two different options 'DEFAULT' and 'NOT NULL'," << " it is recommended to use the syntax '(DEFAULT value, NOT NULL, ...)'"; @@ -1632,7 +1625,6 @@ TMaybe<TColumnOptions> ColumnOptions(const TRule_column_schema& node, TTranslati } } } - } return TColumnOptions{std::move(defaultExpr), nullable, std::move(families)}; @@ -1666,8 +1658,7 @@ TMaybe<TColumnSchema> TSqlTranslation::ColumnSchemaImpl(const TRule_column_schem nullable, std::move(families), serial, - std::move(defaultExpr) - ); + std::move(defaultExpr)); } TNodePtr TSqlTranslation::SerialTypeNode(const TRule_type_name_or_bind& node) { @@ -1696,11 +1687,11 @@ TNodePtr TSqlTranslation::SerialTypeNode(const TRule_type_name_or_bind& node) { const auto res = to_lower(name); if (res == "bigserial" || res == "serial8") { - return new TCallNodeImpl(pos, "DataType", { BuildQuotedAtom(pos, "Int64", TNodeFlags::Default) }); + return new TCallNodeImpl(pos, "DataType", {BuildQuotedAtom(pos, "Int64", TNodeFlags::Default)}); } else if (res == "serial" || res == "serial4") { - return new TCallNodeImpl(pos, "DataType", { BuildQuotedAtom(pos, "Int32", TNodeFlags::Default) }); + return new TCallNodeImpl(pos, "DataType", {BuildQuotedAtom(pos, "Int32", TNodeFlags::Default)}); } else if (res == "smallserial" || res == "serial2") { - return new TCallNodeImpl(pos, "DataType", { BuildQuotedAtom(pos, "Int16", TNodeFlags::Default) }); + return new TCallNodeImpl(pos, "DataType", {BuildQuotedAtom(pos, "Int16", TNodeFlags::Default)}); } return nullptr; @@ -1787,13 +1778,10 @@ bool TSqlTranslation::FillFamilySettings(const TRule_family_settings& settingsNo return true; } - - bool TSqlTranslation::CreateTableEntry(const TRule_create_table_entry& node, TCreateTableParameters& params, const bool isCreateTableAs) { switch (node.Alt_case()) { - case TRule_create_table_entry::kAltCreateTableEntry1: - { + case TRule_create_table_entry::kAltCreateTableEntry1: { if (isCreateTableAs) { Ctx_.Error() << "Column types are not supported for CREATE TABLE AS"; return false; @@ -1810,8 +1798,7 @@ bool TSqlTranslation::CreateTableEntry(const TRule_create_table_entry& node, TCr params.Columns.push_back(*columnSchema); break; } - case TRule_create_table_entry::kAltCreateTableEntry2: - { + case TRule_create_table_entry::kAltCreateTableEntry2: { // table_constraint auto& constraint = node.GetAlt_create_table_entry2().GetRule_table_constraint1(); switch (constraint.Alt_case()) { @@ -1845,7 +1832,7 @@ bool TSqlTranslation::CreateTableEntry(const TRule_create_table_entry& node, TCr return false; } auto& obConstraint = constraint.GetAlt_table_constraint3(); - auto extractDirection = [this] (const TRule_column_order_by_specification& spec, bool& desc) { + auto extractDirection = [this](const TRule_column_order_by_specification& spec, bool& desc) { desc = false; if (!spec.HasBlock2()) { return true; @@ -1886,8 +1873,7 @@ bool TSqlTranslation::CreateTableEntry(const TRule_create_table_entry& node, TCr } break; } - case TRule_create_table_entry::kAltCreateTableEntry3: - { + case TRule_create_table_entry::kAltCreateTableEntry3: { // table_index auto& table_index = node.GetAlt_create_table_entry3().GetRule_table_index1(); if (!CreateTableIndex(table_index, params.Indexes)) { @@ -1895,8 +1881,7 @@ bool TSqlTranslation::CreateTableEntry(const TRule_create_table_entry& node, TCr } break; } - case TRule_create_table_entry::kAltCreateTableEntry4: - { + case TRule_create_table_entry::kAltCreateTableEntry4: { if (isCreateTableAs) { Ctx_.Error() << "Column families are not supported for CREATE TABLE AS"; return false; @@ -1910,8 +1895,7 @@ bool TSqlTranslation::CreateTableEntry(const TRule_create_table_entry& node, TCr params.ColumnFamilies.push_back(family); break; } - case TRule_create_table_entry::kAltCreateTableEntry5: - { + case TRule_create_table_entry::kAltCreateTableEntry5: { // changefeed auto& changefeed = node.GetAlt_create_table_entry5().GetRule_changefeed1(); TSqlExpression expr(Ctx_, Mode_); @@ -1920,8 +1904,7 @@ bool TSqlTranslation::CreateTableEntry(const TRule_create_table_entry& node, TCr } break; } - case TRule_create_table_entry::kAltCreateTableEntry6: - { + case TRule_create_table_entry::kAltCreateTableEntry6: { if (!isCreateTableAs) { Ctx_.Error() << "Column requires a type"; return false; @@ -1941,8 +1924,8 @@ bool TSqlTranslation::CreateTableEntry(const TRule_create_table_entry& node, TCr } namespace { - bool StoreId(const TRule_table_setting_value& from, TMaybe<TIdentifier>& to, TTranslation& ctx) { - switch (from.Alt_case()) { +bool StoreId(const TRule_table_setting_value& from, TMaybe<TIdentifier>& to, TTranslation& ctx) { + switch (from.Alt_case()) { case TRule_table_setting_value::kAltTableSettingValue1: { // id to = IdEx(from.GetAlt_table_setting_value1().GetRule_id1(), ctx); @@ -1950,12 +1933,12 @@ namespace { } default: return false; - } - return true; } + return true; +} - bool StoreString(const TRule_table_setting_value& from, TNodePtr& to, TContext& ctx) { - switch (from.Alt_case()) { +bool StoreString(const TRule_table_setting_value& from, TNodePtr& to, TContext& ctx) { + switch (from.Alt_case()) { case TRule_table_setting_value::kAltTableSettingValue2: { // STRING_VALUE const TString stringValue(ctx.Token(from.GetAlt_table_setting_value2().GetToken1())); @@ -1964,12 +1947,12 @@ namespace { } default: return false; - } - return true; } + return true; +} - bool StoreString(const TRule_table_setting_value& from, TDeferredAtom& to, TContext& ctx, const TString& errorPrefix = {}) { - switch (from.Alt_case()) { +bool StoreString(const TRule_table_setting_value& from, TDeferredAtom& to, TContext& ctx, const TString& errorPrefix = {}) { + switch (from.Alt_case()) { case TRule_table_setting_value::kAltTableSettingValue2: { // STRING_VALUE const TString stringValue(ctx.Token(from.GetAlt_table_setting_value2().GetToken1())); @@ -1984,12 +1967,12 @@ namespace { default: ctx.Error() << errorPrefix << " value should be a string literal"; return false; - } - return true; } + return true; +} - bool StoreInt(const TRule_table_setting_value& from, TNodePtr& to, TContext& ctx) { - switch (from.Alt_case()) { +bool StoreInt(const TRule_table_setting_value& from, TNodePtr& to, TContext& ctx) { + switch (from.Alt_case()) { case TRule_table_setting_value::kAltTableSettingValue3: { // integer to = LiteralNumber(ctx, from.GetAlt_table_setting_value3().GetRule_integer1()); @@ -1997,12 +1980,12 @@ namespace { } default: return false; - } - return true; } + return true; +} - bool StoreInt(const TRule_table_setting_value& from, TDeferredAtom& to, TContext& ctx, const TString& errorPrefix = {}) { - switch (from.Alt_case()) { +bool StoreInt(const TRule_table_setting_value& from, TDeferredAtom& to, TContext& ctx, const TString& errorPrefix = {}) { + switch (from.Alt_case()) { case TRule_table_setting_value::kAltTableSettingValue3: { // integer to = TDeferredAtom(LiteralNumber(ctx, from.GetAlt_table_setting_value3().GetRule_integer1()), ctx); @@ -2011,78 +1994,67 @@ namespace { default: ctx.Error() << errorPrefix << " value should be an integer"; return false; - } - return true; } + return true; +} - bool StoreSplitBoundary(const TRule_literal_value_list& boundary, TVector<TVector<TNodePtr>>& to, - TSqlExpression& expr, TContext& ctx) { - TVector<TNodePtr> boundaryKeys; - auto first_key = expr.LiteralExpr(boundary.GetRule_literal_value2()); - if (!first_key) { +bool StoreSplitBoundary(const TRule_literal_value_list& boundary, TVector<TVector<TNodePtr>>& to, + TSqlExpression& expr, TContext& ctx) { + TVector<TNodePtr> boundaryKeys; + auto first_key = expr.LiteralExpr(boundary.GetRule_literal_value2()); + if (!first_key) { + ctx.Error() << "Empty key in partition at keys"; + return false; + } + if (!first_key->Expr) { + ctx.Error() << "Identifier is not expected in partition at keys"; + return false; + } + boundaryKeys.emplace_back(first_key->Expr); + for (auto& key : boundary.GetBlock3()) { + auto keyExprOrIdent = expr.LiteralExpr(key.GetRule_literal_value2()); + if (!keyExprOrIdent) { ctx.Error() << "Empty key in partition at keys"; return false; } - if (!first_key->Expr) { + if (!keyExprOrIdent->Expr) { ctx.Error() << "Identifier is not expected in partition at keys"; return false; } - boundaryKeys.emplace_back(first_key->Expr); - for (auto& key : boundary.GetBlock3()) { - auto keyExprOrIdent = expr.LiteralExpr(key.GetRule_literal_value2()); - if (!keyExprOrIdent) { - ctx.Error() << "Empty key in partition at keys"; - return false; - } - if (!keyExprOrIdent->Expr) { - ctx.Error() << "Identifier is not expected in partition at keys"; - return false; - } - boundaryKeys.emplace_back(keyExprOrIdent->Expr); - } - to.push_back(boundaryKeys); - return true; + boundaryKeys.emplace_back(keyExprOrIdent->Expr); } + to.push_back(boundaryKeys); + return true; +} - bool StoreSplitBoundaries(const TRule_table_setting_value& from, TVector<TVector<TNodePtr>>& to, - TSqlExpression& expr, TContext& ctx) { - switch (from.Alt_case()) { +bool StoreSplitBoundaries(const TRule_table_setting_value& from, TVector<TVector<TNodePtr>>& to, + TSqlExpression& expr, TContext& ctx) { + switch (from.Alt_case()) { case TRule_table_setting_value::kAltTableSettingValue4: { // split_boundaries const auto& boundariesNode = from.GetAlt_table_setting_value4().GetRule_split_boundaries1(); switch (boundariesNode.Alt_case()) { - case TRule_split_boundaries::kAltSplitBoundaries1: { - // literal_value_list (COMMA literal_value_list)* - auto& complexBoundaries = boundariesNode.GetAlt_split_boundaries1(); + case TRule_split_boundaries::kAltSplitBoundaries1: { + // literal_value_list (COMMA literal_value_list)* + auto& complexBoundaries = boundariesNode.GetAlt_split_boundaries1(); - auto& first_boundary = complexBoundaries.GetRule_literal_value_list2(); - if (!StoreSplitBoundary(first_boundary, to, expr, ctx)) { - return false; - } - - for (auto& boundary : complexBoundaries.GetBlock3()) { - if (!StoreSplitBoundary(boundary.GetRule_literal_value_list2(), to, expr, ctx)) { + auto& first_boundary = complexBoundaries.GetRule_literal_value_list2(); + if (!StoreSplitBoundary(first_boundary, to, expr, ctx)) { return false; } + + for (auto& boundary : complexBoundaries.GetBlock3()) { + if (!StoreSplitBoundary(boundary.GetRule_literal_value_list2(), to, expr, ctx)) { + return false; + } + } + break; } - break; - } - case TRule_split_boundaries::kAltSplitBoundaries2: { - // literal_value_list - auto& simpleBoundaries = boundariesNode.GetAlt_split_boundaries2().GetRule_literal_value_list1(); - auto first_key = expr.LiteralExpr(simpleBoundaries.GetRule_literal_value2()); - if (!first_key) { - ctx.Error() << "Empty key in partition at keys"; - return false; - } - if (!first_key->Expr) { - ctx.Error() << "Identifier is not expected in partition at keys"; - return false; - } - to.push_back(TVector<TNodePtr>(1, first_key->Expr)); - for (auto& key : simpleBoundaries.GetBlock3()) { - auto keyExprOrIdent = expr.LiteralExpr(key.GetRule_literal_value2()); - if (!keyExprOrIdent) { + case TRule_split_boundaries::kAltSplitBoundaries2: { + // literal_value_list + auto& simpleBoundaries = boundariesNode.GetAlt_split_boundaries2().GetRule_literal_value_list1(); + auto first_key = expr.LiteralExpr(simpleBoundaries.GetRule_literal_value2()); + if (!first_key) { ctx.Error() << "Empty key in partition at keys"; return false; } @@ -2090,55 +2062,65 @@ namespace { ctx.Error() << "Identifier is not expected in partition at keys"; return false; } - to.push_back( - TVector<TNodePtr>(1, keyExprOrIdent->Expr) - ); + to.push_back(TVector<TNodePtr>(1, first_key->Expr)); + for (auto& key : simpleBoundaries.GetBlock3()) { + auto keyExprOrIdent = expr.LiteralExpr(key.GetRule_literal_value2()); + if (!keyExprOrIdent) { + ctx.Error() << "Empty key in partition at keys"; + return false; + } + if (!first_key->Expr) { + ctx.Error() << "Identifier is not expected in partition at keys"; + return false; + } + to.push_back( + TVector<TNodePtr>(1, keyExprOrIdent->Expr)); + } + break; } - break; - } - default: - return false; + default: + return false; } break; } default: return false; - } - return true; } + return true; +} - bool FillTieringInterval(const TRule_expr& from, TNodePtr& tieringInterval, TSqlExpression& expr, TContext& ctx) { - auto exprNode = expr.Build(from); - if (!exprNode) { - return false; - } - - if (exprNode->GetOpName() != "Interval") { - ctx.Error() << "Literal of Interval type is expected for TTL"; - return false; - } +bool FillTieringInterval(const TRule_expr& from, TNodePtr& tieringInterval, TSqlExpression& expr, TContext& ctx) { + auto exprNode = expr.Build(from); + if (!exprNode) { + return false; + } - tieringInterval = exprNode; - return true; + if (exprNode->GetOpName() != "Interval") { + ctx.Error() << "Literal of Interval type is expected for TTL"; + return false; } - bool FillTierAction(const TRule_ttl_tier_action& from, std::optional<TIdentifier>& storageName, TTranslation& txc) { - switch (from.GetAltCase()) { - case TRule_ttl_tier_action::kAltTtlTierAction1: - storageName = IdEx(from.GetAlt_ttl_tier_action1().GetRule_an_id5(), txc); - break; - case TRule_ttl_tier_action::kAltTtlTierAction2: - storageName.reset(); - break; - case TRule_ttl_tier_action::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); - } - return true; + tieringInterval = exprNode; + return true; +} + +bool FillTierAction(const TRule_ttl_tier_action& from, std::optional<TIdentifier>& storageName, TTranslation& txc) { + switch (from.GetAltCase()) { + case TRule_ttl_tier_action::kAltTtlTierAction1: + storageName = IdEx(from.GetAlt_ttl_tier_action1().GetRule_an_id5(), txc); + break; + case TRule_ttl_tier_action::kAltTtlTierAction2: + storageName.reset(); + break; + case TRule_ttl_tier_action::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } + return true; +} - bool StoreTtlSettings(const TRule_table_setting_value& from, TResetableSetting<TTtlSettings, void>& to, TSqlExpression& expr, TContext& ctx, - TTranslation& txc) { - switch (from.Alt_case()) { +bool StoreTtlSettings(const TRule_table_setting_value& from, TResetableSetting<TTtlSettings, void>& to, TSqlExpression& expr, TContext& ctx, + TTranslation& txc) { + switch (from.Alt_case()) { case TRule_table_setting_value::kAltTableSettingValue5: { auto columnName = IdEx(from.GetAlt_table_setting_value5().GetRule_an_id3(), txc); auto tiersLiteral = from.GetAlt_table_setting_value5().GetRule_ttl_tier_list1(); @@ -2186,74 +2168,74 @@ namespace { } default: return false; - } - return true; } + return true; +} - template<typename TChar> - struct TPatternComponent { - TBasicString<TChar> Prefix; - TBasicString<TChar> Suffix; - bool IsSimple = true; +template <typename TChar> +struct TPatternComponent { + TBasicString<TChar> Prefix; + TBasicString<TChar> Suffix; + bool IsSimple = true; - void AppendPlain(TChar c) { - if (IsSimple) { - Prefix.push_back(c); - } - Suffix.push_back(c); + void AppendPlain(TChar c) { + if (IsSimple) { + Prefix.push_back(c); } + Suffix.push_back(c); + } - void AppendAnyChar() { - IsSimple = false; - Suffix.clear(); - } - }; + void AppendAnyChar() { + IsSimple = false; + Suffix.clear(); + } +}; - template<typename TChar> - TVector<TPatternComponent<TChar>> SplitPattern(const TBasicString<TChar>& pattern, TMaybe<char> escape, bool& inEscape) { - inEscape = false; - TVector<TPatternComponent<TChar>> result; - TPatternComponent<TChar> current; - bool prevIsPercentChar = false; - for (const TChar c : pattern) { - if (inEscape) { - current.AppendPlain(c); - inEscape = false; - prevIsPercentChar = false; - } else if (escape && c == static_cast<TChar>(*escape)) { - inEscape = true; - } else if (c == '%') { - if (!prevIsPercentChar) { - result.push_back(std::move(current)); - } - current = {}; - prevIsPercentChar = true; - } else if (c == '_') { - current.AppendAnyChar(); - prevIsPercentChar = false; - } else { - current.AppendPlain(c); - prevIsPercentChar = false; - } +template <typename TChar> +TVector<TPatternComponent<TChar>> SplitPattern(const TBasicString<TChar>& pattern, TMaybe<char> escape, bool& inEscape) { + inEscape = false; + TVector<TPatternComponent<TChar>> result; + TPatternComponent<TChar> current; + bool prevIsPercentChar = false; + for (const TChar c : pattern) { + if (inEscape) { + current.AppendPlain(c); + inEscape = false; + prevIsPercentChar = false; + } else if (escape && c == static_cast<TChar>(*escape)) { + inEscape = true; + } else if (c == '%') { + if (!prevIsPercentChar) { + result.push_back(std::move(current)); + } + current = {}; + prevIsPercentChar = true; + } else if (c == '_') { + current.AppendAnyChar(); + prevIsPercentChar = false; + } else { + current.AppendPlain(c); + prevIsPercentChar = false; } - result.push_back(std::move(current)); - return result; } + result.push_back(std::move(current)); + return result; } +} // namespace bool TSqlTranslation::StoreTableSettingsEntry(const TIdentifier& id, const TRule_table_setting_value* value, - TTableSettings& settings, ETableType tableType, bool alter, bool reset) { + TTableSettings& settings, ETableType tableType, bool alter, bool reset) { switch (tableType) { - case ETableType::ExternalTable: - return StoreExternalTableSettingsEntry(id, value, settings, alter, reset); - case ETableType::Table: - case ETableType::TableStore: - return StoreTableSettingsEntry(id, value, settings, alter, reset); + case ETableType::ExternalTable: + return StoreExternalTableSettingsEntry(id, value, settings, alter, reset); + case ETableType::Table: + case ETableType::TableStore: + return StoreTableSettingsEntry(id, value, settings, alter, reset); } } bool TSqlTranslation::StoreExternalTableSettingsEntry(const TIdentifier& id, const TRule_table_setting_value* value, - TTableSettings& settings, bool alter, bool reset) { + TTableSettings& settings, bool alter, bool reset) { YQL_ENSURE(value || reset); YQL_ENSURE(!reset || reset && alter); if (to_lower(id.Name) == "data_source") { @@ -2309,7 +2291,7 @@ bool TSqlTranslation::ValidateTableSettings(const TTableSettings& settings) { } bool TSqlTranslation::StoreTableSettingsEntry(const TIdentifier& id, const TRule_table_setting_value* value, - TTableSettings& settings, bool alter, bool reset) { + TTableSettings& settings, bool alter, bool reset) { YQL_ENSURE(value || reset); YQL_ENSURE(!reset || reset && alter); if (to_lower(id.Name) == "compaction_policy") { @@ -2393,7 +2375,7 @@ bool TSqlTranslation::StoreTableSettingsEntry(const TIdentifier& id, const TRule TSqlExpression expr(Ctx_, Mode_); if (!StoreSplitBoundaries(*value, settings.PartitionAtKeys, expr, Ctx_)) { Ctx_.Error() << to_upper(id.Name) << " value should be a list of keys. " - << "Example1: (10, 1000) Example2: ((10), (1000, \"abc\"))"; + << "Example1: (10, 1000) Example2: ((10), (1000, \"abc\"))"; return false; } } else if (to_lower(id.Name) == "key_bloom_filter") { @@ -2480,7 +2462,7 @@ bool TSqlTranslation::StoreTableSettingsEntry(const TIdentifier& id, const TRule } bool TSqlTranslation::StoreTableSettingsEntry(const TIdentifier& id, const TRule_table_setting_value& value, - TTableSettings& settings, ETableType tableType, bool alter) { + TTableSettings& settings, ETableType tableType, bool alter) { return StoreTableSettingsEntry(id, &value, settings, tableType, alter, false); } @@ -2491,7 +2473,7 @@ bool TSqlTranslation::ResetTableSettingsEntry(const TIdentifier& id, TTableSetti bool TSqlTranslation::CreateTableSettings(const TRule_with_table_settings& settingsNode, TCreateTableParameters& params) { const auto& firstEntry = settingsNode.GetRule_table_settings_entry3(); if (!StoreTableSettingsEntry(IdEx(firstEntry.GetRule_an_id1(), *this), firstEntry.GetRule_table_setting_value3(), - params.TableSettings, params.TableType)) { + params.TableSettings, params.TableType)) { return false; } for (auto& block : settingsNode.GetBlock4()) { @@ -2504,10 +2486,9 @@ bool TSqlTranslation::CreateTableSettings(const TRule_with_table_settings& setti } static bool StoreConsumerSettingsEntry( - const TIdentifier& id, const TRule_topic_consumer_setting_value* value, TSqlExpression& ctx, - TTopicConsumerSettings& settings, - bool reset, bool alter -) { + const TIdentifier& id, const TRule_topic_consumer_setting_value* value, TSqlExpression& ctx, + TTopicConsumerSettings& settings, + bool reset, bool alter) { YQL_ENSURE(value || reset); const TStringBuf statement = alter ? "ALTER CONSUMER"sv : "CONSUMER"sv; TNodePtr valueExprNode; @@ -2554,7 +2535,7 @@ static bool StoreConsumerSettingsEntry( if (reset) { settings.ReadFromTs.Reset(); } else { - //ToDo: !! validate + // ToDo: !! validate settings.ReadFromTs.Set(valueExprNode); } } else if (to_lower(id.Name) == "supported_codecs") { @@ -2583,16 +2564,14 @@ TIdentifier TSqlTranslation::GetTopicConsumerId(const TRule_topic_consumer_ref& } bool TSqlTranslation::CreateConsumerSettings( - const TRule_topic_consumer_settings& node, TTopicConsumerSettings& settings -) { + const TRule_topic_consumer_settings& node, TTopicConsumerSettings& settings) { const auto& firstEntry = node.GetRule_topic_consumer_settings_entry1(); TSqlExpression expr(Ctx_, Mode_); if (!StoreConsumerSettingsEntry( IdEx(firstEntry.GetRule_an_id1(), *this), &firstEntry.GetRule_topic_consumer_setting_value3(), expr, settings, false, - /* alter = */ false - )) { + /* alter = */ false)) { return false; } for (auto& block : node.GetBlock2()) { @@ -2601,8 +2580,7 @@ bool TSqlTranslation::CreateConsumerSettings( IdEx(entry.GetRule_an_id1(), *this), &entry.GetRule_topic_consumer_setting_value3(), expr, settings, false, - /* alter = */ false - )) { + /* alter = */ false)) { return false; } } @@ -2610,9 +2588,8 @@ bool TSqlTranslation::CreateConsumerSettings( } bool TSqlTranslation::CreateTopicConsumer( - const TRule_topic_create_consumer_entry& node, - TVector<TTopicConsumerDescription>& consumers -) { + const TRule_topic_create_consumer_entry& node, + TVector<TTopicConsumerDescription>& consumers) { consumers.emplace_back(IdEx(node.GetRule_an_id2(), *this)); if (node.HasBlock3()) { @@ -2626,16 +2603,13 @@ bool TSqlTranslation::CreateTopicConsumer( } bool TSqlTranslation::AlterTopicConsumerEntry( - const TRule_alter_topic_alter_consumer_entry& node, TTopicConsumerDescription& alterConsumer -) { + const TRule_alter_topic_alter_consumer_entry& node, TTopicConsumerDescription& alterConsumer) { switch (node.Alt_case()) { case TRule_alter_topic_alter_consumer_entry::kAltAlterTopicAlterConsumerEntry1: return CreateConsumerSettings( - node.GetAlt_alter_topic_alter_consumer_entry1().GetRule_topic_alter_consumer_set1() - .GetRule_topic_consumer_settings3(), - alterConsumer.Settings - ); - //case TRule_alter_topic_alter_consumer_entry::ALT_NOT_SET: + node.GetAlt_alter_topic_alter_consumer_entry1().GetRule_topic_alter_consumer_set1().GetRule_topic_consumer_settings3(), + alterConsumer.Settings); + // case TRule_alter_topic_alter_consumer_entry::ALT_NOT_SET: case TRule_alter_topic_alter_consumer_entry::kAltAlterTopicAlterConsumerEntry2: { auto& resetNode = node.GetAlt_alter_topic_alter_consumer_entry2().GetRule_topic_alter_consumer_reset1(); TSqlExpression expr(Ctx_, Mode_); @@ -2643,18 +2617,16 @@ bool TSqlTranslation::AlterTopicConsumerEntry( IdEx(resetNode.GetRule_an_id3(), *this), nullptr, expr, alterConsumer.Settings, true, - /* alter = */ true - )) { + /* alter = */ true)) { return false; } - for (auto& resetItem: resetNode.GetBlock4()) { + for (auto& resetItem : resetNode.GetBlock4()) { if (!StoreConsumerSettingsEntry( IdEx(resetItem.GetRule_an_id2(), *this), nullptr, expr, alterConsumer.Settings, true, - /* alter = */ true - )) { + /* alter = */ true)) { return false; } } @@ -2668,14 +2640,13 @@ bool TSqlTranslation::AlterTopicConsumerEntry( } bool TSqlTranslation::AlterTopicConsumer( - const TRule_alter_topic_alter_consumer& node, - THashMap<TString, TTopicConsumerDescription>& alterConsumers -) { + const TRule_alter_topic_alter_consumer& node, + THashMap<TString, TTopicConsumerDescription>& alterConsumers) { auto consumerId = GetTopicConsumerId(node.GetRule_topic_consumer_ref3()); TString name = to_lower(consumerId.Name); auto iter = alterConsumers.insert(std::make_pair( - name, TTopicConsumerDescription(std::move(consumerId)) - )).first; + name, TTopicConsumerDescription(std::move(consumerId)))) + .first; if (!AlterTopicConsumerEntry(node.GetRule_alter_topic_alter_consumer_entry4(), iter->second)) { return false; } @@ -2692,9 +2663,8 @@ bool TSqlTranslation::CreateTopicEntry(const TRule_create_topic_entry& node, TCr } static bool StoreTopicSettingsEntry( - const TIdentifier& id, const TRule_topic_setting_value* value, TSqlExpression& ctx, - TTopicSettings& settings, bool reset -) { + const TIdentifier& id, const TRule_topic_setting_value* value, TSqlExpression& ctx, + TTopicSettings& settings, bool reset) { YQL_ENSURE(value || reset); TNodePtr valueExprNode; if (value) { @@ -2833,40 +2803,33 @@ static bool StoreTopicSettingsEntry( } bool TSqlTranslation::AlterTopicAction(const TRule_alter_topic_action& node, TAlterTopicParameters& params) { -// alter_topic_action: -// alter_topic_add_consumer -// | alter_topic_alter_consumer -// | alter_topic_drop_consumer -// | alter_topic_set_settings -// | alter_topic_reset_settings + // alter_topic_action: + // alter_topic_add_consumer + // | alter_topic_alter_consumer + // | alter_topic_drop_consumer + // | alter_topic_set_settings + // | alter_topic_reset_settings switch (node.Alt_case()) { case TRule_alter_topic_action::kAltAlterTopicAction1: // alter_topic_add_consumer return CreateTopicConsumer( - node.GetAlt_alter_topic_action1().GetRule_alter_topic_add_consumer1() - .GetRule_topic_create_consumer_entry2(), - params.AddConsumers - ); + node.GetAlt_alter_topic_action1().GetRule_alter_topic_add_consumer1().GetRule_topic_create_consumer_entry2(), + params.AddConsumers); case TRule_alter_topic_action::kAltAlterTopicAction2: // alter_topic_alter_consumer return AlterTopicConsumer( - node.GetAlt_alter_topic_action2().GetRule_alter_topic_alter_consumer1(), - params.AlterConsumers - ); + node.GetAlt_alter_topic_action2().GetRule_alter_topic_alter_consumer1(), + params.AlterConsumers); case TRule_alter_topic_action::kAltAlterTopicAction3: // drop_consumer params.DropConsumers.emplace_back(GetTopicConsumerId( - node.GetAlt_alter_topic_action3().GetRule_alter_topic_drop_consumer1() - .GetRule_topic_consumer_ref3() - )); + node.GetAlt_alter_topic_action3().GetRule_alter_topic_drop_consumer1().GetRule_topic_consumer_ref3())); return true; case TRule_alter_topic_action::kAltAlterTopicAction4: // set_settings return CreateTopicSettings( - node.GetAlt_alter_topic_action4().GetRule_alter_topic_set_settings1() - .GetRule_topic_settings3(), - params.TopicSettings - ); + node.GetAlt_alter_topic_action4().GetRule_alter_topic_set_settings1().GetRule_topic_settings3(), + params.TopicSettings); case TRule_alter_topic_action::kAltAlterTopicAction5: { // reset_settings auto& resetNode = node.GetAlt_alter_topic_action5().GetRule_alter_topic_reset_settings1(); @@ -2874,17 +2837,15 @@ bool TSqlTranslation::AlterTopicAction(const TRule_alter_topic_action& node, TAl if (!StoreTopicSettingsEntry( IdEx(resetNode.GetRule_an_id3(), *this), nullptr, expr, - params.TopicSettings, true - )) { + params.TopicSettings, true)) { return false; } - for (auto& resetItem: resetNode.GetBlock4()) { + for (auto& resetItem : resetNode.GetBlock4()) { if (!StoreTopicSettingsEntry( IdEx(resetItem.GetRule_an_id_pure2(), *this), nullptr, expr, - params.TopicSettings, true - )) { + params.TopicSettings, true)) { return false; } } @@ -2904,8 +2865,7 @@ bool TSqlTranslation::CreateTopicSettings(const TRule_topic_settings& node, TTop if (!StoreTopicSettingsEntry( IdEx(firstEntry.GetRule_an_id1(), *this), &firstEntry.GetRule_topic_setting_value3(), - expr, settings, false - )) { + expr, settings, false)) { return false; } for (auto& block : node.GetBlock2()) { @@ -2913,8 +2873,7 @@ bool TSqlTranslation::CreateTopicSettings(const TRule_topic_settings& node, TTop if (!StoreTopicSettingsEntry( IdEx(entry.GetRule_an_id1(), *this), &entry.GetRule_topic_setting_value3(), - expr, settings, false - )) { + expr, settings, false)) { return false; } } @@ -3003,7 +2962,7 @@ TNodePtr TSqlTranslation::TypeDecimal(const TRule_type_name_decimal& node) { if (!paramTwo) { return {}; } - return new TCallNodeImpl(pos, "DataType", { BuildQuotedAtom(pos, "Decimal", flags), paramOne, paramTwo }); + return new TCallNodeImpl(pos, "DataType", {BuildQuotedAtom(pos, "Decimal", flags), paramOne, paramTwo}); } TNodePtr TSqlTranslation::AddOptionals(const TNodePtr& node, size_t optionalCount) { @@ -3011,13 +2970,12 @@ TNodePtr TSqlTranslation::AddOptionals(const TNodePtr& node, size_t optionalCoun if (node) { TPosition pos = node->GetPos(); for (size_t i = 0; i < optionalCount; ++i) { - result = new TCallNodeImpl(pos, "OptionalType", { result }); + result = new TCallNodeImpl(pos, "OptionalType", {result}); } } return result; } - TMaybe<std::pair<TVector<TNodePtr>, bool>> TSqlTranslation::CallableArgList(const TRule_callable_arg_list& argList, bool namedArgsStarted) { auto pos = Ctx_.Pos(); auto flags = TNodeFlags::Default; @@ -3096,9 +3054,9 @@ TNodePtr TSqlTranslation::TypeNodeOrBind(const TRule_type_name_or_bind& node) { } TNodePtr TSqlTranslation::TypeNode(const TRule_type_name& node) { - //type_name: - // type_name_composite - // | (type_name_decimal | type_name_simple) QUESTION*; + // type_name: + // type_name_composite + // | (type_name_decimal | type_name_simple) QUESTION*; if (node.Alt_case() == TRule_type_name::kAltTypeName1) { return TypeNode(node.GetAlt_type_name1().GetRule_type_name_composite1()); } @@ -3127,34 +3085,34 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name& node) { } TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { - //type_name_composite: - // ( type_name_optional - // | type_name_tuple - // | type_name_struct - // | type_name_variant - // | type_name_list - // | type_name_stream - // | type_name_flow - // | type_name_dict - // | type_name_set - // | type_name_enum - // | type_name_resource - // | type_name_tagged - // | type_name_callable - // ) QUESTION*; + // type_name_composite: + // ( type_name_optional + // | type_name_tuple + // | type_name_struct + // | type_name_variant + // | type_name_list + // | type_name_stream + // | type_name_flow + // | type_name_dict + // | type_name_set + // | type_name_enum + // | type_name_resource + // | type_name_tagged + // | type_name_callable + // ) QUESTION*; TNodePtr result; TPosition pos = Ctx_.Pos(); auto flags = TNodeFlags::Default; - auto wrapOneParamType = [&] (const TRule_type_name_or_bind& param, const char* type) -> TNodePtr { + auto wrapOneParamType = [&](const TRule_type_name_or_bind& param, const char* type) -> TNodePtr { auto node = TypeNodeOrBind(param); - return node ? new TAstListNodeImpl(pos, { BuildAtom(pos, type, flags), node }) : nullptr; + return node ? new TAstListNodeImpl(pos, {BuildAtom(pos, type, flags), node}) : nullptr; }; - auto makeVoid = [&] () -> TNodePtr { - return new TAstListNodeImpl(pos, { BuildAtom(pos, "VoidType", flags) }); + auto makeVoid = [&]() -> TNodePtr { + return new TAstListNodeImpl(pos, {BuildAtom(pos, "VoidType", flags)}); }; - auto makeQuote = [&] (const TNodePtr& node) -> TNodePtr { - return new TAstListNodeImpl(pos, { new TAstAtomNodeImpl(pos, "quote", 0), node }); + auto makeQuote = [&](const TNodePtr& node) -> TNodePtr { + return new TAstListNodeImpl(pos, {new TAstAtomNodeImpl(pos, "quote", 0), node}); }; auto& block = node.GetBlock1(); @@ -3170,27 +3128,27 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { items.push_back(BuildAtom(pos, "TupleType", flags)); switch (tupleType.GetBlock2().Alt_case()) { - case TRule_type_name_tuple::TBlock2::kAlt1: { - if (tupleType.GetBlock2().GetAlt1().HasBlock2()) { - auto typeNode = TypeNodeOrBind(tupleType.GetBlock2().GetAlt1().GetBlock2().GetRule_type_name_or_bind1()); - if (!typeNode) { - return {}; - } - items.push_back(typeNode); - for (auto& arg : tupleType.GetBlock2().GetAlt1().GetBlock2().GetBlock2()) { - auto typeNode = TypeNodeOrBind(arg.GetRule_type_name_or_bind2()); + case TRule_type_name_tuple::TBlock2::kAlt1: { + if (tupleType.GetBlock2().GetAlt1().HasBlock2()) { + auto typeNode = TypeNodeOrBind(tupleType.GetBlock2().GetAlt1().GetBlock2().GetRule_type_name_or_bind1()); if (!typeNode) { return {}; } items.push_back(typeNode); + for (auto& arg : tupleType.GetBlock2().GetAlt1().GetBlock2().GetBlock2()) { + auto typeNode = TypeNodeOrBind(arg.GetRule_type_name_or_bind2()); + if (!typeNode) { + return {}; + } + items.push_back(typeNode); + } } + [[fallthrough]]; // AUTOGENERATED_FALLTHROUGH_FIXME } - [[fallthrough]]; // AUTOGENERATED_FALLTHROUGH_FIXME - } - case TRule_type_name_tuple::TBlock2::kAlt2: - break; - case TRule_type_name_tuple::TBlock2::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_type_name_tuple::TBlock2::kAlt2: + break; + case TRule_type_name_tuple::TBlock2::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } result = new TAstListNodeImpl(pos, items); @@ -3214,7 +3172,7 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { return {}; } - items.push_back(makeQuote(new TAstListNodeImpl(pos, { tag, typeNode }))); + items.push_back(makeQuote(new TAstListNodeImpl(pos, {tag, typeNode}))); for (auto& arg : structType.GetBlock2().GetAlt1().GetBlock2().GetBlock2()) { auto typeNode = TypeNodeOrBind(arg.GetRule_struct_arg2().GetRule_type_name_or_bind3()); if (!typeNode) { @@ -3224,7 +3182,7 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { if (!tag) { return {}; } - items.push_back(makeQuote(new TAstListNodeImpl(pos, { tag, typeNode }))); + items.push_back(makeQuote(new TAstListNodeImpl(pos, {tag, typeNode}))); } } [[fallthrough]]; // AUTOGENERATED_FALLTHROUGH_FIXME @@ -3254,7 +3212,7 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { if (!tag) { return {}; } - items.push_back(makeQuote(new TAstListNodeImpl(pos, { tag, typeNode }))); + items.push_back(makeQuote(new TAstListNodeImpl(pos, {tag, typeNode}))); } else { items.push_back(BuildAtom(pos, "TupleType", flags)); items.push_back(typeNode); @@ -3274,7 +3232,7 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { if (!tag) { return {}; } - items.push_back(makeQuote(new TAstListNodeImpl(pos, { tag, typeNode }))); + items.push_back(makeQuote(new TAstListNodeImpl(pos, {tag, typeNode}))); } else { if (arg.GetRule_variant_arg2().HasBlock1()) { Ctx_.Error() << "Variant over struct and tuple mixture"; @@ -3284,7 +3242,7 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { } } typeNode = new TAstListNodeImpl(pos, items); - result = new TAstListNodeImpl(pos, { BuildAtom(pos, "VariantType", flags), typeNode }); + result = new TAstListNodeImpl(pos, {BuildAtom(pos, "VariantType", flags), typeNode}); break; } case TRule_type_name_composite_TBlock1::kAlt5: { @@ -3325,7 +3283,7 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { if (!typeNode) { return {}; } - result = new TAstListNodeImpl(pos, { BuildAtom(pos, "DictType", flags), typeNode, makeVoid() }); + result = new TAstListNodeImpl(pos, {BuildAtom(pos, "DictType", flags), typeNode, makeVoid()}); break; } case TRule_type_name_composite_TBlock1::kAlt10: { @@ -3336,16 +3294,16 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { if (!tag) { return {}; } - items.push_back(makeQuote(new TAstListNodeImpl(pos, { tag, makeVoid() }))); + items.push_back(makeQuote(new TAstListNodeImpl(pos, {tag, makeVoid()}))); for (auto& arg : enumType.GetBlock4()) { auto tag = TypeNameTag(arg.GetRule_type_name_tag2()); if (!tag) { return {}; } - items.push_back(makeQuote(new TAstListNodeImpl(pos, { tag, makeVoid() }))); + items.push_back(makeQuote(new TAstListNodeImpl(pos, {tag, makeVoid()}))); } auto typeNode = new TAstListNodeImpl(pos, items); - result = new TAstListNodeImpl(pos, { BuildAtom(pos, "VariantType", flags), typeNode }); + result = new TAstListNodeImpl(pos, {BuildAtom(pos, "VariantType", flags), typeNode}); break; } case TRule_type_name_composite_TBlock1::kAlt11: { @@ -3354,7 +3312,7 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { if (!tag) { return {}; } - result = new TAstListNodeImpl(pos, { BuildAtom(pos, "ResourceType", flags), tag }); + result = new TAstListNodeImpl(pos, {BuildAtom(pos, "ResourceType", flags), tag}); break; } case TRule_type_name_composite_TBlock1::kAlt12: { @@ -3367,7 +3325,7 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { if (!tag) { return {}; } - result = new TAstListNodeImpl(pos, { BuildAtom(pos, "TaggedType", flags), typeNode, tag }); + result = new TAstListNodeImpl(pos, {BuildAtom(pos, "TaggedType", flags), typeNode, tag}); break; } case TRule_type_name_composite_TBlock1::kAlt13: { @@ -3399,18 +3357,18 @@ TNodePtr TSqlTranslation::TypeNode(const TRule_type_name_composite& node) { items.push_back(BuildAtom(pos, "CallableType", flags)); if (optionalArgsCount) { items.push_back(makeQuote(new TAstListNodeImpl(pos, - { BuildQuotedAtom(pos, ToString(optionalArgsCount), flags) }))); + {BuildQuotedAtom(pos, ToString(optionalArgsCount), flags)}))); } else { items.push_back(makeQuote(new TAstListNodeImpl(pos, {}))); } - items.push_back(makeQuote(new TAstListNodeImpl(pos, { returnType }))); + items.push_back(makeQuote(new TAstListNodeImpl(pos, {returnType}))); if (requiredArgs) { - for (auto& arg: requiredArgs->first) { + for (auto& arg : requiredArgs->first) { items.push_back(makeQuote(arg)); } } if (optionalArgs) { - for (auto& arg: optionalArgs->first) { + for (auto& arg : optionalArgs->first) { items.push_back(makeQuote(arg)); } } @@ -3559,135 +3517,131 @@ bool TSqlTranslation::TableHintImpl(const TRule_table_hint& rule, TTableHints& h // | SCHEMA EQUALS? LPAREN (struct_arg_positional (COMMA struct_arg_positional)*)? COMMA? RPAREN // | WATERMARK AS LPAREN expr RPAREN switch (rule.Alt_case()) { - case TRule_table_hint::kAltTableHint1: { - const auto& alt = rule.GetAlt_table_hint1(); - const TString id = Id(alt.GetRule_an_id_hint1(), *this); - const auto idLower = to_lower(id); - if (idLower == "schema" || idLower == "columns") { - Error() << "Expected type after " << to_upper(id); - return false; - } - TVector<TNodePtr> hint_val; - if (alt.HasBlock2()) { - auto& tags = alt.GetBlock2().GetBlock2(); - switch (tags.Alt_case()) { - case TRule_table_hint_TAlt1_TBlock2_TBlock2::kAlt1: - hint_val.push_back(TypeNameTag(tags.GetAlt1().GetRule_type_name_tag1())); - break; - case TRule_table_hint_TAlt1_TBlock2_TBlock2::kAlt2: { - hint_val.push_back(TypeNameTag(tags.GetAlt2().GetRule_type_name_tag2())); - for (auto& tag : tags.GetAlt2().GetBlock3()) { - hint_val.push_back(TypeNameTag(tag.GetRule_type_name_tag2())); + case TRule_table_hint::kAltTableHint1: { + const auto& alt = rule.GetAlt_table_hint1(); + const TString id = Id(alt.GetRule_an_id_hint1(), *this); + const auto idLower = to_lower(id); + if (idLower == "schema" || idLower == "columns") { + Error() << "Expected type after " << to_upper(id); + return false; + } + TVector<TNodePtr> hint_val; + if (alt.HasBlock2()) { + auto& tags = alt.GetBlock2().GetBlock2(); + switch (tags.Alt_case()) { + case TRule_table_hint_TAlt1_TBlock2_TBlock2::kAlt1: + hint_val.push_back(TypeNameTag(tags.GetAlt1().GetRule_type_name_tag1())); + break; + case TRule_table_hint_TAlt1_TBlock2_TBlock2::kAlt2: { + hint_val.push_back(TypeNameTag(tags.GetAlt2().GetRule_type_name_tag2())); + for (auto& tag : tags.GetAlt2().GetBlock3()) { + hint_val.push_back(TypeNameTag(tag.GetRule_type_name_tag2())); + } + break; } - break; + case TRule_table_hint_TAlt1_TBlock2_TBlock2::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } - case TRule_table_hint_TAlt1_TBlock2_TBlock2::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); } + hints[id] = hint_val; + break; } - hints[id] = hint_val; - break; - } - case TRule_table_hint::kAltTableHint2: { - const auto& alt2 = rule.GetAlt_table_hint2(); - auto node = TypeNodeOrBind(alt2.GetRule_type_name_or_bind3()); - if (!node) { - return false; - } + case TRule_table_hint::kAltTableHint2: { + const auto& alt2 = rule.GetAlt_table_hint2(); + auto node = TypeNodeOrBind(alt2.GetRule_type_name_or_bind3()); + if (!node) { + return false; + } - hints["user_" + to_lower(alt2.GetToken1().GetValue())] = { node }; - break; - } - - case TRule_table_hint::kAltTableHint3: { - const auto& alt = rule.GetAlt_table_hint3(); - TVector<TNodePtr> labels; - TVector<TNodePtr> structTypeItems; - if (alt.HasBlock4()) { - bool warn = false; - auto processItem = [&](const TRule_struct_arg_positional& arg) { - // struct_arg_positional: - // type_name_tag type_name_or_bind (NOT? NULL)? - // | type_name_or_bind AS type_name_tag; //deprecated - const bool altCurrent = arg.Alt_case() == TRule_struct_arg_positional::kAltStructArgPositional1; - auto& typeNameOrBind = altCurrent ? - arg.GetAlt_struct_arg_positional1().GetRule_type_name_or_bind2() : - arg.GetAlt_struct_arg_positional2().GetRule_type_name_or_bind1(); - auto typeNode = TypeNodeOrBind(typeNameOrBind); - if (!typeNode) { - return false; - } + hints["user_" + to_lower(alt2.GetToken1().GetValue())] = {node}; + break; + } - auto pos = Ctx_.Pos(); - if (!altCurrent && !warn) { - if (!Ctx_.Warning(pos, TIssuesIds::YQL_DEPRECATED_POSITIONAL_SCHEMA, [](auto& out) { - out << "Deprecated syntax for positional schema: " - << "please use 'column type' instead of 'type AS column'"; - })) { + case TRule_table_hint::kAltTableHint3: { + const auto& alt = rule.GetAlt_table_hint3(); + TVector<TNodePtr> labels; + TVector<TNodePtr> structTypeItems; + if (alt.HasBlock4()) { + bool warn = false; + auto processItem = [&](const TRule_struct_arg_positional& arg) { + // struct_arg_positional: + // type_name_tag type_name_or_bind (NOT? NULL)? + // | type_name_or_bind AS type_name_tag; //deprecated + const bool altCurrent = arg.Alt_case() == TRule_struct_arg_positional::kAltStructArgPositional1; + auto& typeNameOrBind = altCurrent ? arg.GetAlt_struct_arg_positional1().GetRule_type_name_or_bind2() : arg.GetAlt_struct_arg_positional2().GetRule_type_name_or_bind1(); + auto typeNode = TypeNodeOrBind(typeNameOrBind); + if (!typeNode) { return false; } - warn = true; - } - if (altCurrent) { - bool notNull = arg.GetAlt_struct_arg_positional1().HasBlock3() && arg.GetAlt_struct_arg_positional1().GetBlock3().HasBlock1(); - if (!notNull) { - typeNode = new TCallNodeImpl(pos, "AsOptionalType", { typeNode }); + auto pos = Ctx_.Pos(); + if (!altCurrent && !warn) { + if (!Ctx_.Warning(pos, TIssuesIds::YQL_DEPRECATED_POSITIONAL_SCHEMA, [](auto& out) { + out << "Deprecated syntax for positional schema: " + << "please use 'column type' instead of 'type AS column'"; + })) { + return false; + } + warn = true; } - } - auto& typeNameTag = altCurrent ? - arg.GetAlt_struct_arg_positional1().GetRule_type_name_tag1() : - arg.GetAlt_struct_arg_positional2().GetRule_type_name_tag3(); - auto tag = TypeNameTag(typeNameTag); - if (!tag) { - return false; - } + if (altCurrent) { + bool notNull = arg.GetAlt_struct_arg_positional1().HasBlock3() && arg.GetAlt_struct_arg_positional1().GetBlock3().HasBlock1(); + if (!notNull) { + typeNode = new TCallNodeImpl(pos, "AsOptionalType", {typeNode}); + } + } - labels.push_back(tag); - structTypeItems.push_back(BuildTuple(pos, { tag, typeNode })); - return true; - }; + auto& typeNameTag = altCurrent ? arg.GetAlt_struct_arg_positional1().GetRule_type_name_tag1() : arg.GetAlt_struct_arg_positional2().GetRule_type_name_tag3(); + auto tag = TypeNameTag(typeNameTag); + if (!tag) { + return false; + } - if (!processItem(alt.GetBlock4().GetRule_struct_arg_positional1())) { - return false; - } + labels.push_back(tag); + structTypeItems.push_back(BuildTuple(pos, {tag, typeNode})); + return true; + }; - for (auto& entry : alt.GetBlock4().GetBlock2()) { - if (!processItem(entry.GetRule_struct_arg_positional2())) { + if (!processItem(alt.GetBlock4().GetRule_struct_arg_positional1())) { return false; } + + for (auto& entry : alt.GetBlock4().GetBlock2()) { + if (!processItem(entry.GetRule_struct_arg_positional2())) { + return false; + } + } } - } - TPosition pos = Ctx_.TokenPosition(alt.GetToken1()); - TNodePtr structType = new TCallNodeImpl(pos, "StructType", structTypeItems); - bool shouldEmitLabel = provider != YtProviderName || TCiString(keyFunc) == "object"; - if (shouldEmitLabel) { - auto labelsTuple = BuildTuple(pos, labels); - hints["user_" + to_lower(alt.GetToken1().GetValue())] = { structType, labelsTuple }; - break; - } else { - hints["user_" + to_lower(alt.GetToken1().GetValue())] = { structType }; - break; + TPosition pos = Ctx_.TokenPosition(alt.GetToken1()); + TNodePtr structType = new TCallNodeImpl(pos, "StructType", structTypeItems); + bool shouldEmitLabel = provider != YtProviderName || TCiString(keyFunc) == "object"; + if (shouldEmitLabel) { + auto labelsTuple = BuildTuple(pos, labels); + hints["user_" + to_lower(alt.GetToken1().GetValue())] = {structType, labelsTuple}; + break; + } else { + hints["user_" + to_lower(alt.GetToken1().GetValue())] = {structType}; + break; + } } - } - case TRule_table_hint::kAltTableHint4: { - const auto& alt = rule.GetAlt_table_hint4(); - const auto pos = Ctx_.TokenPosition(alt.GetToken1()); - TColumnRefScope scope(Ctx_, EColumnRefState::Allow); - auto expr = TSqlExpression(Ctx_, Mode_).Build(alt.GetRule_expr4()); - if (!expr) { - return false; + case TRule_table_hint::kAltTableHint4: { + const auto& alt = rule.GetAlt_table_hint4(); + const auto pos = Ctx_.TokenPosition(alt.GetToken1()); + TColumnRefScope scope(Ctx_, EColumnRefState::Allow); + auto expr = TSqlExpression(Ctx_, Mode_).Build(alt.GetRule_expr4()); + if (!expr) { + return false; + } + hints["watermark"] = {BuildLambda(pos, BuildList(pos, {BuildAtom(pos, "row")}), std::move(expr))}; + break; } - hints["watermark"] = { BuildLambda(pos, BuildList(pos, {BuildAtom(pos, "row")}), std::move(expr)) }; - break; - } - case TRule_table_hint::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_table_hint::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } return true; @@ -3698,20 +3652,20 @@ TMaybe<TTableHints> TSqlTranslation::TableHintsImpl(const TRule_table_hints& nod auto& block = node.GetBlock2(); bool hasErrors = false; switch (block.Alt_case()) { - case TRule_table_hints::TBlock2::kAlt1: { - hasErrors = !TableHintImpl(block.GetAlt1().GetRule_table_hint1(), hints, provider, keyFunc); - break; - } - case TRule_table_hints::TBlock2::kAlt2: { - hasErrors = !TableHintImpl(block.GetAlt2().GetRule_table_hint2(), hints, provider, keyFunc); - for (const auto& x : block.GetAlt2().GetBlock3()) { - hasErrors = hasErrors || !TableHintImpl(x.GetRule_table_hint2(), hints, provider, keyFunc); + case TRule_table_hints::TBlock2::kAlt1: { + hasErrors = !TableHintImpl(block.GetAlt1().GetRule_table_hint1(), hints, provider, keyFunc); + break; } + case TRule_table_hints::TBlock2::kAlt2: { + hasErrors = !TableHintImpl(block.GetAlt2().GetRule_table_hint2(), hints, provider, keyFunc); + for (const auto& x : block.GetAlt2().GetBlock3()) { + hasErrors = hasErrors || !TableHintImpl(x.GetRule_table_hint2(), hints, provider, keyFunc); + } - break; - } - case TRule_table_hints::TBlock2::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + break; + } + case TRule_table_hints::TBlock2::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } if (hasErrors) { return Nothing(); @@ -3750,55 +3704,55 @@ bool TSqlTranslation::SimpleTableRefCoreImpl(const TRule_simple_table_ref_core& TString service = Context().Scoped->CurrService; TDeferredAtom cluster = Context().Scoped->CurrCluster; switch (node.Alt_case()) { - case TRule_simple_table_ref_core::AltCase::kAltSimpleTableRefCore1: { - if (node.GetAlt_simple_table_ref_core1().GetRule_object_ref1().HasBlock1()) { - if (!ClusterExpr(node.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetBlock1().GetRule_cluster_expr1(), false, service, cluster)) { + case TRule_simple_table_ref_core::AltCase::kAltSimpleTableRefCore1: { + if (node.GetAlt_simple_table_ref_core1().GetRule_object_ref1().HasBlock1()) { + if (!ClusterExpr(node.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetBlock1().GetRule_cluster_expr1(), false, service, cluster)) { + return false; + } + } + + if (cluster.Empty()) { + Error() << "No cluster name given and no default cluster is selected"; return false; } - } - if (cluster.Empty()) { - Error() << "No cluster name given and no default cluster is selected"; - return false; + result = TTableRef(Context().MakeName("table"), service, cluster, nullptr); + auto tableOrAt = Id(node.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetRule_id_or_at2(), *this); + auto tableAndView = TableKeyImpl(tableOrAt, {}, *this); + result.Keys = BuildTableKey(Context().Pos(), result.Service, result.Cluster, + TDeferredAtom(Context().Pos(), tableAndView.first), tableAndView.second); + break; } + case TRule_simple_table_ref_core::AltCase::kAltSimpleTableRefCore2: { + if (node.GetAlt_simple_table_ref_core2().HasBlock1()) { + if (!ClusterExpr(node.GetAlt_simple_table_ref_core2().GetBlock1().GetRule_cluster_expr1(), false, service, cluster)) { + return false; + } + } - result = TTableRef(Context().MakeName("table"), service, cluster, nullptr); - auto tableOrAt = Id(node.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetRule_id_or_at2(), *this); - auto tableAndView = TableKeyImpl(tableOrAt, {}, *this); - result.Keys = BuildTableKey(Context().Pos(), result.Service, result.Cluster, - TDeferredAtom(Context().Pos(), tableAndView.first), tableAndView.second); - break; - } - case TRule_simple_table_ref_core::AltCase::kAltSimpleTableRefCore2: { - if (node.GetAlt_simple_table_ref_core2().HasBlock1()) { - if (!ClusterExpr(node.GetAlt_simple_table_ref_core2().GetBlock1().GetRule_cluster_expr1(), false, service, cluster)) { + if (cluster.Empty()) { + Error() << "No cluster name given and no default cluster is selected"; return false; } - } - if (cluster.Empty()) { - Error() << "No cluster name given and no default cluster is selected"; - return false; - } + auto at = node.GetAlt_simple_table_ref_core2().HasBlock2(); + TString bindName; + if (!NamedNodeImpl(node.GetAlt_simple_table_ref_core2().GetRule_bind_parameter3(), bindName, *this)) { + return false; + } + auto named = GetNamedNode(bindName); + if (!named) { + return false; + } - auto at = node.GetAlt_simple_table_ref_core2().HasBlock2(); - TString bindName; - if (!NamedNodeImpl(node.GetAlt_simple_table_ref_core2().GetRule_bind_parameter3(), bindName, *this)) { - return false; - } - auto named = GetNamedNode(bindName); - if (!named) { - return false; + TDeferredAtom table; + MakeTableFromExpression(Context().Pos(), Context(), named, table); + result = TTableRef(Context().MakeName("table"), service, cluster, nullptr); + result.Keys = BuildTableKey(Context().Pos(), result.Service, result.Cluster, table, {at ? "@" : ""}); + break; } - - TDeferredAtom table; - MakeTableFromExpression(Context().Pos(), Context(), named, table); - result = TTableRef(Context().MakeName("table"), service, cluster, nullptr); - result.Keys = BuildTableKey(Context().Pos(), result.Service, result.Cluster, table, {at ? "@" : ""}); - break; - } - case TRule_simple_table_ref_core::AltCase::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_simple_table_ref_core::AltCase::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } return result.Keys != nullptr; @@ -3838,32 +3792,32 @@ TNodePtr TSqlTranslation::NamedNode(const TRule_named_nodes_stmt& rule, TVector< TNodePtr nodeExpr = nullptr; switch (rule.GetBlock3().Alt_case()) { - case TRule_named_nodes_stmt::TBlock3::kAlt1: { - TSqlExpression expr(Ctx_, Mode_); - auto result = expr.BuildSourceOrNode(rule.GetBlock3().GetAlt1().GetRule_expr1()); - if (TSourcePtr source = MoveOutIfSource(result)) { - result = BuildSourceNode(Ctx_.Pos(), std::move(source)); + case TRule_named_nodes_stmt::TBlock3::kAlt1: { + TSqlExpression expr(Ctx_, Mode_); + auto result = expr.BuildSourceOrNode(rule.GetBlock3().GetAlt1().GetRule_expr1()); + if (TSourcePtr source = MoveOutIfSource(result)) { + result = BuildSourceNode(Ctx_.Pos(), std::move(source)); + } + return result; } - return result; - } - case TRule_named_nodes_stmt::TBlock3::kAlt2:{ - const auto& subselect_rule = rule.GetBlock3().GetAlt2().GetRule_select_unparenthesized_stmt1(); + case TRule_named_nodes_stmt::TBlock3::kAlt2: { + const auto& subselect_rule = rule.GetBlock3().GetAlt2().GetRule_select_unparenthesized_stmt1(); - TPosition pos; - TSourcePtr source = TSqlSelect(Ctx_, Mode_).Build(subselect_rule, pos); + TPosition pos; + TSourcePtr source = TSqlSelect(Ctx_, Mode_).Build(subselect_rule, pos); - if (!source) { - return {}; - } + if (!source) { + return {}; + } - return BuildSourceNode(pos, std::move(source)); - } + return BuildSourceNode(pos, std::move(source)); + } - case TRule_named_nodes_stmt::TBlock3::ALT_NOT_SET: - AltNotImplemented("named_node", rule.GetBlock3()); - Ctx_.IncrementMonCounter("sql_errors", "UnknownNamedNode"); - return nullptr; + case TRule_named_nodes_stmt::TBlock3::ALT_NOT_SET: + AltNotImplemented("named_node", rule.GetBlock3()); + Ctx_.IncrementMonCounter("sql_errors", "UnknownNamedNode"); + return nullptr; } } @@ -3941,7 +3895,7 @@ bool TSqlTranslation::SortSpecificationList(const TRule_sort_specification_list& if (!SortSpecification(node.GetRule_sort_specification1(), sortSpecs)) { return false; } - for (auto sortSpec: node.GetBlock2()) { + for (auto sortSpec : node.GetBlock2()) { Token(sortSpec.GetToken1()); if (!SortSpecification(sortSpec.GetRule_sort_specification2(), sortSpecs)) { return false; @@ -3966,14 +3920,12 @@ bool TSqlTranslation::IsDistinctOptSet(const TRule_opt_set_quantifier& node, TPo bool TSqlTranslation::RoleNameClause(const TRule_role_name& node, TDeferredAtom& result, bool allowSystemRoles) { // role_name: an_id_or_type | bind_parameter; switch (node.Alt_case()) { - case TRule_role_name::kAltRoleName1: - { + case TRule_role_name::kAltRoleName1: { TString name = Id(node.GetAlt_role_name1().GetRule_an_id_or_type1(), *this); result = TDeferredAtom(Ctx_.Pos(), name); break; } - case TRule_role_name::kAltRoleName2: - { + case TRule_role_name::kAltRoleName2: { if (!BindParameterClause(node.GetAlt_role_name2().GetRule_bind_parameter1(), result)) { return false; } @@ -3984,7 +3936,7 @@ bool TSqlTranslation::RoleNameClause(const TRule_role_name& node, TDeferredAtom& } if (auto literalName = result.GetLiteral(); literalName && !allowSystemRoles) { - static const THashSet<TStringBuf> systemRoles = { "current_role", "current_user", "session_user" }; + static const THashSet<TStringBuf> systemRoles = {"current_role", "current_user", "session_user"}; if (systemRoles.contains(to_lower(*literalName))) { Ctx_.Error() << "System role " << to_upper(*literalName) << " can not be used here"; return false; @@ -4063,8 +4015,7 @@ bool TSqlTranslation::UserParameters(const std::vector<TRule_user_option>& optio // authentication_option: password_option | hash_option; switch (option.Alt_case()) { - case TRule_user_option::kAltUserOption1: - { + case TRule_user_option::kAltUserOption1: { if (used.contains(EUserOption::Authentication)) { Error() << "Conflicting or redundant options"; return false; @@ -4076,14 +4027,14 @@ bool TSqlTranslation::UserParameters(const std::vector<TRule_user_option>& optio switch (authenticationOption.Alt_case()) { case TRule_authentication_option::kAltAuthenticationOption1: { - if (!PasswordParameter(authenticationOption.GetAlt_authentication_option1().GetRule_password_option1(), result)){ + if (!PasswordParameter(authenticationOption.GetAlt_authentication_option1().GetRule_password_option1(), result)) { return false; } break; } case TRule_authentication_option::kAltAuthenticationOption2: { - if (!HashParameter(authenticationOption.GetAlt_authentication_option2().GetRule_hash_option1(), result)){ + if (!HashParameter(authenticationOption.GetAlt_authentication_option2().GetRule_hash_option1(), result)) { return false; } @@ -4096,8 +4047,7 @@ bool TSqlTranslation::UserParameters(const std::vector<TRule_user_option>& optio break; } - case TRule_user_option::kAltUserOption2: - { + case TRule_user_option::kAltUserOption2: { if (used.contains(EUserOption::Login)) { Error() << "Conflicting or redundant options"; return false; @@ -4109,8 +4059,7 @@ bool TSqlTranslation::UserParameters(const std::vector<TRule_user_option>& optio break; } - case TRule_user_option::ALT_NOT_SET: - { + case TRule_user_option::ALT_NOT_SET: { Y_ABORT("You should change implementation according to grammar changes"); } } @@ -4147,20 +4096,20 @@ bool TSqlTranslation::PermissionNameClause(const TRule_permission_id& node, TDef // | (USE | FULL) LEGACY? // | CREATE (DIRECTORY | TABLE | QUEUE)? - auto handleOneIdentifier = [&result, this] (const auto& permissionNameKeyword) { + auto handleOneIdentifier = [&result, this](const auto& permissionNameKeyword) { result = TDeferredAtom(Ctx_.Pos(), GetIdentifier(*this, permissionNameKeyword).Name); }; - auto handleTwoIdentifiers = [&result, this] (const auto& permissionNameKeyword) { + auto handleTwoIdentifiers = [&result, this](const auto& permissionNameKeyword) { const auto& token1 = permissionNameKeyword.GetToken1(); const auto& token2 = permissionNameKeyword.GetToken2(); TString identifierName = TIdentifier(TPosition(token1.GetColumn(), token1.GetLine()), Identifier(token1)).Name + - "_" + - TIdentifier(TPosition(token2.GetColumn(), token2.GetLine()), Identifier(token2)).Name; + "_" + + TIdentifier(TPosition(token2.GetColumn(), token2.GetLine()), Identifier(token2)).Name; result = TDeferredAtom(Ctx_.Pos(), identifierName); }; - auto handleOneOrTwoIdentifiers = [&result, this] (const auto& permissionNameKeyword) { + auto handleOneOrTwoIdentifiers = [&result, this](const auto& permissionNameKeyword) { TString identifierName = GetIdentifier(*this, permissionNameKeyword).Name; if (permissionNameKeyword.HasBlock2()) { identifierName += "_" + GetIdentifier(*this, permissionNameKeyword.GetBlock2()).Name; @@ -4169,74 +4118,62 @@ bool TSqlTranslation::PermissionNameClause(const TRule_permission_id& node, TDef }; switch (node.GetAltCase()) { - case TRule_permission_id::kAltPermissionId1: - { + case TRule_permission_id::kAltPermissionId1: { // CONNECT handleOneIdentifier(node.GetAlt_permission_id1()); break; } - case TRule_permission_id::kAltPermissionId2: - { + case TRule_permission_id::kAltPermissionId2: { // LIST handleOneIdentifier(node.GetAlt_permission_id2()); break; } - case TRule_permission_id::kAltPermissionId3: - { + case TRule_permission_id::kAltPermissionId3: { // INSERT handleOneIdentifier(node.GetAlt_permission_id3()); break; } - case TRule_permission_id::kAltPermissionId4: - { + case TRule_permission_id::kAltPermissionId4: { // MANAGE handleOneIdentifier(node.GetAlt_permission_id4()); break; } - case TRule_permission_id::kAltPermissionId5: - { + case TRule_permission_id::kAltPermissionId5: { // DROP handleOneIdentifier(node.GetAlt_permission_id5()); break; } - case TRule_permission_id::kAltPermissionId6: - { + case TRule_permission_id::kAltPermissionId6: { // GRANT handleOneIdentifier(node.GetAlt_permission_id6()); break; } - case TRule_permission_id::kAltPermissionId7: - { + case TRule_permission_id::kAltPermissionId7: { // MODIFY (TABLES | ATTRIBUTES) handleTwoIdentifiers(node.GetAlt_permission_id7()); break; } - case TRule_permission_id::kAltPermissionId8: - { + case TRule_permission_id::kAltPermissionId8: { // (UPDATE | ERASE) ROW handleTwoIdentifiers(node.GetAlt_permission_id8()); break; } - case TRule_permission_id::kAltPermissionId9: - { + case TRule_permission_id::kAltPermissionId9: { // (REMOVE | DESCRIBE | ALTER) SCHEMA handleTwoIdentifiers(node.GetAlt_permission_id9()); break; } - case TRule_permission_id::kAltPermissionId10: - { + case TRule_permission_id::kAltPermissionId10: { // SELECT (TABLES | ATTRIBUTES | ROW)? handleOneOrTwoIdentifiers(node.GetAlt_permission_id10()); break; } - case TRule_permission_id::kAltPermissionId11: - { + case TRule_permission_id::kAltPermissionId11: { // (USE | FULL) LEGACY? handleOneOrTwoIdentifiers(node.GetAlt_permission_id11()); break; } - case TRule_permission_id::kAltPermissionId12: - { + case TRule_permission_id::kAltPermissionId12: { // CREATE (DIRECTORY | TABLE | QUEUE)? handleOneOrTwoIdentifiers(node.GetAlt_permission_id12()); break; @@ -4250,13 +4187,11 @@ bool TSqlTranslation::PermissionNameClause(const TRule_permission_id& node, TDef bool TSqlTranslation::PermissionNameClause(const TRule_permission_name& node, TDeferredAtom& result) { // permission_name: permission_id | STRING_VALUE; switch (node.Alt_case()) { - case TRule_permission_name::kAltPermissionName1: - { + case TRule_permission_name::kAltPermissionName1: { return PermissionNameClause(node.GetAlt_permission_name1().GetRule_permission_id1(), result); break; } - case TRule_permission_name::kAltPermissionName2: - { + case TRule_permission_name::kAltPermissionName2: { const TString stringValue(Ctx_.Token(node.GetAlt_permission_name2().GetToken1())); auto unescaped = StringContent(Ctx_, Ctx_.Pos(), stringValue); if (!unescaped) { @@ -4274,8 +4209,7 @@ bool TSqlTranslation::PermissionNameClause(const TRule_permission_name& node, TD bool TSqlTranslation::PermissionNameClause(const TRule_permission_name_target& node, TVector<TDeferredAtom>& result, bool withGrantOption) { // permission_name_target: permission_name (COMMA permission_name)* COMMA? | ALL PRIVILEGES?; switch (node.Alt_case()) { - case TRule_permission_name_target::kAltPermissionNameTarget1: - { + case TRule_permission_name_target::kAltPermissionNameTarget1: { const auto& permissionNameRule = node.GetAlt_permission_name_target1(); result.emplace_back(); if (!PermissionNameClause(permissionNameRule.GetRule_permission_name1(), result.back())) { @@ -4289,8 +4223,7 @@ bool TSqlTranslation::PermissionNameClause(const TRule_permission_name_target& n } break; } - case TRule_permission_name_target::kAltPermissionNameTarget2: - { + case TRule_permission_name_target::kAltPermissionNameTarget2: { result.emplace_back(Ctx_.Pos(), "all_privileges"); break; } @@ -4343,7 +4276,6 @@ bool TSqlTranslation::ParseBackupCollectionSettings(std::map<TString, TDeferredA return true; } - bool TSqlTranslation::ParseBackupCollectionSettings(std::map<TString, TDeferredAtom>& result, std::set<TString>& toReset, const TRule_alter_backup_collection_actions& actions) { auto parseAction = [&](auto& actionVariant) { switch (actionVariant.Alt_case()) { @@ -4384,7 +4316,6 @@ bool TSqlTranslation::ParseBackupCollectionSettings(std::map<TString, TDeferredA } } - return true; } @@ -4450,17 +4381,19 @@ bool TSqlTranslation::ParseBackupCollectionEntries( return true; } - TString TSqlTranslation::FrameSettingsToString(EFrameSettings settings, bool isUnbounded) { TString result; switch (settings) { case FramePreceding: - result = "PRECEDING"; break; + result = "PRECEDING"; + break; case FrameCurrentRow: YQL_ENSURE(!isUnbounded); - result = "CURRENT ROW"; break; + result = "CURRENT ROW"; + break; case FrameFollowing: - result = "FOLLOWING"; break; + result = "FOLLOWING"; + break; default: Y_ABORT("Unexpected frame settings"); } @@ -4548,8 +4481,8 @@ bool TSqlTranslation::IsValidFrameSettings(TContext& ctx, const TFrameSpecificat if (*beginValue > *endValue) { YQL_ENSURE(begin.Bound); if (!ctx.Warning(begin.Bound->GetPos(), TIssuesIds::YQL_EMPTY_WINDOW_FRAME, [](auto& out) { - out << "Used frame specification implies empty window frame"; - })) { + out << "Used frame specification implies empty window frame"; + })) { return false; } } @@ -4711,13 +4644,12 @@ TWindowSpecificationPtr TSqlTranslation::WindowSpecification(const TRule_window_ // "PARTITION BY (), foo(x) as y, (), (z)" is allowed and will work exactly the same as // "PARTITION BY foo(x) as y, z" auto removed = std::remove_if(winSpecPtr->Partitions.begin(), winSpecPtr->Partitions.end(), - [](const TNodePtr& partitionNode) { - return !partitionNode->GetLabel() && !partitionNode->GetColumnName() && - partitionNode->GetTupleNode() != nullptr && - partitionNode->GetTupleSize() == 0; - }); + [](const TNodePtr& partitionNode) { + return !partitionNode->GetLabel() && !partitionNode->GetColumnName() && + partitionNode->GetTupleNode() != nullptr && + partitionNode->GetTupleSize() == 0; + }); winSpecPtr->Partitions.erase(removed, winSpecPtr->Partitions.end()); - } if (rule.HasBlock3()) { if (!OrderByClause(rule.GetBlock3().GetRule_window_order_clause1().GetRule_order_by_clause1(), winSpecPtr->OrderBy)) { @@ -4754,7 +4686,7 @@ TWindowSpecificationPtr TSqlTranslation::WindowSpecification(const TRule_window_ } // Normalize and simplify - auto replaceCurrentWith = [](TFrameBound& frame, bool preceding, TNodePtr value ) { + auto replaceCurrentWith = [](TFrameBound& frame, bool preceding, TNodePtr value) { frame.Settings = preceding ? EFrameSettings::FramePreceding : EFrameSettings::FrameFollowing; frame.Bound = value; }; @@ -4796,95 +4728,95 @@ TWindowSpecificationPtr TSqlTranslation::WindowSpecification(const TRule_window_ TNodePtr TSqlTranslation::DoStatement(const TRule_do_stmt& stmt, bool makeLambda, const TVector<TString>& args) { switch (stmt.GetBlock2().Alt_case()) { - case TRule_do_stmt_TBlock2::kAlt1: { - const auto& callAction = stmt.GetBlock2().GetAlt1().GetRule_call_action1(); - TNodePtr action; - switch (callAction.GetBlock1().GetAltCase()) { - case TRule_call_action_TBlock1::kAlt1: { - TString bindName; - if (!NamedNodeImpl(callAction.GetBlock1().GetAlt1().GetRule_bind_parameter1(), bindName, *this)) { - return nullptr; + case TRule_do_stmt_TBlock2::kAlt1: { + const auto& callAction = stmt.GetBlock2().GetAlt1().GetRule_call_action1(); + TNodePtr action; + switch (callAction.GetBlock1().GetAltCase()) { + case TRule_call_action_TBlock1::kAlt1: { + TString bindName; + if (!NamedNodeImpl(callAction.GetBlock1().GetAlt1().GetRule_bind_parameter1(), bindName, *this)) { + return nullptr; + } + action = GetNamedNode(bindName); + if (!action) { + return nullptr; + } + break; + } + case TRule_call_action_TBlock1::kAlt2: + action = BuildEmptyAction(Ctx_.Pos()); + break; + case TRule_call_action_TBlock1::ALT_NOT_SET: + Ctx_.IncrementMonCounter("sql_errors", "UnknownDoStmt"); + AltNotImplemented("do_stmt", callAction.GetBlock1()); + return nullptr; } - action = GetNamedNode(bindName); - if (!action) { + + TVector<TNodePtr> values; + values.push_back(new TAstAtomNodeImpl(Ctx_.Pos(), "Apply", TNodeFlags::Default)); + values.push_back(action); + values.push_back(new TAstAtomNodeImpl(Ctx_.Pos(), "world", TNodeFlags::Default)); + + TSqlExpression sqlExpr(Ctx_, Mode_); + if (callAction.HasBlock3() && !ExprList(sqlExpr, values, callAction.GetBlock3().GetRule_expr_list1())) { return nullptr; } - break; - } - case TRule_call_action_TBlock1::kAlt2: - action = BuildEmptyAction(Ctx_.Pos()); - break; - case TRule_call_action_TBlock1::ALT_NOT_SET: - Ctx_.IncrementMonCounter("sql_errors", "UnknownDoStmt"); - AltNotImplemented("do_stmt", callAction.GetBlock1()); - return nullptr; - } - TVector<TNodePtr> values; - values.push_back(new TAstAtomNodeImpl(Ctx_.Pos(), "Apply", TNodeFlags::Default)); - values.push_back(action); - values.push_back(new TAstAtomNodeImpl(Ctx_.Pos(), "world", TNodeFlags::Default)); - - TSqlExpression sqlExpr(Ctx_, Mode_); - if (callAction.HasBlock3() && !ExprList(sqlExpr, values, callAction.GetBlock3().GetRule_expr_list1())) { - return nullptr; - } + TNodePtr apply = new TAstListNodeImpl(Ctx_.Pos(), std::move(values)); + if (!makeLambda) { + return BuildDoCall(Ctx_.Pos(), apply); + } - TNodePtr apply = new TAstListNodeImpl(Ctx_.Pos(), std::move(values)); - if (!makeLambda) { - return BuildDoCall(Ctx_.Pos(), apply); - } + TNodePtr params = new TAstListNodeImpl(Ctx_.Pos()); + params->Add("world"); + for (const auto& arg : args) { + params->Add(new TAstAtomNodeImpl(Ctx_.Pos(), arg, TNodeFlags::ArbitraryContent)); + } - TNodePtr params = new TAstListNodeImpl(Ctx_.Pos()); - params->Add("world"); - for (const auto& arg : args) { - params->Add(new TAstAtomNodeImpl(Ctx_.Pos(), arg, TNodeFlags::ArbitraryContent)); + return BuildDoCall(Ctx_.Pos(), BuildLambda(Ctx_.Pos(), params, apply)); } + case TRule_do_stmt_TBlock2::kAlt2: { + const auto& inlineAction = stmt.GetBlock2().GetAlt2().GetRule_inline_action1(); + const auto& body = inlineAction.GetRule_define_action_or_subquery_body2(); - return BuildDoCall(Ctx_.Pos(), BuildLambda(Ctx_.Pos(), params, apply)); - } - case TRule_do_stmt_TBlock2::kAlt2: { - const auto& inlineAction = stmt.GetBlock2().GetAlt2().GetRule_inline_action1(); - const auto& body = inlineAction.GetRule_define_action_or_subquery_body2(); + auto saveScoped = Ctx_.Scoped; + Ctx_.Scoped = MakeIntrusive<TScopedState>(); + Ctx_.AllScopes.push_back(Ctx_.Scoped); + *Ctx_.Scoped = *saveScoped; + Ctx_.Scoped->Local = TScopedState::TLocal{}; + Ctx_.ScopeLevel++; + TSqlQuery query(Ctx_, Ctx_.Settings.Mode, false); + TBlocks innerBlocks; - auto saveScoped = Ctx_.Scoped; - Ctx_.Scoped = MakeIntrusive<TScopedState>(); - Ctx_.AllScopes.push_back(Ctx_.Scoped); - *Ctx_.Scoped = *saveScoped; - Ctx_.Scoped->Local = TScopedState::TLocal{}; - Ctx_.ScopeLevel++; - TSqlQuery query(Ctx_, Ctx_.Settings.Mode, false); - TBlocks innerBlocks; + const bool hasValidBody = DefineActionOrSubqueryBody(query, innerBlocks, body); + auto ret = hasValidBody ? BuildQuery(Ctx_.Pos(), innerBlocks, false, Ctx_.Scoped, Ctx_.SeqMode) : nullptr; + if (!WarnUnusedNodes()) { + return nullptr; + } + Ctx_.ScopeLevel--; + Ctx_.Scoped = saveScoped; - const bool hasValidBody = DefineActionOrSubqueryBody(query, innerBlocks, body); - auto ret = hasValidBody ? BuildQuery(Ctx_.Pos(), innerBlocks, false, Ctx_.Scoped, Ctx_.SeqMode) : nullptr; - if (!WarnUnusedNodes()) { - return nullptr; - } - Ctx_.ScopeLevel--; - Ctx_.Scoped = saveScoped; + if (!ret) { + return {}; + } - if (!ret) { - return {}; - } + TNodePtr blockNode = new TAstListNodeImpl(Ctx_.Pos()); + blockNode->Add("block"); + blockNode->Add(blockNode->Q(ret)); + if (!makeLambda) { + return blockNode; + } - TNodePtr blockNode = new TAstListNodeImpl(Ctx_.Pos()); - blockNode->Add("block"); - blockNode->Add(blockNode->Q(ret)); - if (!makeLambda) { - return blockNode; - } + TNodePtr params = new TAstListNodeImpl(Ctx_.Pos()); + params->Add("world"); + for (const auto& arg : args) { + params->Add(new TAstAtomNodeImpl(Ctx_.Pos(), arg, TNodeFlags::ArbitraryContent)); + } - TNodePtr params = new TAstListNodeImpl(Ctx_.Pos()); - params->Add("world"); - for (const auto& arg : args) { - params->Add(new TAstAtomNodeImpl(Ctx_.Pos(), arg, TNodeFlags::ArbitraryContent)); + return BuildLambda(Ctx_.Pos(), params, blockNode); } - - return BuildLambda(Ctx_.Pos(), params, blockNode); - } - case TRule_do_stmt_TBlock2::ALT_NOT_SET: - Y_ABORT("You should change implementation according to grammar changes"); + case TRule_do_stmt_TBlock2::ALT_NOT_SET: + Y_ABORT("You should change implementation according to grammar changes"); } } @@ -4998,10 +4930,8 @@ bool TSqlTranslation::DefineActionOrSubqueryStatement(const TRule_define_action_ lambda = BuildLambda(Ctx_.Pos(), params, blockNode); if (optionalArgumentsCount > 0) { - lambda = new TCallNodeImpl(Ctx_.Pos(), "WithOptionalArgs", { - lambda, - BuildQuotedAtom(Ctx_.Pos(), ToString(optionalArgumentsCount), TNodeFlags::Default) - }); + lambda = new TCallNodeImpl(Ctx_.Pos(), "WithOptionalArgs", {lambda, + BuildQuotedAtom(Ctx_.Pos(), ToString(optionalArgumentsCount), TNodeFlags::Default)}); } nameAndPos.Name = actionName; @@ -5045,7 +4975,7 @@ TNodePtr TSqlTranslation::ForStatement(const TRule_for_stmt& stmt) { auto exprNode = expr.Build(stmt.GetRule_expr6()); if (!exprNode) { - return{}; + return {}; } itemArgName = PushNamedAtom(itemArgNamePos, itemArgName); @@ -5053,7 +4983,7 @@ TNodePtr TSqlTranslation::ForStatement(const TRule_for_stmt& stmt) { ++Ctx_.ParallelModeCount; } - auto bodyNode = DoStatement(stmt.GetRule_do_stmt7(), true, { itemArgName }); + auto bodyNode = DoStatement(stmt.GetRule_do_stmt7(), true, {itemArgName}); if (isParallel) { --Ctx_.ParallelModeCount; } @@ -5063,14 +4993,14 @@ TNodePtr TSqlTranslation::ForStatement(const TRule_for_stmt& stmt) { } if (!bodyNode) { - return{}; + return {}; } TNodePtr elseNode; if (stmt.HasBlock8()) { elseNode = DoStatement(stmt.GetBlock8().GetRule_do_stmt2(), true); if (!elseNode) { - return{}; + return {}; } } @@ -5094,21 +5024,18 @@ bool TSqlTranslation::BindParameterClause(const TRule_bind_parameter& node, TDef bool TSqlTranslation::ObjectFeatureValueClause(const TRule_object_feature_value& node, TDeferredAtom& result) { // object_feature_value: id_or_type | bind_parameter | STRING_VALUE | bool_value; switch (node.Alt_case()) { - case TRule_object_feature_value::kAltObjectFeatureValue1: - { + case TRule_object_feature_value::kAltObjectFeatureValue1: { TString name = Id(node.GetAlt_object_feature_value1().GetRule_id_or_type1(), *this); result = TDeferredAtom(Ctx_.Pos(), name); break; } - case TRule_object_feature_value::kAltObjectFeatureValue2: - { + case TRule_object_feature_value::kAltObjectFeatureValue2: { if (!BindParameterClause(node.GetAlt_object_feature_value2().GetRule_bind_parameter1(), result)) { return false; } break; } - case TRule_object_feature_value::kAltObjectFeatureValue3: - { + case TRule_object_feature_value::kAltObjectFeatureValue3: { auto strValue = StringContent(Ctx_, Ctx_.Pos(), Ctx_.Token(node.GetAlt_object_feature_value3().GetToken1())); if (!strValue) { Error() << "Cannot parse string correctly: " << Ctx_.Token(node.GetAlt_object_feature_value3().GetToken1()); @@ -5117,8 +5044,7 @@ bool TSqlTranslation::ObjectFeatureValueClause(const TRule_object_feature_value& result = TDeferredAtom(Ctx_.Pos(), strValue->Content); break; } - case TRule_object_feature_value::kAltObjectFeatureValue4: - { + case TRule_object_feature_value::kAltObjectFeatureValue4: { TString value = Ctx_.Token(node.GetAlt_object_feature_value4().GetRule_bool_value1().GetToken1()); result = TDeferredAtom(BuildLiteralBool(Ctx_.Pos(), FromString<bool>(value)), Ctx_); break; @@ -5190,7 +5116,7 @@ bool TSqlTranslation::StoreDataSourceSettingsEntry(const TRule_alter_table_setti bool TSqlTranslation::ParseExternalDataSourceSettings(std::map<TString, TDeferredAtom>& result, const TRule_with_table_settings& settingsNode) { const auto& firstEntry = settingsNode.GetRule_table_settings_entry3(); if (!StoreDataSourceSettingsEntry(IdEx(firstEntry.GetRule_an_id1(), *this), &firstEntry.GetRule_table_setting_value3(), - result)) { + result)) { return false; } for (auto& block : settingsNode.GetBlock4()) { @@ -5248,8 +5174,7 @@ bool TSqlTranslation::ParseExternalDataSourceSettings(std::map<TString, TDeferre bool TSqlTranslation::StoreSecretInheritPermissions( const TRule_secret_setting_value& value, const TString& key, - TSecretParameters& secretParams -) { + TSecretParameters& secretParams) { if (secretParams.InheritPermissions) { Error() << "Duplicate parameter: " << key; return false; @@ -5287,8 +5212,7 @@ bool TSqlTranslation::StoreSecretInheritPermissions( bool TSqlTranslation::StoreSecretValue( const TRule_secret_setting_value& value, const TString& key, - TSecretParameters& secretParams -) { + TSecretParameters& secretParams) { if (secretParams.Value) { Error() << "Duplicate parameter: " << key; return false; @@ -5345,15 +5269,13 @@ bool TSqlTranslation::ParseSecretSettings( const TPosition pos, const TRule_with_secret_settings& settingsNode, TSecretParameters& secretParams, - const TSecretParameters::TOperationMode mode -) { + const TSecretParameters::TOperationMode mode) { // with_secret_settings: WITH LPAREN secret_setting_entry (COMMA secret_setting_entry)* RPAREN; auto tryStoreEntry = [&](const auto& entry) -> bool { return StoreSecretSettingEntry( IdEx(entry.GetRule_an_id1(), *this), entry.GetRule_secret_setting_value3(), - secretParams - ); + secretParams); }; const auto& firstEntry = settingsNode.GetRule_secret_setting_entry3(); @@ -5394,16 +5316,14 @@ bool TSqlTranslation::ValidateAuthMethod(const std::map<TString, TDeferredAtom>& "aws_access_key_id_secret_name", "aws_secret_access_key_secret_name", "aws_region", - "token_secret_name" - }; + "token_secret_name"}; const static TMap<TStringBuf, TSet<TStringBuf>> authMethodFields{ {"NONE", {}}, {"SERVICE_ACCOUNT", {"service_account_id", "service_account_secret_name"}}, {"BASIC", {"login", "password_secret_name"}}, {"AWS", {"aws_access_key_id_secret_name", "aws_secret_access_key_secret_name", "aws_region"}}, {"MDB_BASIC", {"service_account_id", "service_account_secret_name", "login", "password_secret_name"}}, - {"TOKEN", {"token_secret_name"}} - }; + {"TOKEN", {"token_secret_name"}}}; auto authMethodIt = result.find("auth_method"); if (authMethodIt == result.end() || authMethodIt->second.GetLiteral() == nullptr) { Ctx_.Error() << "AUTH_METHOD requires key"; @@ -5416,7 +5336,7 @@ bool TSqlTranslation::ValidateAuthMethod(const std::map<TString, TDeferredAtom>& return false; } const auto& currentAuthFields = it->second; - for (const auto& authField: allAuthFields) { + for (const auto& authField : allAuthFields) { if (currentAuthFields.contains(authField) && !result.contains(TString{authField})) { Ctx_.Error() << to_upper(TString{authField}) << " requires key"; return false; @@ -5454,14 +5374,13 @@ bool TSqlTranslation::ValidateExternalTable(const TCreateTableParameters& params bool TSqlTranslation::ParseViewQuery( std::map<TString, TDeferredAtom>& features, - const TRule_select_stmt& query -) { + const TRule_select_stmt& query) { TStringBuilder queryText; if (!BuildContextRecreationQuery(Ctx_, queryText)) { return false; } queryText << CollectTokens(query); - features["query_text"] = { Ctx_.Pos(), queryText }; + features["query_text"] = {Ctx_.Pos(), queryText}; // The AST is needed solely for the validation of the CREATE VIEW statement. // The final storage format for the query is a plain text, not an AST. @@ -5469,7 +5388,7 @@ bool TSqlTranslation::ParseViewQuery( if (!viewSelect) { return false; } - features["query_ast"] = { viewSelect, Ctx_ }; + features["query_ast"] = {viewSelect, Ctx_}; return true; } @@ -5554,7 +5473,6 @@ std::string::size_type GetQueryPosition(const TString& query, const NSQLv1Genera bool TSqlTranslation::ParseTransferLambda( TString& lambdaText, const TRule_lambda_or_parameter& lambdaOrParameter) { - TSqlExpression expr(Ctx_, Ctx_.Settings.Mode); auto result = expr.Build(lambdaOrParameter); if (!result) { @@ -5569,7 +5487,7 @@ bool TSqlTranslation::ParseTransferLambda( return !lambdaText.empty(); } -class TReturningListColumns : public INode { +class TReturningListColumns: public INode { public: TReturningListColumns(TPosition pos) : INode(pos) @@ -5581,7 +5499,7 @@ public: Star_ = true; } - void AddColumn(const NSQLv1Generated::TRule_an_id & rule, TTranslation& ctx) { + void AddColumn(const NSQLv1Generated::TRule_an_id& rule, TTranslation& ctx) { ColumnNames_.push_back(NSQLTranslationV1::Id(rule, ctx)); } @@ -5821,9 +5739,8 @@ bool TSqlTranslation::ParseStreamingQuerySetting(const TRule_streaming_query_set } case TRule_streaming_query_setting_value::kAltStreamingQuerySettingValue3: { it->second = TDeferredAtom(BuildLiteralBool( - Ctx_.Pos(), - FromString<bool>(Ctx_.Token(valueNode.GetAlt_streaming_query_setting_value3().GetRule_bool_value1().GetToken1())) - ), Ctx_); + Ctx_.Pos(), + FromString<bool>(Ctx_.Token(valueNode.GetAlt_streaming_query_setting_value3().GetRule_bool_value1().GetToken1()))), Ctx_); break; } case TRule_streaming_query_setting_value::ALT_NOT_SET: { @@ -5862,7 +5779,7 @@ bool TSqlTranslation::ParseStreamingQueryDefinition(const TRule_streaming_query_ // Save query ast to perform type check and validation of allowed expressions const auto saveScoped = Ctx_.Scoped; - Ctx_.Scoped = Ctx_.CreateScopedState(); // Reset scoped context to interrupt inheritance of global settings and named nodes + Ctx_.Scoped = Ctx_.CreateScopedState(); // Reset scoped context to interrupt inheritance of global settings and named nodes Ctx_.AllScopes.push_back(Ctx_.Scoped); Ctx_.Scoped->Local = TScopedState::TLocal{}; Ctx_.ScopeLevel++; diff --git a/yql/essentials/sql/v1/sql_translation.h b/yql/essentials/sql/v1/sql_translation.h index 6858ee3a588..5c56b2537f0 100644 --- a/yql/essentials/sql/v1/sql_translation.h +++ b/yql/essentials/sql/v1/sql_translation.h @@ -80,7 +80,7 @@ TString Id(const TRule_an_id_hint& node, TTranslation& ctx); TString Id(const TRule_an_id_pure& node, TTranslation& ctx); -template<typename TRule> +template <typename TRule> inline TIdentifier IdEx(const TRule& node, TTranslation& ctx) { const TString name(Id(node, ctx)); const TPosition pos(ctx.Context().Pos()); @@ -147,7 +147,7 @@ protected: bool ActionOrSubqueryArgs(const TRule_action_or_subquery_args& node, TVector<TSymbolNameWithPos>& bindNames, ui32& optionalArgsCount); bool ModulePath(const TRule_module_path& node, TVector<TString>& path); bool NamedBindList(const TRule_named_bind_parameter_list& node, TVector<TSymbolNameWithPos>& names, - TVector<TSymbolNameWithPos>& aliases); + TVector<TSymbolNameWithPos>& aliases); bool NamedBindParam(const TRule_named_bind_parameter& node, TSymbolNameWithPos& name, TSymbolNameWithPos& alias); TNodePtr NamedNode(const TRule_named_nodes_stmt& rule, TVector<TSymbolNameWithPos>& names); @@ -171,11 +171,11 @@ protected: bool FillFamilySettings(const TRule_family_settings& settingsNode, TFamilyEntry& family); bool CreateTableSettings(const TRule_with_table_settings& settingsNode, TCreateTableParameters& params); bool StoreTableSettingsEntry(const TIdentifier& id, const TRule_table_setting_value* value, TTableSettings& settings, - ETableType tableType, bool alter, bool reset); + ETableType tableType, bool alter, bool reset); bool StoreTableSettingsEntry(const TIdentifier& id, const TRule_table_setting_value* value, TTableSettings& settings, - bool alter, bool reset); + bool alter, bool reset); bool StoreExternalTableSettingsEntry(const TIdentifier& id, const TRule_table_setting_value* value, TTableSettings& settings, - bool alter, bool reset); + bool alter, bool reset); bool StoreTableSettingsEntry(const TIdentifier& id, const TRule_table_setting_value& value, TTableSettings& settings, ETableType tableType, bool alter = false); bool StoreDataSourceSettingsEntry(const TIdentifier& id, const TRule_table_setting_value* value, std::map<TString, TDeferredAtom>& result); bool StoreDataSourceSettingsEntry(const TRule_alter_table_setting_entry& entry, std::map<TString, TDeferredAtom>& result); @@ -192,7 +192,7 @@ protected: bool FillIndexSettings(const TRule_with_index_settings& settingsNode, TIndexDescription::TIndexSettings& indexSettings); bool AddIndexSetting(const TIdentifier& id, const TRule_index_setting_value& value, TIndexDescription::TIndexSettings& indexSettings); TString GetIndexSettingStringValue(const TRule_index_setting_value& node); - template<typename T> + template <typename T> std::tuple<bool, T, TString> GetIndexSettingValue(const TRule_index_setting_value& node); TIdentifier GetTopicConsumerId(const TRule_topic_consumer_ref& node); @@ -208,10 +208,8 @@ protected: bool AlterTopicConsumerEntry(const TRule_alter_topic_alter_consumer_entry& node, TTopicConsumerDescription& alterConsumer); - bool AlterTopicAction(const TRule_alter_topic_action& node, TAlterTopicParameters& params); - TNodePtr TypeSimple(const TRule_type_name_simple& node, bool onlyDataAllowed); TNodePtr TypeDecimal(const TRule_type_name_decimal& node); TNodePtr AddOptionals(const TNodePtr& node, size_t optionalCount); @@ -292,6 +290,7 @@ protected: bool ValidateExternalTable(const TCreateTableParameters& params); TNodePtr ReturningList(const ::NSQLv1Generated::TRule_returning_columns_list& columns); + private: bool SimpleTableRefCoreImpl(const TRule_simple_table_ref_core& node, TTableRef& result); static bool IsValidFrameSettings(TContext& ctx, const TFrameSpecification& frameSpec, size_t sortSpecSize); @@ -314,54 +313,54 @@ TNodePtr LiteralNumber(TContext& ctx, const TRule_integer& node); bool StoreString(const TRule_family_setting_value& from, TNodePtr& to, TContext& ctx); bool StoreInt(const TRule_family_setting_value& from, TNodePtr& to, TContext& ctx); -template<typename TChar> +template <typename TChar> struct TPatternComponent { - TBasicString<TChar> Prefix; - TBasicString<TChar> Suffix; - bool IsSimple = true; + TBasicString<TChar> Prefix; + TBasicString<TChar> Suffix; + bool IsSimple = true; - void AppendPlain(TChar c) { - if (IsSimple) { - Prefix.push_back(c); - } - Suffix.push_back(c); + void AppendPlain(TChar c) { + if (IsSimple) { + Prefix.push_back(c); } + Suffix.push_back(c); + } - void AppendAnyChar() { - IsSimple = false; - Suffix.clear(); - } + void AppendAnyChar() { + IsSimple = false; + Suffix.clear(); + } }; -template<typename TChar> +template <typename TChar> TVector<TPatternComponent<TChar>> SplitPattern(const TBasicString<TChar>& pattern, TMaybe<char> escape, bool& inEscape) { - inEscape = false; - TVector<TPatternComponent<TChar>> result; - TPatternComponent<TChar> current; - bool prevIsPercentChar = false; - for (const TChar c : pattern) { - if (inEscape) { - current.AppendPlain(c); - inEscape = false; - prevIsPercentChar = false; - } else if (escape && c == static_cast<TChar>(*escape)) { - inEscape = true; - } else if (c == '%') { - if (!prevIsPercentChar) { - result.push_back(std::move(current)); - } - current = {}; - prevIsPercentChar = true; - } else if (c == '_') { - current.AppendAnyChar(); - prevIsPercentChar = false; - } else { - current.AppendPlain(c); - prevIsPercentChar = false; + inEscape = false; + TVector<TPatternComponent<TChar>> result; + TPatternComponent<TChar> current; + bool prevIsPercentChar = false; + for (const TChar c : pattern) { + if (inEscape) { + current.AppendPlain(c); + inEscape = false; + prevIsPercentChar = false; + } else if (escape && c == static_cast<TChar>(*escape)) { + inEscape = true; + } else if (c == '%') { + if (!prevIsPercentChar) { + result.push_back(std::move(current)); } + current = {}; + prevIsPercentChar = true; + } else if (c == '_') { + current.AppendAnyChar(); + prevIsPercentChar = false; + } else { + current.AppendPlain(c); + prevIsPercentChar = false; } - result.push_back(std::move(current)); - return result; + } + result.push_back(std::move(current)); + return result; } bool ParseNumbers(TContext& ctx, const TString& strOrig, ui64& value, TString& suffix); diff --git a/yql/essentials/sql/v1/sql_ut.cpp b/yql/essentials/sql/v1/sql_ut.cpp index c29c49ee59a..8abf46bbb02 100644 --- a/yql/essentials/sql/v1/sql_ut.cpp +++ b/yql/essentials/sql/v1/sql_ut.cpp @@ -30,14 +30,14 @@ TParsedTokenList Tokenize(const TString& query) { return tokens; } -} +} // namespace #define ANTLR_VER 3 #include "sql_ut_common.h" Y_UNIT_TEST_SUITE(QuerySplit) { - Y_UNIT_TEST(Simple) { - TString query = R"( +Y_UNIT_TEST(Simple) { + TString query = R"( ; -- Comment 1 SELECT * From Input; -- Comment 2 @@ -63,29 +63,29 @@ Y_UNIT_TEST_SUITE(QuerySplit) { )"; - google::protobuf::Arena Arena; + google::protobuf::Arena Arena; - NSQLTranslation::TTranslationSettings settings; - settings.AnsiLexer = false; - settings.Antlr4Parser = false; - settings.Arena = &Arena; + NSQLTranslation::TTranslationSettings settings; + settings.AnsiLexer = false; + settings.Antlr4Parser = false; + settings.Arena = &Arena; - TVector<TString> statements; - NYql::TIssues issues; + TVector<TString> statements; + NYql::TIssues issues; - NSQLTranslationV1::TLexers lexers; - lexers.Antlr3 = NSQLTranslationV1::MakeAntlr3LexerFactory(); - NSQLTranslationV1::TParsers parsers; - parsers.Antlr3 = NSQLTranslationV1::MakeAntlr3ParserFactory(); + NSQLTranslationV1::TLexers lexers; + lexers.Antlr3 = NSQLTranslationV1::MakeAntlr3LexerFactory(); + NSQLTranslationV1::TParsers parsers; + parsers.Antlr3 = NSQLTranslationV1::MakeAntlr3ParserFactory(); - UNIT_ASSERT(NSQLTranslationV1::SplitQueryToStatements(lexers, parsers, query, statements, issues, settings)); + UNIT_ASSERT(NSQLTranslationV1::SplitQueryToStatements(lexers, parsers, query, statements, issues, settings)); - UNIT_ASSERT_VALUES_EQUAL(statements.size(), 3); + UNIT_ASSERT_VALUES_EQUAL(statements.size(), 3); - UNIT_ASSERT_VALUES_EQUAL(statements[0], "-- Comment 1\n SELECT * From Input; -- Comment 2\n"); - UNIT_ASSERT_VALUES_EQUAL(statements[1], R"(-- Comment 3 + UNIT_ASSERT_VALUES_EQUAL(statements[0], "-- Comment 1\n SELECT * From Input; -- Comment 2\n"); + UNIT_ASSERT_VALUES_EQUAL(statements[1], R"(-- Comment 3 $a = "a";)"); - UNIT_ASSERT_VALUES_EQUAL(statements[2], R"(-- Comment 10 + UNIT_ASSERT_VALUES_EQUAL(statements[2], R"(-- Comment 10 -- Comment 8 @@ -94,5 +94,5 @@ Y_UNIT_TEST_SUITE(QuerySplit) { return /* Comment 5 */ $x; -- Comment 6 };)"); - } } +} // Y_UNIT_TEST_SUITE(QuerySplit) diff --git a/yql/essentials/sql/v1/sql_ut.h b/yql/essentials/sql/v1/sql_ut.h index ac6e410b5dd..feb2403e39d 100644 --- a/yql/essentials/sql/v1/sql_ut.h +++ b/yql/essentials/sql/v1/sql_ut.h @@ -1,3 +1,4 @@ +#pragma once #include <yql/essentials/providers/common/provider/yql_provider_names.h> #include <yql/essentials/sql/sql.h> @@ -35,7 +36,7 @@ inline TString Err2Str(const NYql::TAstParseResult& res, EDebugOutput debug = ED } inline NYql::TAstParseResult SqlToYqlWithMode(const TString& query, NSQLTranslation::ESqlMode mode = NSQLTranslation::ESqlMode::QUERY, size_t maxErrors = 10, const TString& provider = {}, - EDebugOutput debug = EDebugOutput::None, bool ansiLexer = false, NSQLTranslation::TTranslationSettings settings = {}) + EDebugOutput debug = EDebugOutput::None, bool ansiLexer = false, NSQLTranslation::TTranslationSettings settings = {}) { google::protobuf::Arena arena; const auto service = provider ? provider : TString(NYql::YtProviderName); @@ -60,8 +61,7 @@ inline NYql::TAstParseResult SqlToYqlWithMode(const TString& query, NSQLTranslat NSQLTranslation::TTranslators translators( nullptr, NSQLTranslationV1::MakeTranslator(lexers, parsers), - nullptr - ); + nullptr); auto res = SqlToYql(translators, query, settings); if (debug == EDebugOutput::ToCerr) { @@ -118,7 +118,7 @@ inline TString Quote(const char* str) { class TWordCountHive: public TMap<TString, unsigned> { public: TWordCountHive(std::initializer_list<TString> strings) { - for (auto& str: strings) { + for (auto& str : strings) { emplace(str, 0); } } @@ -129,14 +129,14 @@ public: } }; -typedef std::function<void (const TString& word, const TString& line)> TVerifyLineFunc; +typedef std::function<void(const TString& word, const TString& line)> TVerifyLineFunc; inline TString VerifyProgram(const NYql::TAstParseResult& res, TWordCountHive& wordCounter, TVerifyLineFunc verifyLine = TVerifyLineFunc()) { const auto program = GetPrettyPrint(res); TVector<TString> yqlProgram; Split(program, "\n", yqlProgram); - for (const auto& line: yqlProgram) { - for (auto& counterIter: wordCounter) { + for (const auto& line : yqlProgram) { + for (auto& counterIter : wordCounter) { const auto& word = counterIter.first; auto pos = line.find(word); while (pos != TString::npos) { @@ -154,8 +154,7 @@ inline TString VerifyProgram(const NYql::TAstParseResult& res, TWordCountHive& w inline void VerifySqlInHints(const TString& query, const THashSet<TString>& expectedHints, TMaybe<bool> ansi) { TString pragma; if (ansi.Defined()) { - pragma = *ansi ? "PRAGMA AnsiInForEmptyOrNullableItemsCollections;" : - "PRAGMA DisableAnsiInForEmptyOrNullableItemsCollections;"; + pragma = *ansi ? "PRAGMA AnsiInForEmptyOrNullableItemsCollections;" : "PRAGMA DisableAnsiInForEmptyOrNullableItemsCollections;"; } NYql::TAstParseResult res = SqlToYql(pragma + query); @@ -168,7 +167,7 @@ inline void VerifySqlInHints(const TString& query, const THashSet<TString>& expe } else if (*ansi) { UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('ansi)")); } - for (auto& hint : expectedHints) { + for (auto& hint : expectedHints) { UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(hint)); } }; @@ -221,14 +220,15 @@ inline NSQLTranslation::TTranslationSettings GetSettingsWithS3Binding(const TStr return settings; } -inline void AstBfs(NYql::TAstNode const* root, std::function<bool (NYql::TAstNode const*)> visitor) { - std::deque<NYql::TAstNode const*> wishList{ root }; +inline void AstBfs(NYql::TAstNode const* root, std::function<bool(NYql::TAstNode const*)> visitor) { + std::deque<NYql::TAstNode const*> wishList{root}; std::unordered_set<NYql::TAstNode const*> visited; - while(!wishList.empty()){ + while (!wishList.empty()) { auto v = wishList.front(); wishList.pop_front(); - if (!visitor(v)) + if (!visitor(v)) { return; + } visited.insert(v); if (v->IsList()) { for (ui32 i = 0; i != v->GetChildrenCount(); ++i) { @@ -241,7 +241,7 @@ inline void AstBfs(NYql::TAstNode const* root, std::function<bool (NYql::TAstNod } } -inline const NYql::TAstNode* FindNodeByChildAtomContent(const NYql::TAstNode* root, uint32_t childIndex, TStringBuf name){ +inline const NYql::TAstNode* FindNodeByChildAtomContent(const NYql::TAstNode* root, uint32_t childIndex, TStringBuf name) { const NYql::TAstNode* result = nullptr; AstBfs(root, [&result, childIndex, name](auto v) { if (v->IsList() && v->GetChildrenCount() > childIndex && diff --git a/yql/essentials/sql/v1/sql_ut_antlr4.cpp b/yql/essentials/sql/v1/sql_ut_antlr4.cpp index bc29c949ddd..a9dd459223b 100644 --- a/yql/essentials/sql/v1/sql_ut_antlr4.cpp +++ b/yql/essentials/sql/v1/sql_ut_antlr4.cpp @@ -31,14 +31,14 @@ TParsedTokenList Tokenize(const TString& query) { return tokens; } -} +} // namespace #define ANTLR_VER 4 #include "sql_ut_common.h" Y_UNIT_TEST_SUITE(QuerySplit) { - Y_UNIT_TEST(Simple) { - TString query = R"( +Y_UNIT_TEST(Simple) { + TString query = R"( ; -- Comment 1 SELECT * From Input; -- Comment 2 @@ -64,29 +64,29 @@ Y_UNIT_TEST_SUITE(QuerySplit) { )"; - google::protobuf::Arena Arena; + google::protobuf::Arena Arena; - NSQLTranslation::TTranslationSettings settings; - settings.AnsiLexer = false; - settings.Antlr4Parser = true; - settings.Arena = &Arena; + NSQLTranslation::TTranslationSettings settings; + settings.AnsiLexer = false; + settings.Antlr4Parser = true; + settings.Arena = &Arena; - TVector<TString> statements; - NYql::TIssues issues; + TVector<TString> statements; + NYql::TIssues issues; - NSQLTranslationV1::TLexers lexers; - lexers.Antlr4 = NSQLTranslationV1::MakeAntlr4LexerFactory(); - NSQLTranslationV1::TParsers parsers; - parsers.Antlr4 = NSQLTranslationV1::MakeAntlr4ParserFactory(); + NSQLTranslationV1::TLexers lexers; + lexers.Antlr4 = NSQLTranslationV1::MakeAntlr4LexerFactory(); + NSQLTranslationV1::TParsers parsers; + parsers.Antlr4 = NSQLTranslationV1::MakeAntlr4ParserFactory(); - UNIT_ASSERT(NSQLTranslationV1::SplitQueryToStatements(lexers, parsers, query, statements, issues, settings)); + UNIT_ASSERT(NSQLTranslationV1::SplitQueryToStatements(lexers, parsers, query, statements, issues, settings)); - UNIT_ASSERT_VALUES_EQUAL(statements.size(), 3); + UNIT_ASSERT_VALUES_EQUAL(statements.size(), 3); - UNIT_ASSERT_VALUES_EQUAL(statements[0], "-- Comment 1\n SELECT * From Input; -- Comment 2\n"); - UNIT_ASSERT_VALUES_EQUAL(statements[1], R"(-- Comment 3 + UNIT_ASSERT_VALUES_EQUAL(statements[0], "-- Comment 1\n SELECT * From Input; -- Comment 2\n"); + UNIT_ASSERT_VALUES_EQUAL(statements[1], R"(-- Comment 3 $a = "a";)"); - UNIT_ASSERT_VALUES_EQUAL(statements[2], R"(-- Comment 10 + UNIT_ASSERT_VALUES_EQUAL(statements[2], R"(-- Comment 10 -- Comment 8 @@ -95,7 +95,5 @@ Y_UNIT_TEST_SUITE(QuerySplit) { return /* Comment 5 */ $x; -- Comment 6 };)"); - } } - - +} // Y_UNIT_TEST_SUITE(QuerySplit) diff --git a/yql/essentials/sql/v1/sql_ut_antlr4.h b/yql/essentials/sql/v1/sql_ut_antlr4.h index e8d8259a9bc..5bfee9a8913 100644 --- a/yql/essentials/sql/v1/sql_ut_antlr4.h +++ b/yql/essentials/sql/v1/sql_ut_antlr4.h @@ -1,3 +1,4 @@ +#pragma once #include <yql/essentials/providers/common/provider/yql_provider_names.h> #include <yql/essentials/sql/sql.h> @@ -35,7 +36,7 @@ inline TString Err2Str(const NYql::TAstParseResult& res, EDebugOutput debug = ED } inline NYql::TAstParseResult SqlToYqlWithMode(const TString& query, NSQLTranslation::ESqlMode mode = NSQLTranslation::ESqlMode::QUERY, size_t maxErrors = 10, const TString& provider = {}, - EDebugOutput debug = EDebugOutput::None, bool ansiLexer = false, NSQLTranslation::TTranslationSettings settings = {}) + EDebugOutput debug = EDebugOutput::None, bool ansiLexer = false, NSQLTranslation::TTranslationSettings settings = {}) { google::protobuf::Arena arena; const auto service = provider ? provider : TString(NYql::YtProviderName); @@ -60,8 +61,7 @@ inline NYql::TAstParseResult SqlToYqlWithMode(const TString& query, NSQLTranslat NSQLTranslation::TTranslators translators( nullptr, NSQLTranslationV1::MakeTranslator(lexers, parsers), - nullptr - ); + nullptr); auto res = SqlToYql(translators, query, settings); if (debug == EDebugOutput::ToCerr) { @@ -117,7 +117,7 @@ inline TString Quote(const char* str) { class TWordCountHive: public TMap<TString, unsigned> { public: TWordCountHive(std::initializer_list<TString> strings) { - for (auto& str: strings) { + for (auto& str : strings) { emplace(str, 0); } } @@ -128,14 +128,14 @@ public: } }; -typedef std::function<void (const TString& word, const TString& line)> TVerifyLineFunc; +typedef std::function<void(const TString& word, const TString& line)> TVerifyLineFunc; inline TString VerifyProgram(const NYql::TAstParseResult& res, TWordCountHive& wordCounter, TVerifyLineFunc verifyLine = TVerifyLineFunc()) { const auto program = GetPrettyPrint(res); TVector<TString> yqlProgram; Split(program, "\n", yqlProgram); - for (const auto& line: yqlProgram) { - for (auto& counterIter: wordCounter) { + for (const auto& line : yqlProgram) { + for (auto& counterIter : wordCounter) { const auto& word = counterIter.first; auto pos = line.find(word); while (pos != TString::npos) { @@ -153,8 +153,7 @@ inline TString VerifyProgram(const NYql::TAstParseResult& res, TWordCountHive& w inline void VerifySqlInHints(const TString& query, const THashSet<TString>& expectedHints, TMaybe<bool> ansi) { TString pragma; if (ansi.Defined()) { - pragma = *ansi ? "PRAGMA AnsiInForEmptyOrNullableItemsCollections;" : - "PRAGMA DisableAnsiInForEmptyOrNullableItemsCollections;"; + pragma = *ansi ? "PRAGMA AnsiInForEmptyOrNullableItemsCollections;" : "PRAGMA DisableAnsiInForEmptyOrNullableItemsCollections;"; } NYql::TAstParseResult res = SqlToYql(pragma + query); @@ -167,7 +166,7 @@ inline void VerifySqlInHints(const TString& query, const THashSet<TString>& expe } else if (*ansi) { UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('ansi)")); } - for (auto& hint : expectedHints) { + for (auto& hint : expectedHints) { UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(hint)); } }; @@ -220,14 +219,15 @@ inline NSQLTranslation::TTranslationSettings GetSettingsWithS3Binding(const TStr return settings; } -inline void AstBfs(NYql::TAstNode const* root, std::function<bool (NYql::TAstNode const*)> visitor) { - std::deque<NYql::TAstNode const*> wishList{ root }; +inline void AstBfs(NYql::TAstNode const* root, std::function<bool(NYql::TAstNode const*)> visitor) { + std::deque<NYql::TAstNode const*> wishList{root}; std::unordered_set<NYql::TAstNode const*> visited; - while(!wishList.empty()){ + while (!wishList.empty()) { auto v = wishList.front(); wishList.pop_front(); - if (!visitor(v)) + if (!visitor(v)) { return; + } visited.insert(v); if (v->IsList()) { for (ui32 i = 0; i != v->GetChildrenCount(); ++i) { @@ -240,7 +240,7 @@ inline void AstBfs(NYql::TAstNode const* root, std::function<bool (NYql::TAstNod } } -inline const NYql::TAstNode* FindNodeByChildAtomContent(const NYql::TAstNode* root, uint32_t childIndex, TStringBuf name){ +inline const NYql::TAstNode* FindNodeByChildAtomContent(const NYql::TAstNode* root, uint32_t childIndex, TStringBuf name) { const NYql::TAstNode* result = nullptr; AstBfs(root, [&result, childIndex, name](auto v) { if (v->IsList() && v->GetChildrenCount() > childIndex && diff --git a/yql/essentials/sql/v1/sql_ut_common.h b/yql/essentials/sql/v1/sql_ut_common.h index 391b11c2040..49c32fd450c 100644 --- a/yql/essentials/sql/v1/sql_ut_common.h +++ b/yql/essentials/sql/v1/sql_ut_common.h @@ -1,608 +1,580 @@ +#pragma once + namespace { - TString ToString(const TParsedTokenList& tokens) { - TStringBuilder reconstructedQuery; - for (const auto& token : tokens) { - if (token.Name == "WS" || token.Name == "EOF") { - continue; - } - if (!reconstructedQuery.empty()) { - reconstructedQuery << ' '; - } - reconstructedQuery << token.Content; +TString ToString(const TParsedTokenList& tokens) { + TStringBuilder reconstructedQuery; + for (const auto& token : tokens) { + if (token.Name == "WS" || token.Name == "EOF") { + continue; + } + if (!reconstructedQuery.empty()) { + reconstructedQuery << ' '; } - return reconstructedQuery; + reconstructedQuery << token.Content; } + return reconstructedQuery; } +} // namespace Y_UNIT_TEST_SUITE(AnsiMode) { - Y_UNIT_TEST(PragmaAnsi) { - UNIT_ASSERT(SqlToYql("PRAGMA ANSI 2016;").IsOk()); - } +Y_UNIT_TEST(PragmaAnsi) { + UNIT_ASSERT(SqlToYql("PRAGMA ANSI 2016;").IsOk()); } +} // Y_UNIT_TEST_SUITE(AnsiMode) Y_UNIT_TEST_SUITE(SqlParsingOnly) { - ///This function is used in BACKWARD COMPATIBILITY tests below that LIMIT the sets of token that CAN NOT be used - ///as identifiers in different contexts in a SQL request - ///\return list of tokens that failed this check - TVector<TString> ValidateTokens(const THashSet<TString>& forbidden, const std::function<TString (const TString& )>& makeRequest) { - THashMap<TString, bool> allTokens; - for (const auto& t: NSQLFormat::GetKeywords()) { - allTokens[t] = !forbidden.contains((t)); - } - for (const auto& f: forbidden) { - UNIT_ASSERT(allTokens.contains(f)); //check that forbidden list contains tokens only(argument check) - } - TVector<TString> failed; - for (const auto& [token, allowed]: allTokens) { - if (SqlToYql(makeRequest(token)).IsOk() != allowed) - failed.push_back(token); - } - return failed; +/// This function is used in BACKWARD COMPATIBILITY tests below that LIMIT the sets of token that CAN NOT be used +/// as identifiers in different contexts in a SQL request +///\return list of tokens that failed this check +TVector<TString> ValidateTokens(const THashSet<TString>& forbidden, const std::function<TString(const TString&)>& makeRequest) { + THashMap<TString, bool> allTokens; + for (const auto& t : NSQLFormat::GetKeywords()) { + allTokens[t] = !forbidden.contains((t)); + } + for (const auto& f : forbidden) { + UNIT_ASSERT(allTokens.contains(f)); // check that forbidden list contains tokens only(argument check) + } + TVector<TString> failed; + for (const auto& [token, allowed] : allTokens) { + if (SqlToYql(makeRequest(token)).IsOk() != allowed) { + failed.push_back(token); + } } + return failed; +} - Y_UNIT_TEST(TokensAsColumnName) { //id_expr - auto failed = ValidateTokens({ - "ALL", "ANY", "AS", "ASSUME", "ASYMMETRIC", "AUTOMAP", "BETWEEN", "BITCAST", - "CALLABLE", "CASE", "CAST", "CUBE", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", - "DICT", "DISTINCT", "ENUM", "ERASE", "EXCEPT", "EXISTS", "FLOW", "FROM", "FULL", - "HAVING", "HOP", "INTERSECT", "JSON_EXISTS", "JSON_QUERY", "JSON_VALUE", "LIMIT", "LIST", - "NOT", "OPTIONAL", "PROCESS", "REDUCE", "REPEATABLE", "RESOURCE", "RETURN", "RETURNING", "ROLLUP", - "SELECT", "SET", "STREAM", "STRUCT", "SYMMETRIC", "TAGGED", "TUPLE", "UNBOUNDED", - "UNION", "VARIANT", "WHEN", "WHERE", "WINDOW", "WITHOUT" - }, - [](const TString& token){ - TStringBuilder req; - req << "SELECT " << token << " FROM Plato.Input"; - return req; - } - ); - UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); - } +Y_UNIT_TEST(TokensAsColumnName) { // id_expr + auto failed = ValidateTokens({"ALL", "ANY", "AS", "ASSUME", "ASYMMETRIC", "AUTOMAP", "BETWEEN", "BITCAST", + "CALLABLE", "CASE", "CAST", "CUBE", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", + "DICT", "DISTINCT", "ENUM", "ERASE", "EXCEPT", "EXISTS", "FLOW", "FROM", "FULL", + "HAVING", "HOP", "INTERSECT", "JSON_EXISTS", "JSON_QUERY", "JSON_VALUE", "LIMIT", "LIST", + "NOT", "OPTIONAL", "PROCESS", "REDUCE", "REPEATABLE", "RESOURCE", "RETURN", "RETURNING", "ROLLUP", + "SELECT", "SET", "STREAM", "STRUCT", "SYMMETRIC", "TAGGED", "TUPLE", "UNBOUNDED", + "UNION", "VARIANT", "WHEN", "WHERE", "WINDOW", "WITHOUT"}, + [](const TString& token) { + TStringBuilder req; + req << "SELECT " << token << " FROM Plato.Input"; + return req; + }); + UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); +} - Y_UNIT_TEST(TokensAsWithoutColumnName) { //id_without - auto failed = ValidateTokens({ - "ALL", "AS", "ASSUME", "ASYMMETRIC", "AUTOMAP", "BETWEEN", "BITCAST", - "CALLABLE", "CASE", "CAST", "CUBE", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", - "DICT", "DISTINCT", "EMPTY_ACTION", "ENUM", "EXCEPT", "EXISTS", "FALSE", "FLOW", "FROM", "FULL", - "HAVING", "HOP", "INTERSECT", "JSON_EXISTS", "JSON_QUERY", "JSON_VALUE", "LIMIT", "LIST", - "NOT", "NULL", "OPTIONAL", "PROCESS", "REDUCE", "REPEATABLE", "RESOURCE", "RETURN", "RETURNING", "ROLLUP", - "SELECT", "SET", "STRUCT", "SYMMETRIC", "TAGGED", "TRUE", "TUPLE", "UNBOUNDED", - "UNION", "VARIANT", "WHEN", "WHERE", "WINDOW", "WITHOUT" - }, - [](const TString& token){ - TStringBuilder req; - req << "SELECT * WITHOUT " << token << " FROM Plato.Input"; - return req; - } - ); - UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); - } +Y_UNIT_TEST(TokensAsWithoutColumnName) { // id_without + auto failed = ValidateTokens({"ALL", "AS", "ASSUME", "ASYMMETRIC", "AUTOMAP", "BETWEEN", "BITCAST", + "CALLABLE", "CASE", "CAST", "CUBE", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", + "DICT", "DISTINCT", "EMPTY_ACTION", "ENUM", "EXCEPT", "EXISTS", "FALSE", "FLOW", "FROM", "FULL", + "HAVING", "HOP", "INTERSECT", "JSON_EXISTS", "JSON_QUERY", "JSON_VALUE", "LIMIT", "LIST", + "NOT", "NULL", "OPTIONAL", "PROCESS", "REDUCE", "REPEATABLE", "RESOURCE", "RETURN", "RETURNING", "ROLLUP", + "SELECT", "SET", "STRUCT", "SYMMETRIC", "TAGGED", "TRUE", "TUPLE", "UNBOUNDED", + "UNION", "VARIANT", "WHEN", "WHERE", "WINDOW", "WITHOUT"}, + [](const TString& token) { + TStringBuilder req; + req << "SELECT * WITHOUT " << token << " FROM Plato.Input"; + return req; + }); + UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); +} - Y_UNIT_TEST(TokensAsColumnNameInAddColumn) { //id_schema - auto failed = ValidateTokens({ - "ANY", "AUTOMAP", "CALLABLE", "COLUMN", "DICT", "ENUM", "ERASE", "FALSE", "FLOW", - "LIST", "OPTIONAL", "REPEATABLE", "RESOURCE", - "SET", "STREAM", "STRUCT", "TAGGED", "TRUE", "TUPLE", "VARIANT" - }, - [](const TString& token){ - TStringBuilder req; - req << "ALTER TABLE Plato.Input ADD COLUMN " << token << " Bool"; - return req; - } - ); - UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); - } +Y_UNIT_TEST(TokensAsColumnNameInAddColumn) { // id_schema + auto failed = ValidateTokens({"ANY", "AUTOMAP", "CALLABLE", "COLUMN", "DICT", "ENUM", "ERASE", "FALSE", "FLOW", + "LIST", "OPTIONAL", "REPEATABLE", "RESOURCE", + "SET", "STREAM", "STRUCT", "TAGGED", "TRUE", "TUPLE", "VARIANT"}, + [](const TString& token) { + TStringBuilder req; + req << "ALTER TABLE Plato.Input ADD COLUMN " << token << " Bool"; + return req; + }); + UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); +} - Y_UNIT_TEST(TokensAsColumnAlias) { - auto failed = ValidateTokens({ - "AUTOMAP", "FALSE", - "REPEATABLE", "TRUE" - }, - [](const TString& token){ - TStringBuilder req; - req << "SELECT Col as " << token << " FROM Plato.Input"; - return req; - } - ); - UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); - } +Y_UNIT_TEST(TokensAsColumnAlias) { + auto failed = ValidateTokens({"AUTOMAP", "FALSE", + "REPEATABLE", "TRUE"}, + [](const TString& token) { + TStringBuilder req; + req << "SELECT Col as " << token << " FROM Plato.Input"; + return req; + }); + UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); +} - Y_UNIT_TEST(TokensAsTableName) { //id_table_or_type - auto failed = ValidateTokens({ - "ANY", "AUTOMAP", "COLUMN", "ERASE", "FALSE", - "REPEATABLE", "STREAM", "TRUE" - }, - [](const TString& token){ - TStringBuilder req; - req << "SELECT * FROM Plato." << token; - return req; - } - ); - UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); - } +Y_UNIT_TEST(TokensAsTableName) { // id_table_or_type + auto failed = ValidateTokens({"ANY", "AUTOMAP", "COLUMN", "ERASE", "FALSE", + "REPEATABLE", "STREAM", "TRUE"}, + [](const TString& token) { + TStringBuilder req; + req << "SELECT * FROM Plato." << token; + return req; + }); + UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); +} - Y_UNIT_TEST(TokensAsTableAlias) { //id_table - auto failed = ValidateTokens({ - "AUTOMAP", "CALLABLE", "DICT", "ENUM","FALSE", "FLOW", - "LIST", "OPTIONAL", "REPEATABLE", "RESOURCE", - "SET", "STRUCT", "TAGGED", "TRUE", "TUPLE", "VARIANT" - }, - [](const TString& token){ - TStringBuilder req; - req << "SELECT * FROM Plato.Input AS " << token; - return req; - } - ); - UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); - } +Y_UNIT_TEST(TokensAsTableAlias) { // id_table + auto failed = ValidateTokens({"AUTOMAP", "CALLABLE", "DICT", "ENUM", "FALSE", "FLOW", + "LIST", "OPTIONAL", "REPEATABLE", "RESOURCE", + "SET", "STRUCT", "TAGGED", "TRUE", "TUPLE", "VARIANT"}, + [](const TString& token) { + TStringBuilder req; + req << "SELECT * FROM Plato.Input AS " << token; + return req; + }); + UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); +} - Y_UNIT_TEST(TokensAsHints) { //id_hint - auto failed = ValidateTokens({ - "AUTOMAP", "CALLABLE", "COLUMNS", "DICT", "ENUM", "FALSE", "FLOW", - "LIST", "OPTIONAL", "REPEATABLE", "RESOURCE", - "SCHEMA", "SET", "STRUCT", "TAGGED", "TRUE", "TUPLE", "VARIANT" - }, - [](const TString& token){ - TStringBuilder req; - req << "SELECT * FROM Plato.Input WITH " << token; - return req; - } - ); - UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); - } +Y_UNIT_TEST(TokensAsHints) { // id_hint + auto failed = ValidateTokens({"AUTOMAP", "CALLABLE", "COLUMNS", "DICT", "ENUM", "FALSE", "FLOW", + "LIST", "OPTIONAL", "REPEATABLE", "RESOURCE", + "SCHEMA", "SET", "STRUCT", "TAGGED", "TRUE", "TUPLE", "VARIANT"}, + [](const TString& token) { + TStringBuilder req; + req << "SELECT * FROM Plato.Input WITH " << token; + return req; + }); + UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); +} - Y_UNIT_TEST(TokensAsWindow) { //id_window - auto failed = ValidateTokens({ - "AUTOMAP", "CALLABLE", "DICT", "ENUM", "FALSE", "FLOW", "GROUPS", "LIST", "OPTIONAL", - "RANGE", "REPEATABLE", "RESOURCE", "ROWS", "SET", "STRUCT", "TAGGED" ,"TRUE", "TUPLE", "VARIANT" - }, - [](const TString& token){ - TStringBuilder req; - req << "SELECT * FROM Plato.Input WINDOW " << token << " AS ()"; - return req; - } - ); - UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); - } +Y_UNIT_TEST(TokensAsWindow) { // id_window + auto failed = ValidateTokens({"AUTOMAP", "CALLABLE", "DICT", "ENUM", "FALSE", "FLOW", "GROUPS", "LIST", "OPTIONAL", + "RANGE", "REPEATABLE", "RESOURCE", "ROWS", "SET", "STRUCT", "TAGGED", "TRUE", "TUPLE", "VARIANT"}, + [](const TString& token) { + TStringBuilder req; + req << "SELECT * FROM Plato.Input WINDOW " << token << " AS ()"; + return req; + }); + UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); +} - Y_UNIT_TEST(TokensAsIdExprIn) { //id_expr_in - auto failed = ValidateTokens({ - "ALL", "ANY", "AS", "ASSUME", "ASYMMETRIC", "AUTOMAP", "BETWEEN", "BITCAST", - "CALLABLE", "CASE", "CAST", "COMPACT", "CUBE", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", - "DICT", "DISTINCT", "ENUM", "ERASE", "EXCEPT", "EXISTS", "FLOW", "FROM", "FULL", - "HAVING", "HOP", "INTERSECT", "JSON_EXISTS", "JSON_QUERY", "JSON_VALUE", "LIMIT", "LIST", - "NOT", "OPTIONAL", "PROCESS", "REDUCE", "REPEATABLE", "RESOURCE", "RETURN", "RETURNING", "ROLLUP", - "SELECT", "SET", "STREAM", "STRUCT", "SYMMETRIC", "TAGGED", "TUPLE", "UNBOUNDED", - "UNION", "VARIANT", "WHEN", "WHERE", "WINDOW", "WITHOUT" - }, - [](const TString& token){ - TStringBuilder req; - req << "SELECT * FROM Plato.Input WHERE q IN " << token; - return req; - } - ); - UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); - } +Y_UNIT_TEST(TokensAsIdExprIn) { // id_expr_in + auto failed = ValidateTokens({"ALL", "ANY", "AS", "ASSUME", "ASYMMETRIC", "AUTOMAP", "BETWEEN", "BITCAST", + "CALLABLE", "CASE", "CAST", "COMPACT", "CUBE", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", + "DICT", "DISTINCT", "ENUM", "ERASE", "EXCEPT", "EXISTS", "FLOW", "FROM", "FULL", + "HAVING", "HOP", "INTERSECT", "JSON_EXISTS", "JSON_QUERY", "JSON_VALUE", "LIMIT", "LIST", + "NOT", "OPTIONAL", "PROCESS", "REDUCE", "REPEATABLE", "RESOURCE", "RETURN", "RETURNING", "ROLLUP", + "SELECT", "SET", "STREAM", "STRUCT", "SYMMETRIC", "TAGGED", "TUPLE", "UNBOUNDED", + "UNION", "VARIANT", "WHEN", "WHERE", "WINDOW", "WITHOUT"}, + [](const TString& token) { + TStringBuilder req; + req << "SELECT * FROM Plato.Input WHERE q IN " << token; + return req; + }); + UNIT_ASSERT_VALUES_EQUAL(failed, TVector<TString>{}); +} - Y_UNIT_TEST(TableHints) { - UNIT_ASSERT(SqlToYql("SELECT * FROM plato.Input WITH INFER_SCHEMA").IsOk()); - UNIT_ASSERT(SqlToYql("SELECT * FROM plato.Input WITH (INFER_SCHEMA)").IsOk()); - } +Y_UNIT_TEST(TableHints) { + UNIT_ASSERT(SqlToYql("SELECT * FROM plato.Input WITH INFER_SCHEMA").IsOk()); + UNIT_ASSERT(SqlToYql("SELECT * FROM plato.Input WITH (INFER_SCHEMA)").IsOk()); +} - Y_UNIT_TEST(InNoHints) { - TString query = "SELECT * FROM plato.Input WHERE key IN (1,2,3)"; +Y_UNIT_TEST(InNoHints) { + TString query = "SELECT * FROM plato.Input WHERE key IN (1,2,3)"; - VerifySqlInHints(query, { "'('('warnNoAnsi))" }, {}); - VerifySqlInHints(query, { "'()" }, false); - VerifySqlInHints(query, { "'('('ansi))" }, true); - } + VerifySqlInHints(query, {"'('('warnNoAnsi))"}, {}); + VerifySqlInHints(query, {"'()"}, false); + VerifySqlInHints(query, {"'('('ansi))"}, true); +} - Y_UNIT_TEST(InHintCompact) { - // should parse COMPACT as hint - TString query = "SELECT * FROM plato.Input WHERE key IN COMPACT(1, 2, 3)"; +Y_UNIT_TEST(InHintCompact) { + // should parse COMPACT as hint + TString query = "SELECT * FROM plato.Input WHERE key IN COMPACT(1, 2, 3)"; - VerifySqlInHints(query, { "'('isCompact)" }); - } + VerifySqlInHints(query, {"'('isCompact)"}); +} - Y_UNIT_TEST(InHintSubquery) { - // should parse tableSource as hint - TString query = "$subq = (SELECT key FROM plato.Input); SELECT * FROM plato.Input WHERE key IN $subq"; +Y_UNIT_TEST(InHintSubquery) { + // should parse tableSource as hint + TString query = "$subq = (SELECT key FROM plato.Input); SELECT * FROM plato.Input WHERE key IN $subq"; - VerifySqlInHints(query, { "'('tableSource)" }); - } + VerifySqlInHints(query, {"'('tableSource)"}); +} - Y_UNIT_TEST(InHintCompactSubquery) { - TString query = "$subq = (SELECT key FROM plato.Input); SELECT * FROM plato.Input WHERE key IN COMPACT $subq"; +Y_UNIT_TEST(InHintCompactSubquery) { + TString query = "$subq = (SELECT key FROM plato.Input); SELECT * FROM plato.Input WHERE key IN COMPACT $subq"; - VerifySqlInHints(query, { "'('isCompact)", "'('tableSource)" }); - } + VerifySqlInHints(query, {"'('isCompact)", "'('tableSource)"}); +} - Y_UNIT_TEST(CompactKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("SELECT COMPACT FROM plato.Input WHERE COMPACT IN COMPACT(1, 2, 3)").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT * FROM COMPACT").IsOk()); - } +Y_UNIT_TEST(CompactKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("SELECT COMPACT FROM plato.Input WHERE COMPACT IN COMPACT(1, 2, 3)").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT * FROM COMPACT").IsOk()); +} - Y_UNIT_TEST(FamilyKeywordNotReservedForNames) { - // FIXME: check if we can get old behaviour - //UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE FAMILY (FAMILY Uint32, PRIMARY KEY (FAMILY));").IsOk()); - //UNIT_ASSERT(SqlToYql("USE plato; SELECT FAMILY FROM FAMILY").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT FAMILY FROM Input").IsOk()); - } +Y_UNIT_TEST(FamilyKeywordNotReservedForNames) { + // FIXME: check if we can get old behaviour + // UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE FAMILY (FAMILY Uint32, PRIMARY KEY (FAMILY));").IsOk()); + // UNIT_ASSERT(SqlToYql("USE plato; SELECT FAMILY FROM FAMILY").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT FAMILY FROM Input").IsOk()); +} - Y_UNIT_TEST(ResetKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE RESET (RESET Uint32, PRIMARY KEY (RESET));").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT RESET FROM RESET").IsOk()); - } +Y_UNIT_TEST(ResetKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE RESET (RESET Uint32, PRIMARY KEY (RESET));").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT RESET FROM RESET").IsOk()); +} - Y_UNIT_TEST(SyncKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE SYNC (SYNC Uint32, PRIMARY KEY (SYNC));").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT SYNC FROM SYNC").IsOk()); - } +Y_UNIT_TEST(SyncKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE SYNC (SYNC Uint32, PRIMARY KEY (SYNC));").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT SYNC FROM SYNC").IsOk()); +} - Y_UNIT_TEST(AsyncKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE ASYNC (ASYNC Uint32, PRIMARY KEY (ASYNC));").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT ASYNC FROM ASYNC").IsOk()); - } +Y_UNIT_TEST(AsyncKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE ASYNC (ASYNC Uint32, PRIMARY KEY (ASYNC));").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT ASYNC FROM ASYNC").IsOk()); +} - Y_UNIT_TEST(DisableKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE DISABLE (DISABLE Uint32, PRIMARY KEY (DISABLE));").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT DISABLE FROM DISABLE").IsOk()); - } +Y_UNIT_TEST(DisableKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE DISABLE (DISABLE Uint32, PRIMARY KEY (DISABLE));").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT DISABLE FROM DISABLE").IsOk()); +} - Y_UNIT_TEST(ChangefeedKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE CHANGEFEED (CHANGEFEED Uint32, PRIMARY KEY (CHANGEFEED));").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT CHANGEFEED FROM CHANGEFEED").IsOk()); - } +Y_UNIT_TEST(ChangefeedKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE CHANGEFEED (CHANGEFEED Uint32, PRIMARY KEY (CHANGEFEED));").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT CHANGEFEED FROM CHANGEFEED").IsOk()); +} - Y_UNIT_TEST(ReplicationKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE REPLICATION (REPLICATION Uint32, PRIMARY KEY (REPLICATION));").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT REPLICATION FROM REPLICATION").IsOk()); - } +Y_UNIT_TEST(ReplicationKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE REPLICATION (REPLICATION Uint32, PRIMARY KEY (REPLICATION));").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT REPLICATION FROM REPLICATION").IsOk()); +} - Y_UNIT_TEST(TransferKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE TRANSFER (TRANSFER Uint32, PRIMARY KEY (TRANSFER));").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT TRANSFER FROM TRANSFER").IsOk()); - } +Y_UNIT_TEST(TransferKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE TRANSFER (TRANSFER Uint32, PRIMARY KEY (TRANSFER));").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT TRANSFER FROM TRANSFER").IsOk()); +} - Y_UNIT_TEST(SecondsKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE SECONDS (SECONDS Uint32, PRIMARY KEY (SECONDS));").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT SECONDS FROM SECONDS").IsOk()); - } +Y_UNIT_TEST(SecondsKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE SECONDS (SECONDS Uint32, PRIMARY KEY (SECONDS));").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT SECONDS FROM SECONDS").IsOk()); +} - Y_UNIT_TEST(MillisecondsKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE MILLISECONDS (MILLISECONDS Uint32, PRIMARY KEY (MILLISECONDS));").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT MILLISECONDS FROM MILLISECONDS").IsOk()); - } +Y_UNIT_TEST(MillisecondsKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE MILLISECONDS (MILLISECONDS Uint32, PRIMARY KEY (MILLISECONDS));").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT MILLISECONDS FROM MILLISECONDS").IsOk()); +} - Y_UNIT_TEST(MicrosecondsKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE MICROSECONDS (MICROSECONDS Uint32, PRIMARY KEY (MICROSECONDS));").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT MICROSECONDS FROM MICROSECONDS").IsOk()); - } +Y_UNIT_TEST(MicrosecondsKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE MICROSECONDS (MICROSECONDS Uint32, PRIMARY KEY (MICROSECONDS));").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT MICROSECONDS FROM MICROSECONDS").IsOk()); +} - Y_UNIT_TEST(NanosecondsKeywordNotReservedForNames) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE NANOSECONDS (NANOSECONDS Uint32, PRIMARY KEY (NANOSECONDS));").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT NANOSECONDS FROM NANOSECONDS").IsOk()); - } +Y_UNIT_TEST(NanosecondsKeywordNotReservedForNames) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE NANOSECONDS (NANOSECONDS Uint32, PRIMARY KEY (NANOSECONDS));").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT NANOSECONDS FROM NANOSECONDS").IsOk()); +} - Y_UNIT_TEST(Jubilee) { - NYql::TAstParseResult res = SqlToYql("USE plato; INSERT INTO Arcadia (r2000000) VALUES (\"2M GET!!!\");"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(Jubilee) { + NYql::TAstParseResult res = SqlToYql("USE plato; INSERT INTO Arcadia (r2000000) VALUES (\"2M GET!!!\");"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(QualifiedAsteriskBefore) { - NYql::TAstParseResult res = SqlToYql( - "PRAGMA DisableSimpleColumns;" - "select interested_table.*, LENGTH(value) AS megahelpful_len from plato.Input as interested_table;" - ); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(QualifiedAsteriskBefore) { + NYql::TAstParseResult res = SqlToYql( + "PRAGMA DisableSimpleColumns;" + "select interested_table.*, LENGTH(value) AS megahelpful_len from plato.Input as interested_table;"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - static bool seenStar = false; - if (word == "FlattenMembers") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("interested_table.")); - } else if (word == "SqlProjectItem") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("megahelpful_len"))); - UNIT_ASSERT_VALUES_EQUAL(seenStar, true); - } else if (word == "SqlProjectStarItem") { - seenStar = true; - } - }; - TWordCountHive elementStat = {{TString("FlattenMembers"), 0}, {TString("SqlProjectItem"), 0}, {TString("SqlProjectStarItem"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["FlattenMembers"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectItem"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectStarItem"]); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + static bool seenStar = false; + if (word == "FlattenMembers") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("interested_table.")); + } else if (word == "SqlProjectItem") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("megahelpful_len"))); + UNIT_ASSERT_VALUES_EQUAL(seenStar, true); + } else if (word == "SqlProjectStarItem") { + seenStar = true; + } + }; + TWordCountHive elementStat = {{TString("FlattenMembers"), 0}, {TString("SqlProjectItem"), 0}, {TString("SqlProjectStarItem"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["FlattenMembers"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectItem"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectStarItem"]); +} - Y_UNIT_TEST(QualifiedAsteriskAfter) { - NYql::TAstParseResult res = SqlToYql( - "PRAGMA DisableSimpleColumns;" - "select LENGTH(value) AS megahelpful_len, interested_table.* from plato.Input as interested_table;" - ); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(QualifiedAsteriskAfter) { + NYql::TAstParseResult res = SqlToYql( + "PRAGMA DisableSimpleColumns;" + "select LENGTH(value) AS megahelpful_len, interested_table.* from plato.Input as interested_table;"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - static bool seenStar = false; - if (word == "FlattenMembers") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("interested_table.")); - } else if (word == "SqlProjectItem") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("megahelpful_len"))); - UNIT_ASSERT_VALUES_EQUAL(seenStar, false); - } else if (word == "SqlProjectStarItem") { - seenStar = true; - } - }; - TWordCountHive elementStat = {{TString("FlattenMembers"), 0}, {TString("SqlProjectItem"), 0}, {TString("SqlProjectStarItem"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["FlattenMembers"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectItem"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectStarItem"]); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + static bool seenStar = false; + if (word == "FlattenMembers") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("interested_table.")); + } else if (word == "SqlProjectItem") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("megahelpful_len"))); + UNIT_ASSERT_VALUES_EQUAL(seenStar, false); + } else if (word == "SqlProjectStarItem") { + seenStar = true; + } + }; + TWordCountHive elementStat = {{TString("FlattenMembers"), 0}, {TString("SqlProjectItem"), 0}, {TString("SqlProjectStarItem"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["FlattenMembers"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectItem"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectStarItem"]); +} - Y_UNIT_TEST(QualifiedMembers) { - NYql::TAstParseResult res = SqlToYql("select interested_table.key, interested_table.value from plato.Input as interested_table;"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(QualifiedMembers) { + NYql::TAstParseResult res = SqlToYql("select interested_table.key, interested_table.value from plato.Input as interested_table;"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - const bool fieldKey = TString::npos != line.find(Quote("key")); - const bool fieldValue = TString::npos != line.find(Quote("value")); - const bool refOnTable = TString::npos != line.find("interested_table."); - if (word == "SqlProjectItem") { - UNIT_ASSERT(fieldKey || fieldValue); - UNIT_ASSERT(!refOnTable); - } else if (word == "Write!") { - UNIT_ASSERT(fieldKey && fieldValue && !refOnTable); - } - }; - TWordCountHive elementStat = {{TString("SqlProjectStarItem"), 0}, {TString("SqlProjectItem"), 0}, {TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(0, elementStat["SqlProjectStarItem"]); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SqlProjectItem"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + const bool fieldKey = TString::npos != line.find(Quote("key")); + const bool fieldValue = TString::npos != line.find(Quote("value")); + const bool refOnTable = TString::npos != line.find("interested_table."); + if (word == "SqlProjectItem") { + UNIT_ASSERT(fieldKey || fieldValue); + UNIT_ASSERT(!refOnTable); + } else if (word == "Write!") { + UNIT_ASSERT(fieldKey && fieldValue && !refOnTable); + } + }; + TWordCountHive elementStat = {{TString("SqlProjectStarItem"), 0}, {TString("SqlProjectItem"), 0}, {TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(0, elementStat["SqlProjectStarItem"]); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SqlProjectItem"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(ExplainQueryPlan) { - UNIT_ASSERT(SqlToYql("EXPLAIN SELECT 1;").IsOk()); - UNIT_ASSERT(SqlToYql("EXPLAIN QUERY PLAN SELECT 1;").IsOk()); - } +Y_UNIT_TEST(ExplainQueryPlan) { + UNIT_ASSERT(SqlToYql("EXPLAIN SELECT 1;").IsOk()); + UNIT_ASSERT(SqlToYql("EXPLAIN QUERY PLAN SELECT 1;").IsOk()); +} - Y_UNIT_TEST(JoinParseCorrect) { - NYql::TAstParseResult res = SqlToYql( - "PRAGMA DisableSimpleColumns;" - " SELECT table_bb.*, table_aa.key as megakey" - " FROM plato.Input AS table_aa" - " JOIN plato.Input AS table_bb" - " ON table_aa.value == table_bb.value;" - ); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(JoinParseCorrect) { + NYql::TAstParseResult res = SqlToYql( + "PRAGMA DisableSimpleColumns;" + " SELECT table_bb.*, table_aa.key as megakey" + " FROM plato.Input AS table_aa" + " JOIN plato.Input AS table_bb" + " ON table_aa.value == table_bb.value;"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "SelectMembers") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("table_aa.")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("table_bb.")); - } else if (word == "SqlProjectItem") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("megakey"))); - } else if (word == "SqlColumn") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("table_aa"))); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("key"))); - } - }; - TWordCountHive elementStat = {{TString("SqlProjectItem"), 0}, {TString("SqlProjectStarItem"), 0}, {TString("SelectMembers"), 0}, {TString("SqlColumn"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectItem"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectStarItem"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SelectMembers"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlColumn"]); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "SelectMembers") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("table_aa.")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("table_bb.")); + } else if (word == "SqlProjectItem") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("megakey"))); + } else if (word == "SqlColumn") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("table_aa"))); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("key"))); + } + }; + TWordCountHive elementStat = {{TString("SqlProjectItem"), 0}, {TString("SqlProjectStarItem"), 0}, {TString("SelectMembers"), 0}, {TString("SqlColumn"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectItem"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectStarItem"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SelectMembers"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlColumn"]); +} - Y_UNIT_TEST(Join3Table) { - NYql::TAstParseResult res = SqlToYql( - " PRAGMA DisableSimpleColumns;" - " SELECT table_bb.*, table_aa.key as gigakey, table_cc.* " - " FROM plato.Input AS table_aa" - " JOIN plato.Input AS table_bb ON table_aa.key == table_bb.key" - " JOIN plato.Input AS table_cc ON table_aa.subkey == table_cc.subkey;" - ); - Err2Str(res); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(Join3Table) { + NYql::TAstParseResult res = SqlToYql( + " PRAGMA DisableSimpleColumns;" + " SELECT table_bb.*, table_aa.key as gigakey, table_cc.* " + " FROM plato.Input AS table_aa" + " JOIN plato.Input AS table_bb ON table_aa.key == table_bb.key" + " JOIN plato.Input AS table_cc ON table_aa.subkey == table_cc.subkey;"); + Err2Str(res); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "SelectMembers") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("table_aa.")); - UNIT_ASSERT(line.find("table_bb.") != TString::npos || line.find("table_cc.") != TString::npos); - } else if (word == "SqlProjectItem") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("gigakey"))); - } else if (word == "SqlColumn") { - const auto posTableAA = line.find(Quote("table_aa")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, posTableAA); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("key"))); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("table_aa", posTableAA + 3)); - } - }; - TWordCountHive elementStat = {{TString("SqlProjectItem"), 0}, {TString("SqlProjectStarItem"), 0}, {TString("SelectMembers"), 0}, {TString("SqlColumn"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectItem"]); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SqlProjectStarItem"]); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SelectMembers"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlColumn"]); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "SelectMembers") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("table_aa.")); + UNIT_ASSERT(line.find("table_bb.") != TString::npos || line.find("table_cc.") != TString::npos); + } else if (word == "SqlProjectItem") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("gigakey"))); + } else if (word == "SqlColumn") { + const auto posTableAA = line.find(Quote("table_aa")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, posTableAA); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("key"))); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("table_aa", posTableAA + 3)); + } + }; + TWordCountHive elementStat = {{TString("SqlProjectItem"), 0}, {TString("SqlProjectStarItem"), 0}, {TString("SelectMembers"), 0}, {TString("SqlColumn"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectItem"]); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SqlProjectStarItem"]); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SelectMembers"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlColumn"]); +} - Y_UNIT_TEST(DisabledJoinCartesianProduct) { - NYql::TAstParseResult res = SqlToYql("pragma DisableAnsiImplicitCrossJoin; use plato; select * from A,B,C"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:67: Error: Cartesian product of tables is disabled. Please use explicit CROSS JOIN or enable it via PRAGMA AnsiImplicitCrossJoin\n"); - } +Y_UNIT_TEST(DisabledJoinCartesianProduct) { + NYql::TAstParseResult res = SqlToYql("pragma DisableAnsiImplicitCrossJoin; use plato; select * from A,B,C"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:67: Error: Cartesian product of tables is disabled. Please use explicit CROSS JOIN or enable it via PRAGMA AnsiImplicitCrossJoin\n"); +} - Y_UNIT_TEST(JoinCartesianProduct) { - NYql::TAstParseResult res = SqlToYql("pragma AnsiImplicitCrossJoin; use plato; select * from A,B,C"); - UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "EquiJoin") { - auto pos = line.find("Cross"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, pos); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Cross", pos + 1)); - } - }; - TWordCountHive elementStat = {{TString("EquiJoin"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["EquiJoin"]); - } +Y_UNIT_TEST(JoinCartesianProduct) { + NYql::TAstParseResult res = SqlToYql("pragma AnsiImplicitCrossJoin; use plato; select * from A,B,C"); + UNIT_ASSERT(res.Root); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "EquiJoin") { + auto pos = line.find("Cross"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, pos); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Cross", pos + 1)); + } + }; + TWordCountHive elementStat = {{TString("EquiJoin"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["EquiJoin"]); +} - Y_UNIT_TEST(CreateAlterUserWithLoginNoLogin) { - { - auto reqCreateUser = SqlToYql(R"( +Y_UNIT_TEST(CreateAlterUserWithLoginNoLogin) { + { + auto reqCreateUser = SqlToYql(R"( USE plato; CREATE USER user1; )"); - UNIT_ASSERT(reqCreateUser.IsOk()); + UNIT_ASSERT(reqCreateUser.IsOk()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT(line.find("nullPassword") != TString::npos); - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT(line.find("nullPassword") != TString::npos); + }; - TWordCountHive elementStat = {{TString("createUser"), 0}}; - VerifyProgram(reqCreateUser, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("createUser"), 0}}; + VerifyProgram(reqCreateUser, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 1); + } - { - auto reqAlterUser = SqlToYql(R"( + { + auto reqAlterUser = SqlToYql(R"( USE plato; ALTER USER user1; )"); - UNIT_ASSERT(!reqAlterUser.IsOk()); + UNIT_ASSERT(!reqAlterUser.IsOk()); #if ANTLR_VER == 3 - UNIT_ASSERT_STRING_CONTAINS(reqAlterUser.Issues.ToString(), "Error: Unexpected token ';' : cannot match to any predicted input..."); + UNIT_ASSERT_STRING_CONTAINS(reqAlterUser.Issues.ToString(), "Error: Unexpected token ';' : cannot match to any predicted input..."); #else - UNIT_ASSERT_STRING_CONTAINS(reqAlterUser.Issues.ToString(), "Error: mismatched input ';' expecting {ENCRYPTED, HASH, LOGIN, NOLOGIN, PASSWORD, RENAME, WITH}"); + UNIT_ASSERT_STRING_CONTAINS(reqAlterUser.Issues.ToString(), "Error: mismatched input ';' expecting {ENCRYPTED, HASH, LOGIN, NOLOGIN, PASSWORD, RENAME, WITH}"); #endif - } + } - { - auto reqCreateUserLogin = SqlToYql(R"( + { + auto reqCreateUserLogin = SqlToYql(R"( USE plato; CREATE USER user1 LOgin; )"); - UNIT_ASSERT(reqCreateUserLogin.IsOk()); + UNIT_ASSERT(reqCreateUserLogin.IsOk()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "createUser") { - UNIT_ASSERT(line.find("nullPassword") != TString::npos); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "createUser") { + UNIT_ASSERT(line.find("nullPassword") != TString::npos); + } + }; - TWordCountHive elementStat = {{TString("alterUser"), 0}, {TString("createUser"), 0}}; - VerifyProgram(reqCreateUserLogin, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("alterUser"), 0}, {TString("createUser"), 0}}; + VerifyProgram(reqCreateUserLogin, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 1); - UNIT_ASSERT_VALUES_EQUAL(elementStat["alterUser"], 0); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 1); + UNIT_ASSERT_VALUES_EQUAL(elementStat["alterUser"], 0); + } - { - auto reqAlterUserLogin = SqlToYql(R"( + { + auto reqAlterUserLogin = SqlToYql(R"( USE plato; ALTER USER user1 LOgin; )"); - UNIT_ASSERT(reqAlterUserLogin.IsOk()); + UNIT_ASSERT(reqAlterUserLogin.IsOk()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "alterUser") { - UNIT_ASSERT(line.find("nullPassword") == TString::npos); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "alterUser") { + UNIT_ASSERT(line.find("nullPassword") == TString::npos); + } + }; - TWordCountHive elementStat = {{TString("alterUser"), 0}, {TString("createUser"), 0}}; - VerifyProgram(reqAlterUserLogin, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("alterUser"), 0}, {TString("createUser"), 0}}; + VerifyProgram(reqAlterUserLogin, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 0); - UNIT_ASSERT_VALUES_EQUAL(elementStat["alterUser"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 0); + UNIT_ASSERT_VALUES_EQUAL(elementStat["alterUser"], 1); + } - { - auto reqPasswordAndNoLogin = SqlToYql(R"( + { + auto reqPasswordAndNoLogin = SqlToYql(R"( USE plato; CREATE USER user1 PASSWORD '123' NOLOGIN; )"); - UNIT_ASSERT(reqPasswordAndNoLogin.IsOk()); + UNIT_ASSERT(reqPasswordAndNoLogin.IsOk()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT(line.find("nullPassword") == TString::npos); - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT(line.find("nullPassword") == TString::npos); + }; - TWordCountHive elementStat = {{TString("createUser"), 0}}; - VerifyProgram(reqPasswordAndNoLogin, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("createUser"), 0}}; + VerifyProgram(reqPasswordAndNoLogin, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 1); + } - { - auto reqAlterUserNullPassword = SqlToYql(R"( + { + auto reqAlterUserNullPassword = SqlToYql(R"( USE plato; ALTER USER user1 PASSWORD NULL; )"); - UNIT_ASSERT(reqAlterUserNullPassword.IsOk()); + UNIT_ASSERT(reqAlterUserNullPassword.IsOk()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT(line.find("nullPassword") != TString::npos); - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT(line.find("nullPassword") != TString::npos); + }; - TWordCountHive elementStat = {{TString("alterUser"), 0}}; - VerifyProgram(reqAlterUserNullPassword, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("alterUser"), 0}}; + VerifyProgram(reqAlterUserNullPassword, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["alterUser"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["alterUser"], 1); + } - auto reqLogin = SqlToYql(R"( + auto reqLogin = SqlToYql(R"( USE plato; CREATE USER user1 LOGIN; )"); - UNIT_ASSERT(reqLogin.IsOk()); + UNIT_ASSERT(reqLogin.IsOk()); - auto reqNoLogin = SqlToYql(R"( + auto reqNoLogin = SqlToYql(R"( USE plato; CREATE USER user1 NOLOGIN; )"); - UNIT_ASSERT(reqNoLogin.IsOk()); + UNIT_ASSERT(reqNoLogin.IsOk()); - auto reqLoginNoLogin = SqlToYql(R"( + auto reqLoginNoLogin = SqlToYql(R"( USE plato; CREATE USER user1 LOGIN NOLOGIN; )"); - UNIT_ASSERT(!reqLoginNoLogin.IsOk()); - UNIT_ASSERT_STRING_CONTAINS(reqLoginNoLogin.Issues.ToString(), "Error: Conflicting or redundant options"); + UNIT_ASSERT(!reqLoginNoLogin.IsOk()); + UNIT_ASSERT_STRING_CONTAINS(reqLoginNoLogin.Issues.ToString(), "Error: Conflicting or redundant options"); - auto reqAlterLoginNoLogin = SqlToYql(R"( + auto reqAlterLoginNoLogin = SqlToYql(R"( USE plato; CREATE USER user1 LOGIN; ALTER USER user1 NOLOGIN; )"); - UNIT_ASSERT(reqAlterLoginNoLogin.IsOk()); + UNIT_ASSERT(reqAlterLoginNoLogin.IsOk()); - auto reqAlterLoginNoLoginWithPassword = SqlToYql(R"( + auto reqAlterLoginNoLoginWithPassword = SqlToYql(R"( USE plato; CREATE USER user1 LOGIN; ALTER USER user1 PASSWORD '321' NOLOGIN; )"); - UNIT_ASSERT(reqAlterLoginNoLoginWithPassword.IsOk()); - } + UNIT_ASSERT(reqAlterLoginNoLoginWithPassword.IsOk()); +} - Y_UNIT_TEST(CreateUserWithHash) { - auto reqCreateUser = SqlToYql(R"( +Y_UNIT_TEST(CreateUserWithHash) { + auto reqCreateUser = SqlToYql(R"( USE plato; CREATE USER user1 HASH '{ "hash": "p4ffeMugohqyBwyckYCK1TjJfz3LIHbKiGL+t+oEhzw=", @@ -611,9 +583,9 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { }'; )"); - UNIT_ASSERT(reqCreateUser.IsOk()); + UNIT_ASSERT(reqCreateUser.IsOk()); - auto reqCreateUserWithNoLogin = SqlToYql(R"( + auto reqCreateUserWithNoLogin = SqlToYql(R"( USE plato; CREATE USER user1 HASH '{ "hash": "p4ffeMugohqyBwyckYCK1TjJfz3LIHbKiGL+t+oEhzw=", @@ -623,9 +595,9 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { NOLOGIN; )"); - UNIT_ASSERT(reqCreateUserWithNoLogin.IsOk()); + UNIT_ASSERT(reqCreateUserWithNoLogin.IsOk()); - auto reqCreateUserWithPassword = SqlToYql(R"( + auto reqCreateUserWithPassword = SqlToYql(R"( USE plato; CREATE USER user1 HASH '{ "hash": "p4ffeMugohqyBwyckYCK1TjJfz3LIHbKiGL+t+oEhzw=", @@ -635,10 +607,10 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { PASSWORD '123'; )"); - UNIT_ASSERT(!reqCreateUserWithPassword.IsOk()); - UNIT_ASSERT_STRING_CONTAINS(reqCreateUserWithPassword.Issues.ToString(), "Error: Conflicting or redundant options"); + UNIT_ASSERT(!reqCreateUserWithPassword.IsOk()); + UNIT_ASSERT_STRING_CONTAINS(reqCreateUserWithPassword.Issues.ToString(), "Error: Conflicting or redundant options"); - auto reqAlterUser = SqlToYql(R"( + auto reqAlterUser = SqlToYql(R"( USE plato; CREATE USER user1; ALTER USER user1 HASH '{ @@ -648,605 +620,602 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { }'; )"); - UNIT_ASSERT(reqAlterUser.IsOk()); - } + UNIT_ASSERT(reqAlterUser.IsOk()); +} - Y_UNIT_TEST(CreateUserQoutas) { - { - auto req = SqlToYql(R"( +Y_UNIT_TEST(CreateUserQoutas) { + { + auto req = SqlToYql(R"( use plato; CREATE USER user1 PASSWORD passwd; )"); #if ANTLR_VER == 3 - TString error = "<main>:3:43: Error: Unexpected token 'passwd' : unexpected input : nothing is expected here\n\n"; + TString error = "<main>:3:43: Error: Unexpected token 'passwd' : unexpected input : nothing is expected here\n\n"; #else - TString error = "<main>:3:43: Error: mismatched input 'passwd' expecting {NULL, STRING_VALUE}\n"; + TString error = "<main>:3:43: Error: mismatched input 'passwd' expecting {NULL, STRING_VALUE}\n"; #endif - UNIT_ASSERT_VALUES_EQUAL(Err2Str(req), error); - UNIT_ASSERT(!req.Root); - } + UNIT_ASSERT_VALUES_EQUAL(Err2Str(req), error); + UNIT_ASSERT(!req.Root); + } - { - auto req = SqlToYql(R"( + { + auto req = SqlToYql(R"( use plato; CREATE USER user2 PASSWORD NULL; )"); - UNIT_ASSERT(req.Root); - } + UNIT_ASSERT(req.Root); + } - { - auto req = SqlToYql(R"( + { + auto req = SqlToYql(R"( use plato; CREATE USER user3 PASSWORD ''; )"); - UNIT_ASSERT(req.Root); - } - + UNIT_ASSERT(req.Root); + } - { - auto req = SqlToYql(R"( + { + auto req = SqlToYql(R"( use plato; CREATE USER user1 PASSWORD 'password1'; CREATE USER user2 PASSWORD 'password2'; CREATE USER user3; )"); - UNIT_ASSERT(req.Root); - } - } - - Y_UNIT_TEST(JoinWithoutConcreteColumns) { - NYql::TAstParseResult res = SqlToYql( - " use plato;" - " SELECT a.v, b.value" - " FROM `Input1` VIEW `ksv` AS a" - " JOIN `Input2` AS b" - " ON a.k == b.key;" - ); - UNIT_ASSERT(res.Root); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "SqlProjectItem") { - UNIT_ASSERT(line.find(Quote("a.v")) != TString::npos || line.find(Quote("b.value")) != TString::npos); - } else if (word == "SqlColumn") { - const auto posTableA = line.find(Quote("a")); - const auto posTableB = line.find(Quote("b")); - if (posTableA != TString::npos) { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("v"))); - } else { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, posTableB); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("value"))); - } - } - }; - TWordCountHive elementStat = {{TString("SqlProjectStarItem"), 0}, {TString("SqlProjectItem"), 0}, {TString("SqlColumn"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(0, elementStat["SqlProjectStarItem"]); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SqlProjectItem"]); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SqlColumn"]); + UNIT_ASSERT(req.Root); } +} - Y_UNIT_TEST(JoinWithSameValues) { - NYql::TAstParseResult res = SqlToYql("SELECT a.value, b.value FROM plato.Input AS a JOIN plato.Input as b ON a.key == b.key;"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(JoinWithoutConcreteColumns) { + NYql::TAstParseResult res = SqlToYql( + " use plato;" + " SELECT a.v, b.value" + " FROM `Input1` VIEW `ksv` AS a" + " JOIN `Input2` AS b" + " ON a.k == b.key;"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "SqlProjectItem") { - const bool isValueFromA = TString::npos != line.find(Quote("a.value")); - const bool isValueFromB = TString::npos != line.find(Quote("b.value")); - UNIT_ASSERT(isValueFromA || isValueFromB); - } if (word == "Write!") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("a.a.")); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("b.b.")); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "SqlProjectItem") { + UNIT_ASSERT(line.find(Quote("a.v")) != TString::npos || line.find(Quote("b.value")) != TString::npos); + } else if (word == "SqlColumn") { + const auto posTableA = line.find(Quote("a")); + const auto posTableB = line.find(Quote("b")); + if (posTableA != TString::npos) { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("v"))); + } else { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, posTableB); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("value"))); } - }; - TWordCountHive elementStat = {{TString("SqlProjectStarItem"), 0}, {TString("SqlProjectItem"), 0}, {"Write!", 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(0, elementStat["SqlProjectStarItem"]); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SqlProjectItem"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } - - Y_UNIT_TEST(SameColumnsForDifferentTables) { - NYql::TAstParseResult res = SqlToYql("SELECT a.key, b.key FROM plato.Input as a JOIN plato.Input as b on a.key==b.key;"); - UNIT_ASSERT(res.Root); - } + } + }; + TWordCountHive elementStat = {{TString("SqlProjectStarItem"), 0}, {TString("SqlProjectItem"), 0}, {TString("SqlColumn"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(0, elementStat["SqlProjectStarItem"]); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SqlProjectItem"]); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SqlColumn"]); +} - Y_UNIT_TEST(SameColumnsForDifferentTablesFullJoin) { - NYql::TAstParseResult res = SqlToYql("SELECT a.key, b.key, a.value, b.value FROM plato.Input AS a FULL JOIN plato.Input AS b USING(key);"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(JoinWithSameValues) { + NYql::TAstParseResult res = SqlToYql("SELECT a.value, b.value FROM plato.Input AS a JOIN plato.Input as b ON a.key == b.key;"); + UNIT_ASSERT(res.Root); - Y_UNIT_TEST(JoinStreamLookupStrategyHint) { - { - NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a JOIN /*+ StreamLookup() */ plato.Input AS b USING(key);"); - UNIT_ASSERT(res.Root); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "SqlProjectItem") { + const bool isValueFromA = TString::npos != line.find(Quote("a.value")); + const bool isValueFromB = TString::npos != line.find(Quote("b.value")); + UNIT_ASSERT(isValueFromA || isValueFromB); } - //case insensitive - { - NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a JOIN /*+ streamlookup() */ plato.Input AS b USING(key);"); - UNIT_ASSERT(res.Root); + if (word == "Write!") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("a.a.")); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("b.b.")); } - } + }; + TWordCountHive elementStat = {{TString("SqlProjectStarItem"), 0}, {TString("SqlProjectItem"), 0}, {"Write!", 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(0, elementStat["SqlProjectStarItem"]); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["SqlProjectItem"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(JoinConflictingStrategyHint) { - { - NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a JOIN /*+ StreamLookup() */ /*+ Merge() */ plato.Input AS b USING(key);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:91: Error: Conflicting join strategy hints\n"); - } - } +Y_UNIT_TEST(SameColumnsForDifferentTables) { + NYql::TAstParseResult res = SqlToYql("SELECT a.key, b.key FROM plato.Input as a JOIN plato.Input as b on a.key==b.key;"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(JoinDuplicatingStrategyHint) { - { - NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a JOIN /*+ StreamLookup() */ /*+ StreamLookup() */ plato.Input AS b USING(key);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:98: Error: Duplicate join strategy hint\n"); - } - } +Y_UNIT_TEST(SameColumnsForDifferentTablesFullJoin) { + NYql::TAstParseResult res = SqlToYql("SELECT a.key, b.key, a.value, b.value FROM plato.Input AS a FULL JOIN plato.Input AS b USING(key);"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(WarnCrossJoinStrategyHint) { - NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a CROSS JOIN /*+ merge() */ plato.Input AS b;"); +Y_UNIT_TEST(JoinStreamLookupStrategyHint) { + { + NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a JOIN /*+ StreamLookup() */ plato.Input AS b USING(key);"); UNIT_ASSERT(res.Root); - UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:32: Warning: Non-default join strategy will not be used for CROSS JOIN, code: 4534\n"); } - - Y_UNIT_TEST(WarnCartesianProductStrategyHint) { - NYql::TAstParseResult res = SqlToYql("pragma AnsiImplicitCrossJoin; use plato; SELECT * FROM A, /*+ merge() */ B;"); + // case insensitive + { + NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a JOIN /*+ streamlookup() */ plato.Input AS b USING(key);"); UNIT_ASSERT(res.Root); - UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:74: Warning: Non-default join strategy will not be used for CROSS JOIN, code: 4534\n"); } +} - Y_UNIT_TEST(WarnUnknownJoinStrategyHint) { - NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a JOIN /*+ xmerge() */ plato.Input AS b USING (key);"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:41: Warning: Unsupported join hint: xmerge, code: 4534\n"); +Y_UNIT_TEST(JoinConflictingStrategyHint) { + { + NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a JOIN /*+ StreamLookup() */ /*+ Merge() */ plato.Input AS b USING(key);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:91: Error: Conflicting join strategy hints\n"); } +} - Y_UNIT_TEST(ReverseLabels) { - NYql::TAstParseResult res = SqlToYql("select in.key as subkey, subkey as key from plato.Input as in;"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(JoinDuplicatingStrategyHint) { + { + NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a JOIN /*+ StreamLookup() */ /*+ StreamLookup() */ plato.Input AS b USING(key);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:98: Error: Duplicate join strategy hint\n"); } +} - Y_UNIT_TEST(AutogenerationAliasWithoutCollisionConflict1) { - NYql::TAstParseResult res = SqlToYql("select LENGTH(Value), key as column1 from plato.Input;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(WarnCrossJoinStrategyHint) { + NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a CROSS JOIN /*+ merge() */ plato.Input AS b;"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:32: Warning: Non-default join strategy will not be used for CROSS JOIN, code: 4534\n"); +} - Y_UNIT_TEST(AutogenerationAliasWithoutCollision2Conflict2) { - NYql::TAstParseResult res = SqlToYql("select key as column0, LENGTH(Value) from plato.Input;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(WarnCartesianProductStrategyHint) { + NYql::TAstParseResult res = SqlToYql("pragma AnsiImplicitCrossJoin; use plato; SELECT * FROM A, /*+ merge() */ B;"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:74: Warning: Non-default join strategy will not be used for CROSS JOIN, code: 4534\n"); +} - Y_UNIT_TEST(InputAliasForQualifiedAsterisk) { - NYql::TAstParseResult res = SqlToYql("use plato; select zyuzya.*, key from plato.Input as zyuzya;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(WarnUnknownJoinStrategyHint) { + NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input AS a JOIN /*+ xmerge() */ plato.Input AS b USING (key);"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), "<main>:1:41: Warning: Unsupported join hint: xmerge, code: 4534\n"); +} - Y_UNIT_TEST(SelectSupportsResultColumnsWithTrailingComma) { - NYql::TAstParseResult res = SqlToYql("select a, b, c, from plato.Input;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(ReverseLabels) { + NYql::TAstParseResult res = SqlToYql("select in.key as subkey, subkey as key from plato.Input as in;"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(SelectOrderByLabeledColumn) { - NYql::TAstParseResult res = SqlToYql("pragma DisableOrderedColumns; select key as goal from plato.Input order by goal"); - UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "DataSource") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("plato")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Input")); +Y_UNIT_TEST(AutogenerationAliasWithoutCollisionConflict1) { + NYql::TAstParseResult res = SqlToYql("select LENGTH(Value), key as column1 from plato.Input;"); + UNIT_ASSERT(res.Root); +} - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("goal")); - } else if (word == "Sort") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("goal")); +Y_UNIT_TEST(AutogenerationAliasWithoutCollision2Conflict2) { + NYql::TAstParseResult res = SqlToYql("select key as column0, LENGTH(Value) from plato.Input;"); + UNIT_ASSERT(res.Root); +} - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("key")); - } - }; - TWordCountHive elementStat = {{TString("DataSource"), 0}, {TString("Sort"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["DataSource"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Sort"]); - } +Y_UNIT_TEST(InputAliasForQualifiedAsterisk) { + NYql::TAstParseResult res = SqlToYql("use plato; select zyuzya.*, key from plato.Input as zyuzya;"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(SelectOrderBySimpleExpr) { - NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by a + a"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(SelectSupportsResultColumnsWithTrailingComma) { + NYql::TAstParseResult res = SqlToYql("select a, b, c, from plato.Input;"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(SelectAssumeOrderByTableRowAccess) { - NYql::TAstParseResult res = SqlToYql("$key = 'foo';select * from plato.Input assume order by TableRow().$key"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(SelectOrderByLabeledColumn) { + NYql::TAstParseResult res = SqlToYql("pragma DisableOrderedColumns; select key as goal from plato.Input order by goal"); + UNIT_ASSERT(res.Root); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "DataSource") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("plato")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Input")); - Y_UNIT_TEST(SelectOrderByDuplicateLabels) { - NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by a, a"); - UNIT_ASSERT(res.Root); - } + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("goal")); + } else if (word == "Sort") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("goal")); - Y_UNIT_TEST(SelectOrderByExpression) { - NYql::TAstParseResult res = SqlToYql("select * from plato.Input as i order by cast(key as uint32) + cast(subkey as uint32)"); - UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Sort") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"+MayWarn\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("key")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("subkey")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Bool 'true)")); - - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("i.key")); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("i.subkey")); - } - }; - TWordCountHive elementStat = {{TString("Sort"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Sort"]); - } + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("key")); + } + }; + TWordCountHive elementStat = {{TString("DataSource"), 0}, {TString("Sort"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["DataSource"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Sort"]); +} - Y_UNIT_TEST(SelectOrderByExpressionDesc) { - NYql::TAstParseResult res = SqlToYql("pragma disablesimplecolumns; select i.*, key, subkey from plato.Input as i order by cast(i.key as uint32) - cast(i.subkey as uint32) desc"); - UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Sort") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"-MayWarn\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"key\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"subkey\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Bool 'false)")); - } else if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'columns")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"key\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"subkey\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("prefix")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"i.\"")); - } - }; - TWordCountHive elementStat = {{TString("Sort"), 0}, {TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Sort"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } +Y_UNIT_TEST(SelectOrderBySimpleExpr) { + NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by a + a"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(SelectOrderByExpressionAsc) { - NYql::TAstParseResult res = SqlToYql("select i.key, i.subkey from plato.Input as i order by cast(key as uint32) % cast(i.subkey as uint32) asc"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Sort") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"%MayWarn\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"key\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"subkey\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Bool 'true)")); - } else if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'columns")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"key\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"subkey\"")); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("i.")); - } - }; - TWordCountHive elementStat = {{TString("Sort"), 0}, {TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Sort"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } +Y_UNIT_TEST(SelectAssumeOrderByTableRowAccess) { + NYql::TAstParseResult res = SqlToYql("$key = 'foo';select * from plato.Input assume order by TableRow().$key"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(ReferenceToKeyInSubselect) { - NYql::TAstParseResult res = SqlToYql("select b.key from (select a.key from plato.Input as a) as b;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(SelectOrderByDuplicateLabels) { + NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by a, a"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(OrderByCastValue) { - NYql::TAstParseResult res = SqlToYql("select i.key, i.subkey from plato.Input as i order by cast(key as uint32) desc;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(SelectOrderByExpression) { + NYql::TAstParseResult res = SqlToYql("select * from plato.Input as i order by cast(key as uint32) + cast(subkey as uint32)"); + UNIT_ASSERT(res.Root); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Sort") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"+MayWarn\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("key")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("subkey")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Bool 'true)")); + + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("i.key")); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("i.subkey")); + } + }; + TWordCountHive elementStat = {{TString("Sort"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Sort"]); +} - Y_UNIT_TEST(GroupByCastValue) { - NYql::TAstParseResult res = SqlToYql("select count(1) from plato.Input as i group by cast(key as uint8);"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(SelectOrderByExpressionDesc) { + NYql::TAstParseResult res = SqlToYql("pragma disablesimplecolumns; select i.*, key, subkey from plato.Input as i order by cast(i.key as uint32) - cast(i.subkey as uint32) desc"); + UNIT_ASSERT(res.Root); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Sort") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"-MayWarn\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"key\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"subkey\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Bool 'false)")); + } else if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'columns")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"key\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"subkey\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("prefix")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"i.\"")); + } + }; + TWordCountHive elementStat = {{TString("Sort"), 0}, {TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Sort"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(KeywordInSelectColumns) { - NYql::TAstParseResult res = SqlToYql("select in, s.check from (select 1 as in, \"test\" as check) as s;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(SelectOrderByExpressionAsc) { + NYql::TAstParseResult res = SqlToYql("select i.key, i.subkey from plato.Input as i order by cast(key as uint32) % cast(i.subkey as uint32) asc"); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Sort") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"%MayWarn\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"key\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"subkey\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Bool 'true)")); + } else if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'columns")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"key\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"subkey\"")); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("i.")); + } + }; + TWordCountHive elementStat = {{TString("Sort"), 0}, {TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Sort"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(SelectAllGroupBy) { - NYql::TAstParseResult res = SqlToYql("select * from plato.Input group by subkey;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(ReferenceToKeyInSubselect) { + NYql::TAstParseResult res = SqlToYql("select b.key from (select a.key from plato.Input as a) as b;"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(CreateObjectWithFeatures) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT secretId (TYPE SECRET) WITH (Key1=Value1, K2=V2);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(OrderByCastValue) { + NYql::TAstParseResult res = SqlToYql("select i.key, i.subkey from plato.Input as i order by cast(key as uint32) desc;"); + UNIT_ASSERT(res.Root); +} - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('\"K2\" '\"V2\") '('\"Key1\" '\"Value1\")")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; +Y_UNIT_TEST(GroupByCastValue) { + NYql::TAstParseResult res = SqlToYql("select count(1) from plato.Input as i group by cast(key as uint8);"); + UNIT_ASSERT(res.Root); +} - TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} }; - VerifyProgram(res, elementStat, verifyLine); +Y_UNIT_TEST(KeywordInSelectColumns) { + NYql::TAstParseResult res = SqlToYql("select in, s.check from (select 1 as in, \"test\" as check) as s;"); + UNIT_ASSERT(res.Root); +} - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); - } +Y_UNIT_TEST(SelectAllGroupBy) { + NYql::TAstParseResult res = SqlToYql("select * from plato.Input group by subkey;"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(CreateObjectIfNotExists) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT IF NOT EXISTS secretId (TYPE SECRET) WITH (Key1=Value1, K2=V2);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateObjectWithFeatures) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT secretId (TYPE SECRET) WITH (Key1=Value1, K2=V2);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObjectIfNotExists")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('\"K2\" '\"V2\") '('\"Key1\" '\"Value1\")")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); +} - Y_UNIT_TEST(CreateObjectWithFeaturesStrings) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT secretId (TYPE SECRET) WITH (Key1=\"Value1\", K2='V2', K3=V3, K4='', K5=`aaa`, K6='a\\'aa');"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateObjectIfNotExists) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT IF NOT EXISTS secretId (TYPE SECRET) WITH (Key1=Value1, K2=V2);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('\"K2\" '\"V2\") '('\"K3\" '\"V3\") '('\"K4\" '\"\") '('\"K5\" '\"aaa\") '('\"K6\" '\"a'aa\") '('\"Key1\" '\"Value1\")")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObjectIfNotExists")); + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - } + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - Y_UNIT_TEST(UpsertObjectWithFeatures) { - NYql::TAstParseResult res = SqlToYql("USE plato; UPSERT OBJECT secretId (TYPE SECRET) WITH (Key1=Value1, K2=V2);"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); +} - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('\"K2\" '\"V2\") '('\"Key1\" '\"Value1\")")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("upsertObject")); - } - }; +Y_UNIT_TEST(CreateObjectWithFeaturesStrings) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT secretId (TYPE SECRET) WITH (Key1=\"Value1\", K2='V2', K3=V3, K4='', K5=`aaa`, K6='a\\'aa');"); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('\"K2\" '\"V2\") '('\"K3\" '\"V3\") '('\"K4\" '\"\") '('\"K5\" '\"aaa\") '('\"K6\" '\"a'aa\") '('\"Key1\" '\"Value1\")")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); - } + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; + VerifyProgram(res, elementStat, verifyLine); +} - Y_UNIT_TEST(CreateObjectWithFeaturesAndFlags) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT secretId (TYPE SECRET) WITH (Key1=Value1, K2=V2, RECURSE);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(UpsertObjectWithFeatures) { + NYql::TAstParseResult res = SqlToYql("USE plato; UPSERT OBJECT secretId (TYPE SECRET) WITH (Key1=Value1, K2=V2);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('\"Key1\" '\"Value1\") '('\"RECURSE\")")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('\"K2\" '\"V2\") '('\"Key1\" '\"Value1\")")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("upsertObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); +} - Y_UNIT_TEST(Select1Type) { - NYql::TAstParseResult res = SqlToYql("SELECT 1 type;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(CreateObjectWithFeaturesAndFlags) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT secretId (TYPE SECRET) WITH (Key1=Value1, K2=V2, RECURSE);"); + UNIT_ASSERT(res.Root); - Y_UNIT_TEST(SelectTableType) { - NYql::TAstParseResult res = SqlToYql("USE plato; SELECT * from T type;"); - UNIT_ASSERT(res.Root); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('\"Key1\" '\"Value1\") '('\"RECURSE\")")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - Y_UNIT_TEST(CreateObjectNoFeatures) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT secretId (TYPE SECRET);"); - UNIT_ASSERT(res.Root); + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); +} - TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} }; - VerifyProgram(res, elementStat, verifyLine); +Y_UNIT_TEST(Select1Type) { + NYql::TAstParseResult res = SqlToYql("SELECT 1 type;"); + UNIT_ASSERT(res.Root); +} - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); - } +Y_UNIT_TEST(SelectTableType) { + NYql::TAstParseResult res = SqlToYql("USE plato; SELECT * from T type;"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(AlterObjectWithFeatures) { - NYql::TAstParseResult res = SqlToYql( - "USE plato;\n" - "declare $path as String;\n" - "ALTER OBJECT secretId (TYPE SECRET) SET (Key1=$path, K2=V2);" - ); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateObjectNoFeatures) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT secretId (TYPE SECRET);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'features")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'\"Key1\" (EvaluateAtom \"$path\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'\"K2\" '\"V2\"")); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alterObject")); - } - }; + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); +} - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); - } +Y_UNIT_TEST(AlterObjectWithFeatures) { + NYql::TAstParseResult res = SqlToYql( + "USE plato;\n" + "declare $path as String;\n" + "ALTER OBJECT secretId (TYPE SECRET) SET (Key1=$path, K2=V2);"); + UNIT_ASSERT(res.Root); - Y_UNIT_TEST(AlterObjectNoFeatures) { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER OBJECT secretId (TYPE SECRET);"); - UNIT_ASSERT(!res.Root); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'features")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'\"Key1\" (EvaluateAtom \"$path\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'\"K2\" '\"V2\"")); - Y_UNIT_TEST(DropObjectNoFeatures) { - NYql::TAstParseResult res = SqlToYql("USE plato; DROP OBJECT secretId (TYPE SECRET);"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alterObject")); + } + }; - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); - } - }; + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); +} - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); - } +Y_UNIT_TEST(AlterObjectNoFeatures) { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER OBJECT secretId (TYPE SECRET);"); + UNIT_ASSERT(!res.Root); +} - Y_UNIT_TEST(DropObjectWithFeatures) { - NYql::TAstParseResult res = SqlToYql("USE plato; DROP OBJECT secretId (TYPE SECRET) WITH (A, B, C);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(DropObjectNoFeatures) { + NYql::TAstParseResult res = SqlToYql("USE plato; DROP OBJECT secretId (TYPE SECRET);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'features")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); +} - Y_UNIT_TEST(DropObjectWithOneOption) { - NYql::TAstParseResult res = SqlToYql("USE plato; DROP OBJECT secretId (TYPE SECRET) WITH OVERRIDE;"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(DropObjectWithFeatures) { + NYql::TAstParseResult res = SqlToYql("USE plato; DROP OBJECT secretId (TYPE SECRET) WITH (A, B, C);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'features")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'\"OVERRIDE\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'features")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); +} - Y_UNIT_TEST(DropObjectIfExists) { - NYql::TAstParseResult res = SqlToYql("USE plato; DROP OBJECT IF EXISTS secretId (TYPE SECRET);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(DropObjectWithOneOption) { + NYql::TAstParseResult res = SqlToYql("USE plato; DROP OBJECT secretId (TYPE SECRET) WITH OVERRIDE;"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObjectIfExists")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'features")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'\"OVERRIDE\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); +} - Y_UNIT_TEST(PrimaryKeyParseCorrect) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE tableName (Key Uint32, Subkey Int64, Value String, PRIMARY KEY (Key, Subkey));"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(DropObjectIfExists) { + NYql::TAstParseResult res = SqlToYql("USE plato; DROP OBJECT IF EXISTS secretId (TYPE SECRET);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"Key\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"Subkey\"")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObjectIfExists")); + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}, {TString("primarykey"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("SECRET"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["primarykey"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]); +} - Y_UNIT_TEST(AlterDatabaseAst) { - NYql::TAstParseResult request = SqlToYql("USE plato; ALTER DATABASE `/Root/test` OWNER TO user1;"); - UNIT_ASSERT_C(request.IsOk(), request.Issues.ToString()); +Y_UNIT_TEST(PrimaryKeyParseCorrect) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE tableName (Key Uint32, Subkey Int64, Value String, PRIMARY KEY (Key, Subkey));"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - Y_UNUSED(word); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"Key\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"Subkey\"")); + } + }; - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find( - R"(let world (Write! world sink (Key '('databasePath (String '"/Root/test"))) (Void) '('('mode 'alterDatabase) '('owner '"user1"))))" - )); - }; + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("primarykey"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - TWordCountHive elementStat({TString("\'mode \'alterDatabase")}); - VerifyProgram(request, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'mode \'alterDatabase"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["primarykey"]); +} - Y_UNIT_TEST(AlterDatabaseSetting) { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER DATABASE `/Root/test` SET (key1 = 1);"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); +Y_UNIT_TEST(AlterDatabaseAst) { + NYql::TAstParseResult request = SqlToYql("USE plato; ALTER DATABASE `/Root/test` OWNER TO user1;"); + UNIT_ASSERT_C(request.IsOk(), request.Issues.ToString()); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_STRING_CONTAINS(line, "(Key '('databasePath (String '\"/Root/test\")))"); - UNIT_ASSERT_STRING_CONTAINS(line, "'('('mode 'alterDatabase) '('\"KEY1\" (Uint64 '\"1\")))"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + Y_UNUSED(word); - TWordCountHive elementStat = { {"Write!"} }; - VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find( + R"(let world (Write! world sink (Key '('databasePath (String '"/Root/test"))) (Void) '('('mode 'alterDatabase) '('owner '"user1"))))")); + }; - UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); - } + TWordCountHive elementStat({TString("\'mode \'alterDatabase")}); + VerifyProgram(request, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'mode \'alterDatabase"]); +} - Y_UNIT_TEST(AlterDatabaseSettings) { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER DATABASE `/Root/test` SET (key1 = 1, key2 = \"2\", key3 = true);"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); +Y_UNIT_TEST(AlterDatabaseSetting) { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER DATABASE `/Root/test` SET (key1 = 1);"); + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_STRING_CONTAINS(line, "(Key '('databasePath (String '\"/Root/test\")))"); - UNIT_ASSERT_STRING_CONTAINS(line, "'('mode 'alterDatabase)"); - UNIT_ASSERT_STRING_CONTAINS(line, "'('\"KEY1\" (Uint64 '\"1\"))"); - UNIT_ASSERT_STRING_CONTAINS(line, "'('\"KEY2\" (String '\"2\"))"); - UNIT_ASSERT_STRING_CONTAINS(line, "'('\"KEY3\" (Bool '\"true\"))"); - } - }; + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_STRING_CONTAINS(line, "(Key '('databasePath (String '\"/Root/test\")))"); + UNIT_ASSERT_STRING_CONTAINS(line, "'('('mode 'alterDatabase) '('\"KEY1\" (Uint64 '\"1\")))"); + } + }; - TWordCountHive elementStat = { {"Write!"} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{"Write!"}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); +} - Y_UNIT_TEST(CreateTableDublicateOptions) { - { - NYql::TAstParseResult req = SqlToYql(R"sql( +Y_UNIT_TEST(AlterDatabaseSettings) { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER DATABASE `/Root/test` SET (key1 = 1, key2 = \"2\", key3 = true);"); + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); + + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_STRING_CONTAINS(line, "(Key '('databasePath (String '\"/Root/test\")))"); + UNIT_ASSERT_STRING_CONTAINS(line, "'('mode 'alterDatabase)"); + UNIT_ASSERT_STRING_CONTAINS(line, "'('\"KEY1\" (Uint64 '\"1\"))"); + UNIT_ASSERT_STRING_CONTAINS(line, "'('\"KEY2\" (String '\"2\"))"); + UNIT_ASSERT_STRING_CONTAINS(line, "'('\"KEY3\" (Bool '\"true\"))"); + } + }; + + TWordCountHive elementStat = {{"Write!"}}; + VerifyProgram(res, elementStat, verifyLine); + + UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); +} + +Y_UNIT_TEST(CreateTableDublicateOptions) { + { + NYql::TAstParseResult req = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1255,12 +1224,12 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT(!req.IsOk()); - UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('NOT NULL' option can be specified only once)"); - } + UNIT_ASSERT(!req.IsOk()); + UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('NOT NULL' option can be specified only once)"); + } - { - NYql::TAstParseResult req = SqlToYql(R"sql( + { + NYql::TAstParseResult req = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1269,12 +1238,12 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT(!req.IsOk()); - UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('NOT NULL' option can be specified only once)"); - } + UNIT_ASSERT(!req.IsOk()); + UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('NOT NULL' option can be specified only once)"); + } - { - NYql::TAstParseResult req = SqlToYql(R"sql( + { + NYql::TAstParseResult req = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1283,12 +1252,12 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT(!req.IsOk()); - UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('DEFAULT' option can be specified only once)"); - } + UNIT_ASSERT(!req.IsOk()); + UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('DEFAULT' option can be specified only once)"); + } - { - NYql::TAstParseResult req = SqlToYql(R"sql( + { + NYql::TAstParseResult req = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1297,12 +1266,12 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT(!req.IsOk()); - UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('DEFAULT' option can be specified only once)"); - } + UNIT_ASSERT(!req.IsOk()); + UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('DEFAULT' option can be specified only once)"); + } - { - NYql::TAstParseResult req = SqlToYql(R"sql( + { + NYql::TAstParseResult req = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1319,12 +1288,12 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT(!req.IsOk()); - UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('FAMILY' option can be specified only once)"); - } + UNIT_ASSERT(!req.IsOk()); + UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('FAMILY' option can be specified only once)"); + } - { - NYql::TAstParseResult req = SqlToYql(R"sql( + { + NYql::TAstParseResult req = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1341,13 +1310,13 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT(!req.IsOk()); - UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('FAMILY' option can be specified only once)"); - } + UNIT_ASSERT(!req.IsOk()); + UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('FAMILY' option can be specified only once)"); } +} - Y_UNIT_TEST(CreateTableFamilyAndNotNullInOrder) { - NYql::TAstParseResult familyBeforeConstraint = SqlToYql(R"sql( +Y_UNIT_TEST(CreateTableFamilyAndNotNullInOrder) { + NYql::TAstParseResult familyBeforeConstraint = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1364,22 +1333,22 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT_C(familyBeforeConstraint.IsOk(), familyBeforeConstraint.Issues.ToString()); + UNIT_ASSERT_C(familyBeforeConstraint.IsOk(), familyBeforeConstraint.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__('('columnConstrains '('('not_null))) '('"family_large")))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__('('columnConstrains '('('not_null))) '('"family_large")))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(familyBeforeConstraint, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(familyBeforeConstraint, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTableFamilyAndNotNullReversed) { - NYql::TAstParseResult familyAfterConstraint = SqlToYql(R"sql( +Y_UNIT_TEST(CreateTableFamilyAndNotNullReversed) { + NYql::TAstParseResult familyAfterConstraint = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1396,23 +1365,23 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT_C(familyAfterConstraint.IsOk(), familyAfterConstraint.Issues.ToString()); + UNIT_ASSERT_C(familyAfterConstraint.IsOk(), familyAfterConstraint.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__('('columnConstrains '('('not_null))) '('"family_large")))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__('('columnConstrains '('('not_null))) '('"family_large")))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(familyAfterConstraint, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(familyAfterConstraint, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTableNotNullInsideDefault) { - { - NYql::TAstParseResult req = SqlToYql(R"sql( +Y_UNIT_TEST(CreateTableNotNullInsideDefault) { + { + NYql::TAstParseResult req = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1421,12 +1390,12 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT(!req.IsOk()); - UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('DEFAULT' option can not use expr which contains literall 'NOT NULL')"); - } + UNIT_ASSERT(!req.IsOk()); + UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('DEFAULT' option can not use expr which contains literall 'NOT NULL')"); + } - { - NYql::TAstParseResult req = SqlToYql(R"sql( + { + NYql::TAstParseResult req = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1435,12 +1404,12 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT(!req.IsOk()); - UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('DEFAULT' option can not use expr which contains literall 'NOT NULL')"); - } + UNIT_ASSERT(!req.IsOk()); + UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('DEFAULT' option can not use expr which contains literall 'NOT NULL')"); + } - { - NYql::TAstParseResult req = SqlToYql(R"sql( + { + NYql::TAstParseResult req = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1449,13 +1418,13 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT(!req.IsOk()); - UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('DEFAULT' option can not use expr which contains literall 'NOT NULL')"); - } + UNIT_ASSERT(!req.IsOk()); + UNIT_ASSERT_STRING_CONTAINS(req.Issues.ToString(), R"('DEFAULT' option can not use expr which contains literall 'NOT NULL')"); } +} - Y_UNIT_TEST(CreateTableDefaultAndNotNullInOrderWithComma) { - NYql::TAstParseResult defaultBeforeConstraint = SqlToYql(R"sql( +Y_UNIT_TEST(CreateTableDefaultAndNotNullInOrderWithComma) { + NYql::TAstParseResult defaultBeforeConstraint = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1464,22 +1433,22 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT_C(defaultBeforeConstraint.IsOk(), defaultBeforeConstraint.Issues.ToString()); + UNIT_ASSERT_C(defaultBeforeConstraint.IsOk(), defaultBeforeConstraint.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__(('columnConstrains '('('not_null) '('default (Bool '"false")))) '()))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__(('columnConstrains '('('not_null) '('default (Bool '"false")))) '()))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(defaultBeforeConstraint, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(defaultBeforeConstraint, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTableDefaultAndNotNullReversed) { - NYql::TAstParseResult defaultAfterConstraint = SqlToYql(R"sql( +Y_UNIT_TEST(CreateTableDefaultAndNotNullReversed) { + NYql::TAstParseResult defaultAfterConstraint = SqlToYql(R"sql( USE plato; CREATE TABLE tbl ( k Uint64, @@ -1488,568 +1457,568 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )sql"); - UNIT_ASSERT_C(defaultAfterConstraint.IsOk(), defaultAfterConstraint.Issues.ToString()); + UNIT_ASSERT_C(defaultAfterConstraint.IsOk(), defaultAfterConstraint.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__('('columnConstrains '('('not_null) '('default (Int32 '"0")))) '()))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__('('columnConstrains '('('not_null) '('default (Int32 '"0")))) '()))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(defaultAfterConstraint, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(defaultAfterConstraint, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTableNonNullableYqlTypeAstCorrect) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32 not null);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateTableNonNullableYqlTypeAstCorrect) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32 not null);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (DataType 'Int32) '('columnConstrains '('('not_null))) '())))))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (DataType 'Int32) '('columnConstrains '('('not_null))) '())))))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTableNullableYqlTypeAstCorrect) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateTableNullableYqlTypeAstCorrect) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTableNonNullablePgTypeAstCorrect) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a pg_int4 not null);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateTableNonNullablePgTypeAstCorrect) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a pg_int4 not null);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (PgType '_int4) '('columnConstrains '('('not_null))) '())))))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (PgType '_int4) '('columnConstrains '('('not_null))) '())))))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTableNullablePgTypeAstCorrect) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a pg_int4);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateTableNullablePgTypeAstCorrect) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a pg_int4);"); + UNIT_ASSERT(res.Root); - res.Root->PrettyPrintTo(Cout, PRETTY_FLAGS); + res.Root->PrettyPrintTo(Cout, PRETTY_FLAGS); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (AsOptionalType (PgType '_int4)) '('columnConstrains '()) '()))))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (AsOptionalType (PgType '_int4)) '('columnConstrains '()) '()))))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTableNullPkColumnsAreAllowed) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32, primary key(a));"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateTableNullPkColumnsAreAllowed) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32, primary key(a));"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))) '('primarykey '('"a")))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))) '('primarykey '('"a")))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTableNotNullPkColumnsAreIdempotentAstCorrect) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32 not null, primary key(a));"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateTableNotNullPkColumnsAreIdempotentAstCorrect) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32 not null, primary key(a));"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (DataType 'Int32) '('columnConstrains '('('not_null))) '()))) '('primarykey '('"a"))))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (DataType 'Int32) '('columnConstrains '('('not_null))) '()))) '('primarykey '('"a"))))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTableWithIfNotExists) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE IF NOT EXISTS t (a int32, primary key(a));"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateTableWithIfNotExists) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE IF NOT EXISTS t (a int32, primary key(a));"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create_if_not_exists) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))) '('primarykey '('"a")))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create_if_not_exists) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))) '('primarykey '('"a")))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTempTable) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TEMP TABLE t (a int32, primary key(a));"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateTempTable) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TEMP TABLE t (a int32, primary key(a));"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, - line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))) '('primarykey '('"a")) '('temporary))))__"), line); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, + line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))) '('primarykey '('"a")) '('temporary))))__"), line); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTemporaryTable) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TEMPORARY TABLE t (a int32, primary key(a));"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(CreateTemporaryTable) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TEMPORARY TABLE t (a int32, primary key(a));"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, - line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))) '('primarykey '('"a")) '('temporary))))__"), line); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, + line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))) '('primarykey '('"a")) '('temporary))))__"), line); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); +} - Y_UNIT_TEST(CreateTableWithoutTypes) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a, primary key(a));"); - UNIT_ASSERT(!res.Root); - } +Y_UNIT_TEST(CreateTableWithoutTypes) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a, primary key(a));"); + UNIT_ASSERT(!res.Root); +} - Y_UNIT_TEST(CreateTableAsSelectWithTypes) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32, primary key(a)) AS SELECT * FROM ts;"); - UNIT_ASSERT(!res.Root); - } +Y_UNIT_TEST(CreateTableAsSelectWithTypes) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32, primary key(a)) AS SELECT * FROM ts;"); + UNIT_ASSERT(!res.Root); +} - Y_UNIT_TEST(CreateTableAsSelect) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a, b, primary key(a)) AS SELECT * FROM ts;"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); +Y_UNIT_TEST(CreateTableAsSelect) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a, b, primary key(a)) AS SELECT * FROM ts;"); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((let world (Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a") '('"b"))) '('primarykey '('"a"))))))__")); - } - if (word == "Read!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((Read! world (DataSource '"yt" '"plato") (MrTableConcat (Key '('table (String '"ts")))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((let world (Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '('('"a") '('"b"))) '('primarykey '('"a"))))))__")); + } + if (word == "Read!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((Read! world (DataSource '"yt" '"plato") (MrTableConcat (Key '('table (String '"ts")))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}, {TString("Read!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}, {TString("Read!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Read!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Read!"]); +} - Y_UNIT_TEST(CreateTableAsSelectOnlyPrimary) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (primary key(a)) AS SELECT * FROM ts;"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); +Y_UNIT_TEST(CreateTableAsSelectOnlyPrimary) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (primary key(a)) AS SELECT * FROM ts;"); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((let world (Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '()) '('primarykey '('"a"))))))__")); - } - if (word == "Read!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((Read! world (DataSource '"yt" '"plato") (MrTableConcat (Key '('table (String '"ts")))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((let world (Write! world sink (Key '('tablescheme (String '"t"))) values '('('mode 'create) '('columns '()) '('primarykey '('"a"))))))__")); + } + if (word == "Read!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((Read! world (DataSource '"yt" '"plato") (MrTableConcat (Key '('table (String '"ts")))))__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}, {TString("Read!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}, {TString("Read!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Read!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Read!"]); +} - Y_UNIT_TEST(CreateTableAsValuesFail) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a, primary key(a)) AS VALUES (1), (2);"); - UNIT_ASSERT(!res.Root); - } +Y_UNIT_TEST(CreateTableAsValuesFail) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a, primary key(a)) AS VALUES (1), (2);"); + UNIT_ASSERT(!res.Root); +} - Y_UNIT_TEST(CreateTableDuplicatedPkColumnsFail) { - NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32 not null, primary key(a, a));"); - UNIT_ASSERT(!res.Root); - } +Y_UNIT_TEST(CreateTableDuplicatedPkColumnsFail) { + NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32 not null, primary key(a, a));"); + UNIT_ASSERT(!res.Root); +} - Y_UNIT_TEST(DeleteFromTableByKey) { - NYql::TAstParseResult res = SqlToYql("delete from plato.Input where key = 200;", 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(DeleteFromTableByKey) { + NYql::TAstParseResult res = SqlToYql("delete from plato.Input where key = 200;", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'delete)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'delete)")); + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DeleteFromTable) { - NYql::TAstParseResult res = SqlToYql("delete from plato.Input;", 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(DeleteFromTable) { + NYql::TAstParseResult res = SqlToYql("delete from plato.Input;", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'delete)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'delete)")); + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DeleteFromTableBatch) { - NYql::TAstParseResult res = SqlToYql("batch delete from plato.Input;", 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(DeleteFromTableBatch) { + NYql::TAstParseResult res = SqlToYql("batch delete from plato.Input;", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'delete)")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('is_batch 'true)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'delete)")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('is_batch 'true)")); + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DeleteFromTableBatchReturning) { - NYql::TAstParseResult res = SqlToYql("batch delete from plato.Input returning *;", 10, "kikimr"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:6: Error: BATCH DELETE is unsupported with RETURNING\n"); - } +Y_UNIT_TEST(DeleteFromTableBatchReturning) { + NYql::TAstParseResult res = SqlToYql("batch delete from plato.Input returning *;", 10, "kikimr"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:6: Error: BATCH DELETE is unsupported with RETURNING\n"); +} - Y_UNIT_TEST(DeleteFromTableOnValues) { - NYql::TAstParseResult res = SqlToYql("delete from plato.Input on (key) values (1);", - 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(DeleteFromTableOnValues) { + NYql::TAstParseResult res = SqlToYql("delete from plato.Input on (key) values (1);", + 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'delete_on)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'delete_on)")); + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DeleteFromTableOnSelect) { - NYql::TAstParseResult res = SqlToYql( - "delete from plato.Input on select key from plato.Input where value > 0;", 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(DeleteFromTableOnSelect) { + NYql::TAstParseResult res = SqlToYql( + "delete from plato.Input on select key from plato.Input where value > 0;", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'delete_on)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'delete_on)")); + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DeleteFromTableOnBatch) { - NYql::TAstParseResult res = SqlToYql("batch delete from plato.Input on (key) values (1);", - 10, "kikimr"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:6: Error: BATCH DELETE is unsupported with ON\n"); - } +Y_UNIT_TEST(DeleteFromTableOnBatch) { + NYql::TAstParseResult res = SqlToYql("batch delete from plato.Input on (key) values (1);", + 10, "kikimr"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:6: Error: BATCH DELETE is unsupported with ON\n"); +} - Y_UNIT_TEST(UpdateByValues) { - NYql::TAstParseResult res = SqlToYql("update plato.Input set key = 777, value = 'cool' where key = 200;", 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(UpdateByValues) { + NYql::TAstParseResult res = SqlToYql("update plato.Input set key = 777, value = 'cool' where key = 200;", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update)")); - } else if (word == "AsStruct") { - const bool isKey = line.find("key") != TString::npos; - const bool isValue = line.find("value") != TString::npos; - UNIT_ASSERT(isKey || isValue); - if (isKey) { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("777"))); - } else if (isValue) { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("cool"))); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update)")); + } else if (word == "AsStruct") { + const bool isKey = line.find("key") != TString::npos; + const bool isValue = line.find("value") != TString::npos; + UNIT_ASSERT(isKey || isValue); + if (isKey) { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("777"))); + } else if (isValue) { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("cool"))); } - }; + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}, {TString("AsStruct"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("AsStruct"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["AsStruct"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["AsStruct"]); +} - Y_UNIT_TEST(UpdateByValuesBatch) { - NYql::TAstParseResult res = SqlToYql("batch update plato.Input set key = 777, value = 'cool' where key = 200;", 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(UpdateByValuesBatch) { + NYql::TAstParseResult res = SqlToYql("batch update plato.Input set key = 777, value = 'cool' where key = 200;", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update)")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('is_batch 'true)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update)")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('is_batch 'true)")); + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(UpdateByValuesBatchReturning) { - NYql::TAstParseResult res = SqlToYql("batch update plato.Input set value = 'cool' where key = 200 returning key;", 10, "kikimr"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:6: Error: BATCH UPDATE is unsupported with RETURNING\n"); - } +Y_UNIT_TEST(UpdateByValuesBatchReturning) { + NYql::TAstParseResult res = SqlToYql("batch update plato.Input set value = 'cool' where key = 200 returning key;", 10, "kikimr"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:6: Error: BATCH UPDATE is unsupported with RETURNING\n"); +} - Y_UNIT_TEST(UpdateByMultiValues) { - NYql::TAstParseResult res = SqlToYql("update plato.Input set (key, value, subkey) = ('2','ddd',':') where key = 200;", 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(UpdateByMultiValues) { + NYql::TAstParseResult res = SqlToYql("update plato.Input set (key, value, subkey) = ('2','ddd',':') where key = 200;", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update)")); - } else if (word == "AsStruct") { - const bool isKey = line.find("key") != TString::npos; - const bool isSubkey = line.find("subkey") != TString::npos; - const bool isValue = line.find("value") != TString::npos; - UNIT_ASSERT(isKey || isSubkey || isValue); - if (isKey && !isSubkey) { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("2"))); - } else if (isSubkey) { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote(":"))); - } else if (isValue) { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("ddd"))); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update)")); + } else if (word == "AsStruct") { + const bool isKey = line.find("key") != TString::npos; + const bool isSubkey = line.find("subkey") != TString::npos; + const bool isValue = line.find("value") != TString::npos; + UNIT_ASSERT(isKey || isSubkey || isValue); + if (isKey && !isSubkey) { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("2"))); + } else if (isSubkey) { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote(":"))); + } else if (isValue) { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("ddd"))); } - }; - - TWordCountHive elementStat = {{TString("Write"), 0}, {TString("AsStruct"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + } + }; - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["AsStruct"]); - } + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("AsStruct"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - Y_UNIT_TEST(UpdateBySelect) { - NYql::TAstParseResult res = SqlToYql("update plato.Input set (key, value, subkey) = (select key, value, subkey from plato.Input where key = 911) where key = 200;", 10, "kikimr"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["AsStruct"]); +} - int lineIndex = 0; - int writeLineIndex = -1; - bool found = false; +Y_UNIT_TEST(UpdateBySelect) { + NYql::TAstParseResult res = SqlToYql("update plato.Input set (key, value, subkey) = (select key, value, subkey from plato.Input where key = 911) where key = 200;", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [&lineIndex, &writeLineIndex, &found](const TString& word, const TString& line) { - if (word == "Write") { - writeLineIndex = lineIndex; - found = line.find("('mode 'update)") != TString::npos; - } else if (word == "mode") { - found |= lineIndex == writeLineIndex + 1 && line.find("('mode 'update)") != TString::npos; - UNIT_ASSERT(found); - } + int lineIndex = 0; + int writeLineIndex = -1; + bool found = false; + + TVerifyLineFunc verifyLine = [&lineIndex, &writeLineIndex, &found](const TString& word, const TString& line) { + if (word == "Write") { + writeLineIndex = lineIndex; + found = line.find("('mode 'update)") != TString::npos; + } else if (word == "mode") { + found |= lineIndex == writeLineIndex + 1 && line.find("('mode 'update)") != TString::npos; + UNIT_ASSERT(found); + } - ++lineIndex; - }; + ++lineIndex; + }; - TWordCountHive elementStat = {{TString("Write"), 0}, {TString("mode"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("mode"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(UpdateSelfModifyAll) { - NYql::TAstParseResult res = SqlToYql("update plato.Input set subkey = subkey + 's';", 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(UpdateSelfModifyAll) { + NYql::TAstParseResult res = SqlToYql("update plato.Input set subkey = subkey + 's';", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update)")); - } else if (word == "AsStruct") { - const bool isSubkey = line.find("subkey") != TString::npos; - UNIT_ASSERT(isSubkey); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("subkey"))); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("s"))); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update)")); + } else if (word == "AsStruct") { + const bool isSubkey = line.find("subkey") != TString::npos; + UNIT_ASSERT(isSubkey); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("subkey"))); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(Quote("s"))); + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}, {TString("AsStruct"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("AsStruct"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["AsStruct"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["AsStruct"]); +} - Y_UNIT_TEST(UpdateOnValues) { - NYql::TAstParseResult res = SqlToYql("update plato.Input on (key, value) values (5, 'cool')", 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(UpdateOnValues) { + NYql::TAstParseResult res = SqlToYql("update plato.Input on (key, value) values (5, 'cool')", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update_on)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update_on)")); + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(UpdateOnSelect) { - NYql::TAstParseResult res = SqlToYql( - "update plato.Input on select key, value + 1 as value from plato.Input", 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(UpdateOnSelect) { + NYql::TAstParseResult res = SqlToYql( + "update plato.Input on select key, value + 1 as value from plato.Input", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update_on)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("('mode 'update_on)")); + } + }; - TWordCountHive elementStat = {{TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(UpdateOnBatch) { - NYql::TAstParseResult res = SqlToYql("batch update plato.Input on (key, value) values (5, 'cool')", 10, "kikimr"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:6: Error: BATCH UPDATE is unsupported with ON\n"); - } +Y_UNIT_TEST(UpdateOnBatch) { + NYql::TAstParseResult res = SqlToYql("batch update plato.Input on (key, value) values (5, 'cool')", 10, "kikimr"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:6: Error: BATCH UPDATE is unsupported with ON\n"); +} - // UNION +// UNION - Y_UNIT_TEST(UnionAllTest) { - NYql::TAstParseResult res = SqlToYql("PRAGMA DisableEmitUnionMerge; SELECT key FROM plato.Input UNION ALL select subkey FROM plato.Input;"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(UnionAllTest) { + NYql::TAstParseResult res = SqlToYql("PRAGMA DisableEmitUnionMerge; SELECT key FROM plato.Input UNION ALL select subkey FROM plato.Input;"); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("UnionAll"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["UnionAll"]); - } + TWordCountHive elementStat = {{TString("UnionAll"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["UnionAll"]); +} - Y_UNIT_TEST(UnionAllMergeTest) { - NYql::TAstParseResult res = SqlToYql("PRAGMA EmitUnionMerge; SELECT key FROM plato.Input UNION ALL select subkey FROM plato.Input;"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(UnionAllMergeTest) { + NYql::TAstParseResult res = SqlToYql("PRAGMA EmitUnionMerge; SELECT key FROM plato.Input UNION ALL select subkey FROM plato.Input;"); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("UnionMerge"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["UnionMerge"]); - } + TWordCountHive elementStat = {{TString("UnionMerge"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["UnionMerge"]); +} - Y_UNIT_TEST(UnionTest) { - NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input UNION select subkey FROM plato.Input;"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(UnionTest) { + NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input UNION select subkey FROM plato.Input;"); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("Union"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Union"]); - } + TWordCountHive elementStat = {{TString("Union"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Union"]); +} - Y_UNIT_TEST(UnionDistinctTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2025, 3); +Y_UNIT_TEST(UnionDistinctTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = NYql::MakeLangVersion(2025, 3); - NYql::TAstParseResult res = SqlToYqlWithSettings( - R"sql(SELECT key FROM plato.Input UNION DISTINCT SELECT subkey FROM plato.Input;)sql", - settings); + NYql::TAstParseResult res = SqlToYqlWithSettings( + R"sql(SELECT key FROM plato.Input UNION DISTINCT SELECT subkey FROM plato.Input;)sql", + settings); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("Union"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Union"]); - } + TWordCountHive elementStat = {{TString("Union"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Union"]); +} - Y_UNIT_TEST(LegacyNotNull2025_03) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2025, 3); +Y_UNIT_TEST(LegacyNotNull2025_03) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = NYql::MakeLangVersion(2025, 3); - NYql::TAstParseResult res = SqlToYqlWithSettings( - R"sql(SELECT 1 NOT NULL)sql", - settings); + NYql::TAstParseResult res = SqlToYqlWithSettings( + R"sql(SELECT 1 NOT NULL)sql", + settings); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - } + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); +} - Y_UNIT_TEST(LegacyNotNull2025_04) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2025, 4); +Y_UNIT_TEST(LegacyNotNull2025_04) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = NYql::MakeLangVersion(2025, 4); - NYql::TAstParseResult res = SqlToYqlWithSettings( - R"sql(SELECT 1 NOT NULL)sql", - settings); + NYql::TAstParseResult res = SqlToYqlWithSettings( + R"sql(SELECT 1 NOT NULL)sql", + settings); - UNIT_ASSERT(!res.Root); - } + UNIT_ASSERT(!res.Root); +} - Y_UNIT_TEST(UnionAggregationTest) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(UnionAggregationTest) { + NYql::TAstParseResult res = SqlToYql(R"( PRAGMA DisableEmitUnionMerge; SELECT 1 UNION ALL @@ -2059,16 +2028,16 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1; )"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("Union"), 0}, {TString("UnionAll"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["UnionAll"]); - UNIT_ASSERT_VALUES_EQUAL(3, elementStat["Union"]); - } + TWordCountHive elementStat = {{TString("Union"), 0}, {TString("UnionAll"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["UnionAll"]); + UNIT_ASSERT_VALUES_EQUAL(3, elementStat["Union"]); +} - Y_UNIT_TEST(UnionMergeAggregationTest) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(UnionMergeAggregationTest) { + NYql::TAstParseResult res = SqlToYql(R"( PRAGMA EmitUnionMerge; SELECT 1 UNION ALL @@ -2078,370 +2047,370 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1; )"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("Union"), 0}, {TString("UnionMerge"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["UnionMerge"]); - UNIT_ASSERT_VALUES_EQUAL(3, elementStat["Union"]); - } + TWordCountHive elementStat = {{TString("Union"), 0}, {TString("UnionMerge"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["UnionMerge"]); + UNIT_ASSERT_VALUES_EQUAL(3, elementStat["Union"]); +} - Y_UNIT_TEST(UnionAssumeOrderByWarning) { - { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(UnionAssumeOrderByWarning) { + { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; SELECT a FROM x ASSUME ORDER BY a; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), ""); - } - { - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), ""); + } + { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; SELECT a FROM x UNION ALL SELECT a FROM y ORDER BY a; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), ""); - } - { - NYql::TAstParseResult warn = SqlToYql(R"sql( + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_STRINGS_EQUAL(res.Issues.ToString(), ""); + } + { + NYql::TAstParseResult warn = SqlToYql(R"sql( USE plato; SELECT a FROM x UNION ALL SELECT a FROM y ASSUME ORDER BY a; )sql"); - UNIT_ASSERT_C(warn.Root, warn.Issues.ToString()); - UNIT_ASSERT_STRINGS_EQUAL( - warn.Issues.ToString(), - "<main>:6:33: Warning: ASSUME ORDER BY is used, " - "but UNION, INTERSECT and EXCEPT operators " - "have no ordering guarantees, " - "therefore consider using ORDER BY, code: 3\n"); - } + UNIT_ASSERT_C(warn.Root, warn.Issues.ToString()); + UNIT_ASSERT_STRINGS_EQUAL( + warn.Issues.ToString(), + "<main>:6:33: Warning: ASSUME ORDER BY is used, " + "but UNION, INTERSECT and EXCEPT operators " + "have no ordering guarantees, " + "therefore consider using ORDER BY, code: 3\n"); } +} - // INTERSECT +// INTERSECT - Y_UNIT_TEST(IntersectAllTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT ALL SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(IntersectAllTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; + NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT ALL SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("IntersectAll"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["IntersectAll"]); - } + TWordCountHive elementStat = {{TString("IntersectAll"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["IntersectAll"]); +} - Y_UNIT_TEST(IntersectTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(IntersectTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; + NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("Intersect"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Intersect"]); - } + TWordCountHive elementStat = {{TString("Intersect"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Intersect"]); +} - Y_UNIT_TEST(IntersectDistinctTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT DISTINCT SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(IntersectDistinctTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; + NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT DISTINCT SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("Intersect"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Intersect"]); - } + TWordCountHive elementStat = {{TString("Intersect"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Intersect"]); +} - Y_UNIT_TEST(IntersectAllPositionalTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("PRAGMA PositionalUnionAll; SELECT key FROM plato.Input INTERSECT ALL SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(IntersectAllPositionalTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; + NYql::TAstParseResult res = SqlToYqlWithSettings("PRAGMA PositionalUnionAll; SELECT key FROM plato.Input INTERSECT ALL SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("IntersectAllPositional"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["IntersectAllPositional"]); - } + TWordCountHive elementStat = {{TString("IntersectAllPositional"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["IntersectAllPositional"]); +} - Y_UNIT_TEST(IntersectDistinctPositionalTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("PRAGMA PositionalUnionAll; SELECT key FROM plato.Input INTERSECT DISTINCT SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(IntersectDistinctPositionalTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; + NYql::TAstParseResult res = SqlToYqlWithSettings("PRAGMA PositionalUnionAll; SELECT key FROM plato.Input INTERSECT DISTINCT SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("IntersectPositional"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["IntersectPositional"]); - } + TWordCountHive elementStat = {{TString("IntersectPositional"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["IntersectPositional"]); +} - Y_UNIT_TEST(MultipleIntersectTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; +Y_UNIT_TEST(MultipleIntersectTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT SELECT subkey FROM plato.Input INTERSECT SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); + NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT SELECT subkey FROM plato.Input INTERSECT SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("Intersect"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["Intersect"]); + TWordCountHive elementStat = {{TString("Intersect"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["Intersect"]); - res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT SELECT subkey FROM plato.Input INTERSECT ALL SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); + res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT SELECT subkey FROM plato.Input INTERSECT ALL SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - elementStat = {{TString("Intersect"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["Intersect"]); + elementStat = {{TString("Intersect"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["Intersect"]); - res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT SELECT subkey FROM plato.Input UNION SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); + res = SqlToYqlWithSettings("SELECT key FROM plato.Input INTERSECT SELECT subkey FROM plato.Input UNION SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - elementStat = {{TString("Intersect"), 0}, {TString("Union"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Intersect"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Union"]); - } + elementStat = {{TString("Intersect"), 0}, {TString("Union"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Intersect"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Union"]); +} - // EXCEPT +// EXCEPT - Y_UNIT_TEST(ExceptAllTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT ALL SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(ExceptAllTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; + NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT ALL SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("ExceptAll"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["ExceptAll"]); - } + TWordCountHive elementStat = {{TString("ExceptAll"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["ExceptAll"]); +} - Y_UNIT_TEST(ExceptTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(ExceptTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; + NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("Except"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Except"]); - } + TWordCountHive elementStat = {{TString("Except"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Except"]); +} - Y_UNIT_TEST(ExceptDistinctTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT DISTINCT SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(ExceptDistinctTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; + NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT DISTINCT SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("Except"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Except"]); - } + TWordCountHive elementStat = {{TString("Except"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Except"]); +} - Y_UNIT_TEST(ExceptAllPositionalTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("PRAGMA PositionalUnionAll; SELECT key FROM plato.Input EXCEPT ALL SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(ExceptAllPositionalTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; + NYql::TAstParseResult res = SqlToYqlWithSettings("PRAGMA PositionalUnionAll; SELECT key FROM plato.Input EXCEPT ALL SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("ExceptAllPositional"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["ExceptAllPositional"]); - } + TWordCountHive elementStat = {{TString("ExceptAllPositional"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["ExceptAllPositional"]); +} - Y_UNIT_TEST(ExceptDistinctPositionalTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("PRAGMA PositionalUnionAll; SELECT key FROM plato.Input EXCEPT DISTINCT SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(ExceptDistinctPositionalTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; + NYql::TAstParseResult res = SqlToYqlWithSettings("PRAGMA PositionalUnionAll; SELECT key FROM plato.Input EXCEPT DISTINCT SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("ExceptPositional"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["ExceptPositional"]); - } + TWordCountHive elementStat = {{TString("ExceptPositional"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["ExceptPositional"]); +} - Y_UNIT_TEST(MultipleExceptTest) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202503; +Y_UNIT_TEST(MultipleExceptTest) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202503; - NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT SELECT subkey FROM plato.Input EXCEPT SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); + NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT SELECT subkey FROM plato.Input EXCEPT SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("Except"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["Except"]); + TWordCountHive elementStat = {{TString("Except"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["Except"]); - res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT SELECT subkey FROM plato.Input EXCEPT ALL SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); + res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT SELECT subkey FROM plato.Input EXCEPT ALL SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - elementStat = {{TString("Except"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["Except"]); + elementStat = {{TString("Except"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["Except"]); - res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT SELECT subkey FROM plato.Input UNION SELECT subkey FROM plato.Input;", settings); - UNIT_ASSERT(res.Root); + res = SqlToYqlWithSettings("SELECT key FROM plato.Input EXCEPT SELECT subkey FROM plato.Input UNION SELECT subkey FROM plato.Input;", settings); + UNIT_ASSERT(res.Root); - elementStat = {{TString("Except"), 0}, {TString("Union"), 0}}; - VerifyProgram(res, elementStat, {}); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Except"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Union"]); - } + elementStat = {{TString("Except"), 0}, {TString("Union"), 0}}; + VerifyProgram(res, elementStat, {}); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Except"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Union"]); +} - Y_UNIT_TEST(DefaultYQL20367) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202502; +Y_UNIT_TEST(DefaultYQL20367) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202502; - NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT 1 EXCEPT SELECT 1;", settings); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - } + NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT 1 EXCEPT SELECT 1;", settings); + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); +} - Y_UNIT_TEST(DisabledYQL20367) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = 202502; - settings.Flags.emplace("DisableExceptIntersectBefore202503"); +Y_UNIT_TEST(DisabledYQL20367) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = 202502; + settings.Flags.emplace("DisableExceptIntersectBefore202503"); - NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT 1 EXCEPT SELECT 1;", settings); - UNIT_ASSERT_C(!res.IsOk(), res.Issues.ToString()); - } + NYql::TAstParseResult res = SqlToYqlWithSettings("SELECT 1 EXCEPT SELECT 1;", settings); + UNIT_ASSERT_C(!res.IsOk(), res.Issues.ToString()); +} - Y_UNIT_TEST(DeclareDecimalParameter) { - NYql::TAstParseResult res = SqlToYql("declare $value as Decimal(22,9); select $value as cnt;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(DeclareDecimalParameter) { + NYql::TAstParseResult res = SqlToYql("declare $value as Decimal(22,9); select $value as cnt;"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(SimpleGroupBy) { - NYql::TAstParseResult res = SqlToYql("select count(1),z from plato.Input group by key as z order by z;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(SimpleGroupBy) { + NYql::TAstParseResult res = SqlToYql("select count(1),z from plato.Input group by key as z order by z;"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(EmptyColumnName0) { - /// Now it's parsed well and error occur on validate step like "4:31:Empty struct member name is not allowed" in "4:31:Function: AddMember" - NYql::TAstParseResult res = SqlToYql("insert into plato.Output (``, list1) values (0, AsList(0, 1, 2));"); - /// Verify that parsed well without crash - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(EmptyColumnName0) { + /// Now it's parsed well and error occur on validate step like "4:31:Empty struct member name is not allowed" in "4:31:Function: AddMember" + NYql::TAstParseResult res = SqlToYql("insert into plato.Output (``, list1) values (0, AsList(0, 1, 2));"); + /// Verify that parsed well without crash + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(KikimrRollback) { - NYql::TAstParseResult res = SqlToYql("use plato; select * from Input; rollback;", 10, "kikimr"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(KikimrRollback) { + NYql::TAstParseResult res = SqlToYql("use plato; select * from Input; rollback;", 10, "kikimr"); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("rollback"), 0}}; - VerifyProgram(res, elementStat); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["rollback"]); - } + TWordCountHive elementStat = {{TString("rollback"), 0}}; + VerifyProgram(res, elementStat); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["rollback"]); +} - Y_UNIT_TEST(PragmaFile) { - NYql::TAstParseResult res = SqlToYql(R"(pragma file("HW", "sbr:181041334");)"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(PragmaFile) { + NYql::TAstParseResult res = SqlToYql(R"(pragma file("HW", "sbr:181041334");)"); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString(R"((let world (Configure! world (DataSource '"config") '"AddFileByUrl" '"HW" '"sbr:181041334")))"), 0}}; - VerifyProgram(res, elementStat); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat.cbegin()->second); - } + TWordCountHive elementStat = {{TString(R"((let world (Configure! world (DataSource '"config") '"AddFileByUrl" '"HW" '"sbr:181041334")))"), 0}}; + VerifyProgram(res, elementStat); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat.cbegin()->second); +} - Y_UNIT_TEST(DoNotCrashOnNamedInFilter) { - NYql::TAstParseResult res = SqlToYql("USE plato; $all = ($table_name) -> { return true; }; SELECT * FROM FILTER(Input, $all)"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(DoNotCrashOnNamedInFilter) { + NYql::TAstParseResult res = SqlToYql("USE plato; $all = ($table_name) -> { return true; }; SELECT * FROM FILTER(Input, $all)"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(PragmasFileAndUdfOrder) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(PragmasFileAndUdfOrder) { + NYql::TAstParseResult res = SqlToYql(R"( PRAGMA file("libvideoplayers_udf.so", "https://proxy.sandbox.yandex-team.ru/235185290"); PRAGMA udf("libvideoplayers_udf.so"); )"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - const auto programm = GetPrettyPrint(res); - const auto file = programm.find("AddFileByUrl"); - const auto udfs = programm.find("ImportUdfs"); - UNIT_ASSERT(file < udfs); - } + const auto programm = GetPrettyPrint(res); + const auto file = programm.find("AddFileByUrl"); + const auto udfs = programm.find("ImportUdfs"); + UNIT_ASSERT(file < udfs); +} - Y_UNIT_TEST(ProcessUserType) { - NYql::TAstParseResult res = SqlToYql("process plato.Input using Kikimr::PushData(TableRows());", 1, TString(NYql::KikimrProviderName)); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(ProcessUserType) { + NYql::TAstParseResult res = SqlToYql("process plato.Input using Kikimr::PushData(TableRows());", 1, TString(NYql::KikimrProviderName)); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Kikimr.PushData") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("TupleType")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("TypeOf")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Kikimr.PushData") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("TupleType")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("TypeOf")); + } + }; - TWordCountHive elementStat = {{TString("Kikimr.PushData"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Kikimr.PushData"]); - } + TWordCountHive elementStat = {{TString("Kikimr.PushData"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Kikimr.PushData"]); +} - Y_UNIT_TEST(ProcessUserTypeAuth) { - NYql::TAstParseResult res = SqlToYql("process plato.Input using YDB::PushData(TableRows(), AsTuple('oauth', SecureParam('api:oauth')));", 1, TString(NYql::KikimrProviderName)); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(ProcessUserTypeAuth) { + NYql::TAstParseResult res = SqlToYql("process plato.Input using YDB::PushData(TableRows(), AsTuple('oauth', SecureParam('api:oauth')));", 1, TString(NYql::KikimrProviderName)); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "YDB.PushData") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("TupleType")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("TypeOf")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("api:oauth")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "YDB.PushData") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("TupleType")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("TypeOf")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("api:oauth")); + } + }; - TWordCountHive elementStat = {{TString("YDB.PushData"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["YDB.PushData"]); - } + TWordCountHive elementStat = {{TString("YDB.PushData"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["YDB.PushData"]); +} - Y_UNIT_TEST(SelectStreamRtmr) { - NYql::TAstParseResult res = SqlToYql( - "USE plato; INSERT INTO Output SELECT STREAM key FROM Input;", - 10, TString(NYql::RtmrProviderName)); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(SelectStreamRtmr) { + NYql::TAstParseResult res = SqlToYql( + "USE plato; INSERT INTO Output SELECT STREAM key FROM Input;", + 10, TString(NYql::RtmrProviderName)); + UNIT_ASSERT(res.Root); - res = SqlToYql( - "USE plato; INSERT INTO Output SELECT key FROM Input;", - 10, TString(NYql::RtmrProviderName)); - UNIT_ASSERT(res.Root); - } + res = SqlToYql( + "USE plato; INSERT INTO Output SELECT key FROM Input;", + 10, TString(NYql::RtmrProviderName)); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(SelectStreamRtmrJoinWithYt) { - NYql::TAstParseResult res = SqlToYql( - "USE plato; INSERT INTO Output SELECT STREAM key FROM Input LEFT JOIN hahn.ttt as t ON Input.key = t.Name;", - 10, TString(NYql::RtmrProviderName)); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(SelectStreamRtmrJoinWithYt) { + NYql::TAstParseResult res = SqlToYql( + "USE plato; INSERT INTO Output SELECT STREAM key FROM Input LEFT JOIN hahn.ttt as t ON Input.key = t.Name;", + 10, TString(NYql::RtmrProviderName)); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(SelectStreamNonRtmr) { - NYql::TAstParseResult res = SqlToYql( - "USE plato; INSERT INTO Output SELECT STREAM key FROM Input;", - 10); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:31: Error: SELECT STREAM is unsupported for non-streaming sources\n"); - } +Y_UNIT_TEST(SelectStreamNonRtmr) { + NYql::TAstParseResult res = SqlToYql( + "USE plato; INSERT INTO Output SELECT STREAM key FROM Input;", + 10); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:31: Error: SELECT STREAM is unsupported for non-streaming sources\n"); +} - Y_UNIT_TEST(GroupByHopRtmr) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(GroupByHopRtmr) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; INSERT INTO Output SELECT key, SUM(value) AS value FROM Input GROUP BY key, HOP(subkey, "PT10S", "PT30S", "PT20S"); )", 10, TString(NYql::RtmrProviderName)); - UNIT_ASSERT(res.Root); - } + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(GroupByHopRtmrSubquery) { - // 'use plato' intentially avoided - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(GroupByHopRtmrSubquery) { + // 'use plato' intentially avoided + NYql::TAstParseResult res = SqlToYql(R"( SELECT COUNT(*) AS value FROM (SELECT * FROM plato.Input) GROUP BY HOP(Data, "PT10S", "PT30S", "PT20S") )", 10, TString(NYql::RtmrProviderName)); - UNIT_ASSERT(res.Root); - } + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(GroupByHopRtmrSubqueryBinding) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(GroupByHopRtmrSubqueryBinding) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; $q = SELECT * FROM Input; INSERT INTO Output SELECT STREAM * FROM ( @@ -2449,45 +2418,45 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { GROUP BY HOP(Data, "PT10S", "PT30S", "PT20S") ); )", 10, TString(NYql::RtmrProviderName)); - UNIT_ASSERT(res.Root); - } + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(GroupByNoHopRtmr) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(GroupByNoHopRtmr) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; INSERT INTO Output SELECT STREAM key, SUM(value) AS value FROM Input GROUP BY key; )", 10, TString(NYql::RtmrProviderName)); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:22: Error: Streaming group by query must have a hopping window specification.\n"); - } + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:22: Error: Streaming group by query must have a hopping window specification.\n"); +} - Y_UNIT_TEST(KikimrInserts) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(KikimrInserts) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; INSERT INTO Output SELECT key, value FROM Input; INSERT OR ABORT INTO Output SELECT key, value FROM Input; INSERT OR IGNORE INTO Output SELECT key, value FROM Input; INSERT OR REVERT INTO Output SELECT key, value FROM Input; )", 10, TString(NYql::KikimrProviderName)); - UNIT_ASSERT(res.Root); - } + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(InsertIntoNamedExpr) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(InsertIntoNamedExpr) { + NYql::TAstParseResult res = SqlToYql(R"sql( $target = "target"; INSERT INTO plato.$target (x) VALUES ((1)); )sql"); - UNIT_ASSERT(res.Root); - } + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(WarnMissingIsBeforeNotNull) { - NYql::TAstParseResult res = SqlToYql("select 1 NOT NULL"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Warning: Missing IS keyword before NOT NULL, code: 4507\n"); - } +Y_UNIT_TEST(WarnMissingIsBeforeNotNull) { + NYql::TAstParseResult res = SqlToYql("select 1 NOT NULL"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Warning: Missing IS keyword before NOT NULL, code: 4507\n"); +} - Y_UNIT_TEST(Subqueries) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(Subqueries) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; $sq1 = (SELECT * FROM plato.Input); @@ -2516,11 +2485,11 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { SELECT * FROM $squ2; SELECT * FROM $squ3; )"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(SubqueriesJoin) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(SubqueriesJoin) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; $left = SELECT * FROM plato.Input1 WHERE value != "BadValue"; @@ -2530,16 +2499,16 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { JOIN $right AS r ON l.key == r.key; )"); - UNIT_ASSERT(res.Root); - } + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(AnyInBackticksAsTableName) { - NYql::TAstParseResult res = SqlToYql("use plato; select * from `any`;"); - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(AnyInBackticksAsTableName) { + NYql::TAstParseResult res = SqlToYql("use plato; select * from `any`;"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(AnyJoinForTableAndSubQuery) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(AnyJoinForTableAndSubQuery) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; $r = SELECT * FROM plato.Input2; @@ -2549,24 +2518,24 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { USING (key); )"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "EquiJoin") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('left 'any)")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('right 'any)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "EquiJoin") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('left 'any)")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('right 'any)")); + } + }; - TWordCountHive elementStat = {{TString("left"), 0}, {TString("right"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("left"), 0}, {TString("right"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["left"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["right"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["left"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["right"]); +} - Y_UNIT_TEST(AnyJoinForTableAndTableSource) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(AnyJoinForTableAndTableSource) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; $r = AsList( @@ -2578,24 +2547,24 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { USING (key); )"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "EquiJoin") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('left 'any)")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('right 'any)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "EquiJoin") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('left 'any)")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('right 'any)")); + } + }; - TWordCountHive elementStat = {{TString("left"), 0}, {TString("right"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("left"), 0}, {TString("right"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["left"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["right"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["left"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["right"]); +} - Y_UNIT_TEST(AnyJoinNested) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(AnyJoinNested) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; FROM ANY Input1 as a @@ -2606,435 +2575,429 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { SELECT *; )"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("left"), 0}, {TString("right"), 0}}; - VerifyProgram(res, elementStat); + TWordCountHive elementStat = {{TString("left"), 0}, {TString("right"), 0}}; + VerifyProgram(res, elementStat); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["left"]); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["right"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["left"]); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["right"]); +} - Y_UNIT_TEST(InlineAction) { - NYql::TAstParseResult res = SqlToYql( - "do begin\n" - " select 1\n" - "; end do\n"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), ""); - } +Y_UNIT_TEST(InlineAction) { + NYql::TAstParseResult res = SqlToYql( + "do begin\n" + " select 1\n" + "; end do\n"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), ""); +} - Y_UNIT_TEST(FlattenByCorrelationName) { - UNIT_ASSERT(SqlToYql("select * from plato.Input as t flatten by t.x").IsOk()); - UNIT_ASSERT(SqlToYql("select * from plato.Input as t flatten by t -- same as flatten by t.t").IsOk()); - } +Y_UNIT_TEST(FlattenByCorrelationName) { + UNIT_ASSERT(SqlToYql("select * from plato.Input as t flatten by t.x").IsOk()); + UNIT_ASSERT(SqlToYql("select * from plato.Input as t flatten by t -- same as flatten by t.t").IsOk()); +} - Y_UNIT_TEST(DiscoveryMode) { - UNIT_ASSERT(SqlToYqlWithMode("insert into plato.Output select * from plato.Input", NSQLTranslation::ESqlMode::DISCOVERY).IsOk()); - UNIT_ASSERT(SqlToYqlWithMode("select * from plato.concat(Input1, Input2)", NSQLTranslation::ESqlMode::DISCOVERY).IsOk()); - UNIT_ASSERT(SqlToYqlWithMode("select * from plato.each(AsList(\"Input1\", \"Input2\"))", NSQLTranslation::ESqlMode::DISCOVERY).IsOk()); - } +Y_UNIT_TEST(DiscoveryMode) { + UNIT_ASSERT(SqlToYqlWithMode("insert into plato.Output select * from plato.Input", NSQLTranslation::ESqlMode::DISCOVERY).IsOk()); + UNIT_ASSERT(SqlToYqlWithMode("select * from plato.concat(Input1, Input2)", NSQLTranslation::ESqlMode::DISCOVERY).IsOk()); + UNIT_ASSERT(SqlToYqlWithMode("select * from plato.each(AsList(\"Input1\", \"Input2\"))", NSQLTranslation::ESqlMode::DISCOVERY).IsOk()); +} - Y_UNIT_TEST(CubeWithAutoGeneratedLikeColumnName) { - UNIT_ASSERT(SqlToYql("select key,subkey,group from plato.Input group by cube(key,subkey,group)").IsOk()); - } +Y_UNIT_TEST(CubeWithAutoGeneratedLikeColumnName) { + UNIT_ASSERT(SqlToYql("select key,subkey,group from plato.Input group by cube(key,subkey,group)").IsOk()); +} - Y_UNIT_TEST(CubeWithAutoGeneratedLikeAlias) { - UNIT_ASSERT(SqlToYql("select key,subkey,group from plato.Input group by cube(key,subkey,value as group)").IsOk()); - } +Y_UNIT_TEST(CubeWithAutoGeneratedLikeAlias) { + UNIT_ASSERT(SqlToYql("select key,subkey,group from plato.Input group by cube(key,subkey,value as group)").IsOk()); +} - Y_UNIT_TEST(FilterCanBeUsedAsColumnIdOrBind) { - UNIT_ASSERT(SqlToYql("select filter from plato.Input").IsOk()); - UNIT_ASSERT(SqlToYql("select 1 as filter").IsOk()); - UNIT_ASSERT(SqlToYql("$filter = 1; select $filter").IsOk()); - } +Y_UNIT_TEST(FilterCanBeUsedAsColumnIdOrBind) { + UNIT_ASSERT(SqlToYql("select filter from plato.Input").IsOk()); + UNIT_ASSERT(SqlToYql("select 1 as filter").IsOk()); + UNIT_ASSERT(SqlToYql("$filter = 1; select $filter").IsOk()); +} - Y_UNIT_TEST(DuplicateSemicolonsAreAllowedBetweenTopLevelStatements) { - UNIT_ASSERT(SqlToYql(";;select 1; ; select 2;/*comment*/;select 3;;--comment\n;select 4;;").IsOk()); - } +Y_UNIT_TEST(DuplicateSemicolonsAreAllowedBetweenTopLevelStatements) { + UNIT_ASSERT(SqlToYql(";;select 1; ; select 2;/*comment*/;select 3;;--comment\n;select 4;;").IsOk()); +} - Y_UNIT_TEST(DuplicateAndMissingTrailingSemicolonsAreAllowedBetweenActionStatements) { - TString req = - "define action $action($b,$c) as\n" - " ;;$d = $b + $c;\n" - " select $b;\n" - " select $c;;\n" - " select $d,\n" - "end define;\n" - "\n" - "do $action(1,2);"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(DuplicateAndMissingTrailingSemicolonsAreAllowedBetweenActionStatements) { + TString req = + "define action $action($b,$c) as\n" + " ;;$d = $b + $c;\n" + " select $b;\n" + " select $c;;\n" + " select $d,\n" + "end define;\n" + "\n" + "do $action(1,2);"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(DuplicateAndMissingTrailingSemicolonsAreAllowedBetweenInlineActionStatements) { - TString req = - "do begin\n" - " ;select 1,\n" - "end do;\n" - "evaluate for $i in AsList(1,2,3) do begin\n" - " select $i;;\n" - " select $i + $i;;\n" - "end do;"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(DuplicateAndMissingTrailingSemicolonsAreAllowedBetweenInlineActionStatements) { + TString req = + "do begin\n" + " ;select 1,\n" + "end do;\n" + "evaluate for $i in AsList(1,2,3) do begin\n" + " select $i;;\n" + " select $i + $i;;\n" + "end do;"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(DuplicateSemicolonsAreAllowedBetweenLambdaStatements) { - TString req = - "$x=1;\n" - "$foo = ($a, $b)->{\n" - " ;;$v = $a + $b;\n" - " $bar = ($c) -> {; return $c << $x};;\n" - " return $bar($v);;\n" - "};\n" - "select $foo(1,2);"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(DuplicateSemicolonsAreAllowedBetweenLambdaStatements) { + TString req = + "$x=1;\n" + "$foo = ($a, $b)->{\n" + " ;;$v = $a + $b;\n" + " $bar = ($c) -> {; return $c << $x};;\n" + " return $bar($v);;\n" + "};\n" + "select $foo(1,2);"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(StringLiteralWithEscapedBackslash) { - NYql::TAstParseResult res1 = SqlToYql(R"foo(SELECT 'a\\';)foo"); - NYql::TAstParseResult res2 = SqlToYql(R"foo(SELECT "a\\";)foo"); - UNIT_ASSERT(res1.Root); - UNIT_ASSERT(res2.Root); +Y_UNIT_TEST(StringLiteralWithEscapedBackslash) { + NYql::TAstParseResult res1 = SqlToYql(R"foo(SELECT 'a\\';)foo"); + NYql::TAstParseResult res2 = SqlToYql(R"foo(SELECT "a\\";)foo"); + UNIT_ASSERT(res1.Root); + UNIT_ASSERT(res2.Root); - TWordCountHive elementStat = {{TString("a\\"), 0}}; + TWordCountHive elementStat = {{TString("a\\"), 0}}; - VerifyProgram(res1, elementStat); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["a\\"]); + VerifyProgram(res1, elementStat); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["a\\"]); - VerifyProgram(res2, elementStat); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["a\\"]); - } + VerifyProgram(res2, elementStat); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["a\\"]); +} - Y_UNIT_TEST(StringMultiLineLiteralWithEscapes) { - UNIT_ASSERT(SqlToYql("SELECT @@@foo@@@@bar@@@").IsOk()); - UNIT_ASSERT(SqlToYql("SELECT @@@@@@@@@").IsOk()); - } +Y_UNIT_TEST(StringMultiLineLiteralWithEscapes) { + UNIT_ASSERT(SqlToYql("SELECT @@@foo@@@@bar@@@").IsOk()); + UNIT_ASSERT(SqlToYql("SELECT @@@@@@@@@").IsOk()); +} - Y_UNIT_TEST(StringMultiLineLiteralConsequitiveAt) { - UNIT_ASSERT(!SqlToYql("SELECT @").IsOk()); - UNIT_ASSERT(!SqlToYql("SELECT @@").IsOk()); - UNIT_ASSERT(!SqlToYql("SELECT @@@").IsOk()); - UNIT_ASSERT( SqlToYql("SELECT @@@@").IsOk()); - UNIT_ASSERT( SqlToYql("SELECT @@@@@").IsOk()); +Y_UNIT_TEST(StringMultiLineLiteralConsequitiveAt) { + UNIT_ASSERT(!SqlToYql("SELECT @").IsOk()); + UNIT_ASSERT(!SqlToYql("SELECT @@").IsOk()); + UNIT_ASSERT(!SqlToYql("SELECT @@@").IsOk()); + UNIT_ASSERT(SqlToYql("SELECT @@@@").IsOk()); + UNIT_ASSERT(SqlToYql("SELECT @@@@@").IsOk()); - UNIT_ASSERT(!SqlToYql("SELECT @@@@@@").IsOk()); - UNIT_ASSERT(!SqlToYql("SELECT @@@@@@@").IsOk()); + UNIT_ASSERT(!SqlToYql("SELECT @@@@@@").IsOk()); + UNIT_ASSERT(!SqlToYql("SELECT @@@@@@@").IsOk()); - UNIT_ASSERT( SqlToYql("SELECT @@@@@@@@").IsOk()); - UNIT_ASSERT( SqlToYql("SELECT @@@@@@@@@").IsOk()); - UNIT_ASSERT(!SqlToYql("SELECT @@@@@@@@@@").IsOk()); - } + UNIT_ASSERT(SqlToYql("SELECT @@@@@@@@").IsOk()); + UNIT_ASSERT(SqlToYql("SELECT @@@@@@@@@").IsOk()); + UNIT_ASSERT(!SqlToYql("SELECT @@@@@@@@@@").IsOk()); +} - Y_UNIT_TEST(ConstnessForListDictSetCreate) { - auto req = "$foo = ($x, $y) -> (\"aaaa\");\n" - "\n" - "select\n" - " $foo(sum(key), ListCreate(String)),\n" - " $foo(sum(key), DictCreate(String, String)),\n" - " $foo(sum(key), SetCreate(String)),\n" - "from (select 1 as key);"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(ConstnessForListDictSetCreate) { + auto req = "$foo = ($x, $y) -> (\"aaaa\");\n" + "\n" + "select\n" + " $foo(sum(key), ListCreate(String)),\n" + " $foo(sum(key), DictCreate(String, String)),\n" + " $foo(sum(key), SetCreate(String)),\n" + "from (select 1 as key);"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(CanUseEmptyTupleInWindowPartitionBy) { - auto req = "select sum(key) over w\n" - "from plato.Input\n" - "window w as (partition compact by (), (subkey), (), value || value as dvalue);"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(CanUseEmptyTupleInWindowPartitionBy) { + auto req = "select sum(key) over w\n" + "from plato.Input\n" + "window w as (partition compact by (), (subkey), (), value || value as dvalue);"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(DenyAnsiOrderByLimitLegacyMode) { - auto req = "pragma DisableAnsiOrderByLimitInUnionAll;\n" - "use plato;\n" - "\n" - "select * from Input order by key limit 10\n" - "union all\n" - "select * from Input order by key limit 1;"; +Y_UNIT_TEST(DenyAnsiOrderByLimitLegacyMode) { + auto req = "pragma DisableAnsiOrderByLimitInUnionAll;\n" + "use plato;\n" + "\n" + "select * from Input order by key limit 10\n" + "union all\n" + "select * from Input order by key limit 1;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: DisableAnsiOrderByLimitInUnionAll pragma is deprecated and no longer supported\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: DisableAnsiOrderByLimitInUnionAll pragma is deprecated and no longer supported\n"); +} - Y_UNIT_TEST(ReduceUsingUdfWithShortcutsWorks) { - auto req = "use plato;\n" - "\n" - "$arg = 'foo';\n" - "$func = XXX::YYY($arg);\n" - "\n" - "REDUCE Input ON key using $func(subkey);\n" - "REDUCE Input ON key using $func(UUU::VVV(TableRow()));\n"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - req = "use plato;\n" - "\n" - "$arg = 'foo';\n" - "$func = XXX::YYY($arg);\n" - "\n" - "REDUCE Input ON key using all $func(subkey);\n" - "REDUCE Input ON key using all $func(UUU::VVV(TableRow()));"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(ReduceUsingUdfWithShortcutsWorks) { + auto req = "use plato;\n" + "\n" + "$arg = 'foo';\n" + "$func = XXX::YYY($arg);\n" + "\n" + "REDUCE Input ON key using $func(subkey);\n" + "REDUCE Input ON key using $func(UUU::VVV(TableRow()));\n"; + UNIT_ASSERT(SqlToYql(req).IsOk()); + req = "use plato;\n" + "\n" + "$arg = 'foo';\n" + "$func = XXX::YYY($arg);\n" + "\n" + "REDUCE Input ON key using all $func(subkey);\n" + "REDUCE Input ON key using all $func(UUU::VVV(TableRow()));"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(YsonDisableStrict) { - UNIT_ASSERT(SqlToYql("pragma yson.DisableStrict = \"false\";").IsOk()); - UNIT_ASSERT(SqlToYql("pragma yson.DisableStrict;").IsOk()); - } +Y_UNIT_TEST(YsonDisableStrict) { + UNIT_ASSERT(SqlToYql("pragma yson.DisableStrict = \"false\";").IsOk()); + UNIT_ASSERT(SqlToYql("pragma yson.DisableStrict;").IsOk()); +} - Y_UNIT_TEST(YsonStrict) { - UNIT_ASSERT(SqlToYql("pragma yson.Strict = \"false\";").IsOk()); - UNIT_ASSERT(SqlToYql("pragma yson.Strict;").IsOk()); - } +Y_UNIT_TEST(YsonStrict) { + UNIT_ASSERT(SqlToYql("pragma yson.Strict = \"false\";").IsOk()); + UNIT_ASSERT(SqlToYql("pragma yson.Strict;").IsOk()); +} - Y_UNIT_TEST(JoinByTuple) { - auto req = "use plato;\n" - "\n" - "select * from T1 as a\n" - "join T2 as b\n" - "on AsTuple(a.key, a.subkey) = AsTuple(b.key, b.subkey);"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(JoinByTuple) { + auto req = "use plato;\n" + "\n" + "select * from T1 as a\n" + "join T2 as b\n" + "on AsTuple(a.key, a.subkey) = AsTuple(b.key, b.subkey);"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(JoinByStruct) { - auto req = "use plato;\n" - "\n" - "select * from T1 as a\n" - "join T2 as b\n" - "on AsStruct(a.key as k, a.subkey as sk) = AsStruct(b.key as k, b.subkey as sk);"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(JoinByStruct) { + auto req = "use plato;\n" + "\n" + "select * from T1 as a\n" + "join T2 as b\n" + "on AsStruct(a.key as k, a.subkey as sk) = AsStruct(b.key as k, b.subkey as sk);"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(JoinByUdf) { - auto req = "use plato;\n" - "\n" - "select a.align\n" - "from T1 as a\n" - "join T2 as b\n" - "on Yson::SerializeJsonEncodeUtf8(a.align)=b.align;"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(JoinByUdf) { + auto req = "use plato;\n" + "\n" + "select a.align\n" + "from T1 as a\n" + "join T2 as b\n" + "on Yson::SerializeJsonEncodeUtf8(a.align)=b.align;"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(EscapedIdentifierAsLambdaArg) { - auto req = "$f = ($`foo bar`, $x) -> { return $`foo bar` + $x; };\n" - "\n" - "select $f(1, 2);"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - const auto programm = GetPrettyPrint(res); - auto expected = "(lambda '(\"$foo bar\" \"$x\")"; - UNIT_ASSERT(programm.find(expected) != TString::npos); - } +Y_UNIT_TEST(EscapedIdentifierAsLambdaArg) { + auto req = "$f = ($`foo bar`, $x) -> { return $`foo bar` + $x; };\n" + "\n" + "select $f(1, 2);"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + const auto programm = GetPrettyPrint(res); + auto expected = "(lambda '(\"$foo bar\" \"$x\")"; + UNIT_ASSERT(programm.find(expected) != TString::npos); +} - Y_UNIT_TEST(UdfSyntaxSugarOnlyCallable) { - auto req = "SELECT Udf(DateTime::FromString)('2022-01-01');"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - const auto programm = GetPrettyPrint(res); - auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType))"; - UNIT_ASSERT(programm.find(expected) != TString::npos); - } +Y_UNIT_TEST(UdfSyntaxSugarOnlyCallable) { + auto req = "SELECT Udf(DateTime::FromString)('2022-01-01');"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + const auto programm = GetPrettyPrint(res); + auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType))"; + UNIT_ASSERT(programm.find(expected) != TString::npos); +} - Y_UNIT_TEST(UdfSyntaxSugarTypeNoRun) { - auto req = "SELECT Udf(DateTime::FromString, String, Tuple<Int32, Float>, 'foo' as TypeConfig)('2022-01-01');"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - const auto programm = GetPrettyPrint(res); - auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (DataType 'String) (TupleType (DataType 'Int32) (DataType 'Float))) '\"foo\")"; - UNIT_ASSERT(programm.find(expected) != TString::npos); - } +Y_UNIT_TEST(UdfSyntaxSugarTypeNoRun) { + auto req = "SELECT Udf(DateTime::FromString, String, Tuple<Int32, Float>, 'foo' as TypeConfig)('2022-01-01');"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + const auto programm = GetPrettyPrint(res); + auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (DataType 'String) (TupleType (DataType 'Int32) (DataType 'Float))) '\"foo\")"; + UNIT_ASSERT(programm.find(expected) != TString::npos); +} - Y_UNIT_TEST(UdfSyntaxSugarRunNoType) { - auto req = "SELECT Udf(DateTime::FromString, String, Tuple<Int32, Float>, Void() as RunConfig)('2022-01-01');"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - const auto programm = GetPrettyPrint(res); - auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (DataType 'String) (TupleType (DataType 'Int32) (DataType 'Float))) '\"\" (Void))"; - UNIT_ASSERT(programm.find(expected) != TString::npos); - } +Y_UNIT_TEST(UdfSyntaxSugarRunNoType) { + auto req = "SELECT Udf(DateTime::FromString, String, Tuple<Int32, Float>, Void() as RunConfig)('2022-01-01');"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + const auto programm = GetPrettyPrint(res); + auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (DataType 'String) (TupleType (DataType 'Int32) (DataType 'Float))) '\"\" (Void))"; + UNIT_ASSERT(programm.find(expected) != TString::npos); +} - Y_UNIT_TEST(UdfSyntaxSugarFullTest) { - auto req = "SELECT Udf(DateTime::FromString, String, Tuple<Int32, Float>, 'foo' as TypeConfig, Void() As RunConfig)('2022-01-01');"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - const auto programm = GetPrettyPrint(res); - auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (DataType 'String) (TupleType (DataType 'Int32) (DataType 'Float))) '\"foo\" (Void))"; - UNIT_ASSERT(programm.find(expected) != TString::npos); - } +Y_UNIT_TEST(UdfSyntaxSugarFullTest) { + auto req = "SELECT Udf(DateTime::FromString, String, Tuple<Int32, Float>, 'foo' as TypeConfig, Void() As RunConfig)('2022-01-01');"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + const auto programm = GetPrettyPrint(res); + auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (DataType 'String) (TupleType (DataType 'Int32) (DataType 'Float))) '\"foo\" (Void))"; + UNIT_ASSERT(programm.find(expected) != TString::npos); +} - Y_UNIT_TEST(UdfSyntaxSugarOtherRunConfigs) { - auto req = "SELECT Udf(DateTime::FromString, String, Tuple<Int32, Float>, 'foo' as TypeConfig, '55' As RunConfig)('2022-01-01');"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - const auto programm = GetPrettyPrint(res); - auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (DataType 'String) (TupleType (DataType 'Int32) (DataType 'Float))) '\"foo\" (String '\"55\"))"; - UNIT_ASSERT(programm.find(expected) != TString::npos); - } +Y_UNIT_TEST(UdfSyntaxSugarOtherRunConfigs) { + auto req = "SELECT Udf(DateTime::FromString, String, Tuple<Int32, Float>, 'foo' as TypeConfig, '55' As RunConfig)('2022-01-01');"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + const auto programm = GetPrettyPrint(res); + auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (DataType 'String) (TupleType (DataType 'Int32) (DataType 'Float))) '\"foo\" (String '\"55\"))"; + UNIT_ASSERT(programm.find(expected) != TString::npos); +} - Y_UNIT_TEST(UdfSyntaxSugarOtherRunConfigs2) { - auto req = "SELECT Udf(DateTime::FromString, String, Tuple<Int32, Float>, 'foo' as TypeConfig, AsTuple(32, 'no', AsStruct(1e-9 As SomeFloat)) As RunConfig)('2022-01-01');"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - const auto programm = GetPrettyPrint(res); - auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (DataType 'String) (TupleType (DataType 'Int32) (DataType 'Float))) '\"foo\" '((Int32 '\"32\") (String '\"no\") (AsStruct '('\"SomeFloat\" (Double '\"1e-9\")))))"; - UNIT_ASSERT(programm.find(expected) != TString::npos); - } +Y_UNIT_TEST(UdfSyntaxSugarOtherRunConfigs2) { + auto req = "SELECT Udf(DateTime::FromString, String, Tuple<Int32, Float>, 'foo' as TypeConfig, AsTuple(32, 'no', AsStruct(1e-9 As SomeFloat)) As RunConfig)('2022-01-01');"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + const auto programm = GetPrettyPrint(res); + auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (DataType 'String) (TupleType (DataType 'Int32) (DataType 'Float))) '\"foo\" '((Int32 '\"32\") (String '\"no\") (AsStruct '('\"SomeFloat\" (Double '\"1e-9\")))))"; + UNIT_ASSERT(programm.find(expected) != TString::npos); +} - Y_UNIT_TEST(UdfSyntaxSugarOptional) { - auto req = "SELECT Udf(DateTime::FromString, String?, Int32??, Tuple<Int32, Float>, \"foo\" as TypeConfig, Void() As RunConfig)(\"2022-01-01\");"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - const auto programm = GetPrettyPrint(res); - auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (OptionalType (DataType 'String)) (OptionalType (OptionalType (DataType 'Int32))) (TupleType (DataType 'Int32) (DataType 'Float))) '\"foo\" (Void))"; - UNIT_ASSERT(programm.find(expected) != TString::npos); - } +Y_UNIT_TEST(UdfSyntaxSugarOptional) { + auto req = "SELECT Udf(DateTime::FromString, String?, Int32??, Tuple<Int32, Float>, \"foo\" as TypeConfig, Void() As RunConfig)(\"2022-01-01\");"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + const auto programm = GetPrettyPrint(res); + auto expected = "(SqlCall '\"DateTime.FromString\" '((PositionalArgs (String '\"2022-01-01\")) (AsStruct)) (TupleType (OptionalType (DataType 'String)) (OptionalType (OptionalType (DataType 'Int32))) (TupleType (DataType 'Int32) (DataType 'Float))) '\"foo\" (Void))"; + UNIT_ASSERT(programm.find(expected) != TString::npos); +} - Y_UNIT_TEST(CompactionPolicyParseCorrect) { - NYql::TAstParseResult res = SqlToYql( - R"( USE plato; +Y_UNIT_TEST(CompactionPolicyParseCorrect) { + NYql::TAstParseResult res = SqlToYql( + R"( USE plato; CREATE TABLE tableName (Key Uint32, Value String, PRIMARY KEY (Key)) - WITH ( COMPACTION_POLICY = "SomeCompactionPreset" );)" - ); - UNIT_ASSERT(res.Root); + WITH ( COMPACTION_POLICY = "SomeCompactionPreset" );)"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("compactionPolicy")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("SomeCompactionPreset")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("compactionPolicy")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("SomeCompactionPreset")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(AutoPartitioningBySizeParseCorrect) { - NYql::TAstParseResult res = SqlToYql( - R"( USE plato; +Y_UNIT_TEST(AutoPartitioningBySizeParseCorrect) { + NYql::TAstParseResult res = SqlToYql( + R"( USE plato; CREATE TABLE tableName (Key Uint32, Value String, PRIMARY KEY (Key)) - WITH ( AUTO_PARTITIONING_BY_SIZE = ENABLED );)" - ); - UNIT_ASSERT(res.Root); + WITH ( AUTO_PARTITIONING_BY_SIZE = ENABLED );)"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("autoPartitioningBySize")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("ENABLED")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("autoPartitioningBySize")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("ENABLED")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(UniformPartitionsParseCorrect) { - NYql::TAstParseResult res = SqlToYql( - R"( USE plato; +Y_UNIT_TEST(UniformPartitionsParseCorrect) { + NYql::TAstParseResult res = SqlToYql( + R"( USE plato; CREATE TABLE tableName (Key Uint32, Value String, PRIMARY KEY (Key)) - WITH ( UNIFORM_PARTITIONS = 16 );)" - ); - UNIT_ASSERT(res.Root); + WITH ( UNIFORM_PARTITIONS = 16 );)"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("uniformPartitions")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("16")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("uniformPartitions")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("16")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DateTimeTtlParseCorrect) { - NYql::TAstParseResult res = SqlToYql( - R"( USE plato; +Y_UNIT_TEST(DateTimeTtlParseCorrect) { + NYql::TAstParseResult res = SqlToYql( + R"( USE plato; CREATE TABLE tableName (Key Uint32, CreatedAt Timestamp, PRIMARY KEY (Key)) - WITH (TTL = Interval("P1D") On CreatedAt);)" - ); - UNIT_ASSERT(res.Root); + WITH (TTL = Interval("P1D") On CreatedAt);)"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("setTtlSettings")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tiers")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("evictionDelay")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("86400000")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("setTtlSettings")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tiers")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("evictionDelay")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("86400000")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(IntTtlParseCorrect) { - NYql::TAstParseResult res = SqlToYql( - R"( USE plato; +Y_UNIT_TEST(IntTtlParseCorrect) { + NYql::TAstParseResult res = SqlToYql( + R"( USE plato; CREATE TABLE tableName (Key Uint32, CreatedAt Uint32, PRIMARY KEY (Key)) - WITH (TTL = Interval("P1D") On CreatedAt AS SECONDS);)" - ); - UNIT_ASSERT(res.Root); + WITH (TTL = Interval("P1D") On CreatedAt AS SECONDS);)"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("setTtlSettings")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tiers")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("evictionDelay")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("86400000")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("columnUnit")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("seconds")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("setTtlSettings")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tiers")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("evictionDelay")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("86400000")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("columnUnit")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("seconds")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(TtlTieringParseCorrect) { - NYql::TAstParseResult res = SqlToYql( - R"( USE plato; +Y_UNIT_TEST(TtlTieringParseCorrect) { + NYql::TAstParseResult res = SqlToYql( + R"( USE plato; CREATE TABLE tableName (Key Uint32, CreatedAt Uint32, PRIMARY KEY (Key)) WITH (TTL = Interval("P1D") TO EXTERNAL DATA SOURCE Tier1, Interval("P2D") TO EXTERNAL DATA SOURCE Tier2, Interval("P30D") DELETE - ON CreatedAt AS SECONDS);)" - ); - UNIT_ASSERT(res.Root); + ON CreatedAt AS SECONDS);)"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("setTtlSettings")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tiers")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("evictionDelay")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("storageName")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Tier1")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Tier2")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("86400000")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("172800000")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("2592000000")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("columnUnit")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("seconds")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("setTtlSettings")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tiers")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("evictionDelay")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("storageName")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Tier1")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Tier2")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("86400000")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("172800000")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("2592000000")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("columnUnit")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("seconds")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(TtlTieringWithOtherActionsParseCorrect) { - NYql::TAstParseResult res = SqlToYql( - R"( USE plato; +Y_UNIT_TEST(TtlTieringWithOtherActionsParseCorrect) { + NYql::TAstParseResult res = SqlToYql( + R"( USE plato; ALTER TABLE tableName ADD FAMILY cold (DATA = "rot"), SET TTL @@ -3044,99 +3007,95 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ON CreatedAt, ALTER COLUMN payload_v2 SET FAMILY cold, ALTER FAMILY default SET DATA "ssd" - ;)" - ); - UNIT_ASSERT(res.Root); + ;)"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("addColumnFamilies")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("cold")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alterColumnFamilies")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("default")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("setTtlSettings")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tiers")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("evictionDelay")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("storageName")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Tier1")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Tier2")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("86400000")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("172800000")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("2592000000")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("addColumnFamilies")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("cold")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alterColumnFamilies")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("default")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("setTtlSettings")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tiers")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("evictionDelay")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("storageName")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Tier1")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Tier2")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("86400000")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("172800000")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("2592000000")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(TieringParseCorrect) { - NYql::TAstParseResult res = SqlToYql( - R"( USE plato; +Y_UNIT_TEST(TieringParseCorrect) { + NYql::TAstParseResult res = SqlToYql( + R"( USE plato; CREATE TABLE tableName (Key Uint32, Value String, PRIMARY KEY (Key)) - WITH ( TIERING = 'my_tiering' );)" - ); - UNIT_ASSERT(res.Root); + WITH ( TIERING = 'my_tiering' );)"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tiering")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("my_tiering")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tiering")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("my_tiering")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(StoreExternalBlobsParseCorrect) { - NYql::TAstParseResult res = SqlToYql( - R"( USE plato; +Y_UNIT_TEST(StoreExternalBlobsParseCorrect) { + NYql::TAstParseResult res = SqlToYql( + R"( USE plato; CREATE TABLE tableName (Key Uint32, Value String, PRIMARY KEY (Key)) - WITH ( STORE_EXTERNAL_BLOBS = ENABLED );)" - ); - UNIT_ASSERT(res.Root); + WITH ( STORE_EXTERNAL_BLOBS = ENABLED );)"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("storeExternalBlobs")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("ENABLED")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("storeExternalBlobs")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("ENABLED")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(ExternalDataChannelsCountParseCorrect) { - NYql::TAstParseResult res = SqlToYql( - R"( USE plato; +Y_UNIT_TEST(ExternalDataChannelsCountParseCorrect) { + NYql::TAstParseResult res = SqlToYql( + R"( USE plato; CREATE TABLE tableName (Key Uint32, Value String, PRIMARY KEY (Key)) - WITH ( EXTERNAL_DATA_CHANNELS_COUNT = 7 );)" - ); - UNIT_ASSERT(res.Root); + WITH ( EXTERNAL_DATA_CHANNELS_COUNT = 7 );)"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("externalDataChannelsCount")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("7")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("externalDataChannelsCount")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("7")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DefaultValueColumn2) { - auto res = SqlToYql(R"( use plato; +Y_UNIT_TEST(DefaultValueColumn2) { + auto res = SqlToYql(R"( use plato; $lambda = () -> { RETURN CAST(RandomUuid(2) as String) }; @@ -3148,28 +3107,28 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )"); - UNIT_ASSERT_C(res.Root, Err2Str(res)); + UNIT_ASSERT_C(res.Root, Err2Str(res)); - const auto program = GetPrettyPrint(res); + const auto program = GetPrettyPrint(res); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, program.find("RandomNumber")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, program.find("RandomUuid")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, program.find("columnConstrains")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, program.find("columnConstrains")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, program.find("Write")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, program.find("RandomNumber")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, program.find("RandomUuid")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, program.find("columnConstrains")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, program.find("columnConstrains")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, program.find("Write")); #if 0 Cerr << program << Endl; #endif - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DefaultValueColumn3) { - auto res = SqlToYql(R"( use plato; +Y_UNIT_TEST(DefaultValueColumn3) { + auto res = SqlToYql(R"( use plato; CREATE TABLE tableName ( database_id Utf8, @@ -3179,12 +3138,12 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )"); - UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), "<main>:6:40: Error: Column reference \"database_id\" is not allowed in current scope\n"); - UNIT_ASSERT(!res.Root); - } + UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), "<main>:6:40: Error: Column reference \"database_id\" is not allowed in current scope\n"); + UNIT_ASSERT(!res.Root); +} - Y_UNIT_TEST(DefaultValueColumn) { - auto res = SqlToYql(R"( use plato; +Y_UNIT_TEST(DefaultValueColumn) { + auto res = SqlToYql(R"( use plato; CREATE TABLE tableName ( Key Uint32 FAMILY cold DEFAULT 5, Value String FAMILY default DEFAULT "empty", @@ -3200,29 +3159,29 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )"); - UNIT_ASSERT_C(res.Root, Err2Str(res)); + UNIT_ASSERT_C(res.Root, Err2Str(res)); #if 0 const auto program = GetPrettyPrint(res); Cerr << program << Endl; #endif - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("default")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("columnConstrains")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("columnFamilies")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("default")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("columnConstrains")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("columnFamilies")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(ChangefeedParseCorrect) { - auto res = SqlToYql(R"( USE plato; +Y_UNIT_TEST(ChangefeedParseCorrect) { + auto res = SqlToYql(R"( USE plato; CREATE TABLE tableName ( Key Uint32, PRIMARY KEY (Key), CHANGEFEED feedName WITH ( @@ -3238,424 +3197,415 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ) ); )"); - UNIT_ASSERT_C(res.Root, Err2Str(res)); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("changefeed")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("mode")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("KEYS_ONLY")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("format")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("json")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("initial_scan")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("true")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("virtual_timestamps")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("false")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("barriers_interval")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("schema_changes")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("retention_period")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("topic_min_active_partitions")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("aws_region")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("aws:region")); - } - }; + UNIT_ASSERT_C(res.Root, Err2Str(res)); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("changefeed")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("mode")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("KEYS_ONLY")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("format")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("json")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("initial_scan")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("true")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("virtual_timestamps")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("false")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("barriers_interval")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("schema_changes")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("retention_period")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("topic_min_active_partitions")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("aws_region")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("aws:region")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CloneForAsTableWorksWithCube) { - UNIT_ASSERT(SqlToYql("SELECT * FROM AS_TABLE([<|k1:1, k2:1|>]) GROUP BY CUBE(k1, k2);").IsOk()); - } +Y_UNIT_TEST(CloneForAsTableWorksWithCube) { + UNIT_ASSERT(SqlToYql("SELECT * FROM AS_TABLE([<|k1:1, k2:1|>]) GROUP BY CUBE(k1, k2);").IsOk()); +} - Y_UNIT_TEST(WindowPartitionByColumnProperlyEscaped) { - NYql::TAstParseResult res = SqlToYql("SELECT SUM(key) OVER w FROM plato.Input WINDOW w AS (PARTITION BY `column with space`);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(WindowPartitionByColumnProperlyEscaped) { + NYql::TAstParseResult res = SqlToYql("SELECT SUM(key) OVER w FROM plato.Input WINDOW w AS (PARTITION BY `column with space`);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "CalcOverWindow") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"column with space\"")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "CalcOverWindow") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("\"column with space\"")); + } + }; - TWordCountHive elementStat = { {TString("CalcOverWindow"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("CalcOverWindow"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["CalcOverWindow"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["CalcOverWindow"]); +} - Y_UNIT_TEST(WindowPartitionByExpressionWithoutAliasesAreAllowed) { - NYql::TAstParseResult res = SqlToYql("SELECT SUM(key) OVER w FROM plato.Input as i WINDOW w AS (PARTITION BY ii.subkey);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(WindowPartitionByExpressionWithoutAliasesAreAllowed) { + NYql::TAstParseResult res = SqlToYql("SELECT SUM(key) OVER w FROM plato.Input as i WINDOW w AS (PARTITION BY ii.subkey);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "AddMember") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("AddMember row 'group_w_0 (SqlAccess 'struct (Member row '\"ii\")")); - } - if (word == "CalcOverWindow") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("CalcOverWindow core '('\"group_w_0\")")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "AddMember") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("AddMember row 'group_w_0 (SqlAccess 'struct (Member row '\"ii\")")); + } + if (word == "CalcOverWindow") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("CalcOverWindow core '('\"group_w_0\")")); + } + }; - TWordCountHive elementStat = { {TString("CalcOverWindow"), 0}, {TString("AddMember"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("CalcOverWindow"), 0}, {TString("AddMember"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["CalcOverWindow"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["AddMember"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["CalcOverWindow"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["AddMember"]); +} - Y_UNIT_TEST(PqReadByAfterUse) { - ExpectFailWithError("use plato; pragma PqReadBy='plato2';", - "<main>:1:28: Error: Cluster in PqReadPqBy pragma differs from cluster specified in USE statement: plato2 != plato\n"); +Y_UNIT_TEST(PqReadByAfterUse) { + ExpectFailWithError("use plato; pragma PqReadBy='plato2';", + "<main>:1:28: Error: Cluster in PqReadPqBy pragma differs from cluster specified in USE statement: plato2 != plato\n"); - UNIT_ASSERT(SqlToYql("pragma PqReadBy='plato2';").IsOk()); - UNIT_ASSERT(SqlToYql("pragma PqReadBy='plato2'; use plato;").IsOk()); - UNIT_ASSERT(SqlToYql("$x='plato'; use rtmr:$x; pragma PqReadBy='plato2';").IsOk()); - UNIT_ASSERT(SqlToYql("use plato; pragma PqReadBy='dq';").IsOk()); - } + UNIT_ASSERT(SqlToYql("pragma PqReadBy='plato2';").IsOk()); + UNIT_ASSERT(SqlToYql("pragma PqReadBy='plato2'; use plato;").IsOk()); + UNIT_ASSERT(SqlToYql("$x='plato'; use rtmr:$x; pragma PqReadBy='plato2';").IsOk()); + UNIT_ASSERT(SqlToYql("use plato; pragma PqReadBy='dq';").IsOk()); +} - Y_UNIT_TEST(MrObject) { - NYql::TAstParseResult res = SqlToYql( - "declare $path as String;\n" - "select * from plato.object($path, `format`, \"comp\" || \"ression\" as compression, 1 as bar) with schema (Int32 as y, String as x)" - ); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(MrObject) { + NYql::TAstParseResult res = SqlToYql( + "declare $path as String;\n" + "select * from plato.object($path, `format`, \"comp\" || \"ression\" as compression, 1 as bar) with schema (Int32 as y, String as x)"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "MrObject") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((MrObject (EvaluateAtom "$path") '"format" '('('"compression" (Concat (String '"comp") (String '"ression"))) '('"bar" (Int32 '"1")))))__")); - } else if (word == "userschema") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__('('('"userschema" (StructType '('"y" (DataType 'Int32)) '('"x" (DataType 'String))) '('"y" '"x"))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "MrObject") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((MrObject (EvaluateAtom "$path") '"format" '('('"compression" (Concat (String '"comp") (String '"ression"))) '('"bar" (Int32 '"1")))))__")); + } else if (word == "userschema") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__('('('"userschema" (StructType '('"y" (DataType 'Int32)) '('"x" (DataType 'String))) '('"y" '"x"))))__")); + } + }; - TWordCountHive elementStat = {{TString("MrObject"), 0}, {TString("userschema"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("MrObject"), 0}, {TString("userschema"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["MrObject"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["userschema"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["MrObject"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["userschema"]); +} - Y_UNIT_TEST(TableBindings) { - NSQLTranslation::TTranslationSettings settings = GetSettingsWithS3Binding("foo"); - NYql::TAstParseResult res = SqlToYqlWithSettings( - "select * from bindings.foo", - settings - ); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(TableBindings) { + NSQLTranslation::TTranslationSettings settings = GetSettingsWithS3Binding("foo"); + NYql::TAstParseResult res = SqlToYqlWithSettings( + "select * from bindings.foo", + settings); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "MrObject") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((MrTableConcat (Key '('table (String '"path")))) (Void) '('('"bar" '"1") '('"compression" '"ccompression") '('"format" '"format") '('"partitionedby" '"key" '"subkey") '('"userschema" (SqlTypeFromYson)__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "MrObject") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((MrTableConcat (Key '('table (String '"path")))) (Void) '('('"bar" '"1") '('"compression" '"ccompression") '('"format" '"format") '('"partitionedby" '"key" '"subkey") '('"userschema" (SqlTypeFromYson)__")); + } + }; - TWordCountHive elementStat = {{TString("MrTableConcat"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("MrTableConcat"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["MrTableConcat"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["MrTableConcat"]); - settings.DefaultCluster = "plato"; - settings.BindingsMode = NSQLTranslation::EBindingsMode::DISABLED; - res = SqlToYqlWithSettings( - "select * from bindings.foo", - settings - ); - UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), "<main>:1:15: Error: Please remove 'bindings.' from your query, the support for this syntax has ended, code: 4601\n"); - UNIT_ASSERT(!res.Root); + settings.DefaultCluster = "plato"; + settings.BindingsMode = NSQLTranslation::EBindingsMode::DISABLED; + res = SqlToYqlWithSettings( + "select * from bindings.foo", + settings); + UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), "<main>:1:15: Error: Please remove 'bindings.' from your query, the support for this syntax has ended, code: 4601\n"); + UNIT_ASSERT(!res.Root); - settings.BindingsMode = NSQLTranslation::EBindingsMode::DROP; - res = SqlToYqlWithSettings( - "select * from bindings.foo", - settings - ); + settings.BindingsMode = NSQLTranslation::EBindingsMode::DROP; + res = SqlToYqlWithSettings( + "select * from bindings.foo", + settings); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine2 = [](const TString& word, const TString& line) { - if (word == "MrTableConcat") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((MrTableConcat (Key '('table (String '"foo")))) (Void) '())))__")); - } - }; + TVerifyLineFunc verifyLine2 = [](const TString& word, const TString& line) { + if (word == "MrTableConcat") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((MrTableConcat (Key '('table (String '"foo")))) (Void) '())))__")); + } + }; - TWordCountHive elementStat2 = {{TString("MrTableConcat"), 0}}; - VerifyProgram(res, elementStat2, verifyLine2); + TWordCountHive elementStat2 = {{TString("MrTableConcat"), 0}}; + VerifyProgram(res, elementStat2, verifyLine2); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat2["MrTableConcat"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat2["MrTableConcat"]); - settings.BindingsMode = NSQLTranslation::EBindingsMode::DROP_WITH_WARNING; - res = SqlToYqlWithSettings( - "select * from bindings.foo", - settings - ); - UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), "<main>:1:15: Warning: Please remove 'bindings.' from your query, the support for this syntax will be dropped soon, code: 4538\n"); - UNIT_ASSERT(res.Root); + settings.BindingsMode = NSQLTranslation::EBindingsMode::DROP_WITH_WARNING; + res = SqlToYqlWithSettings( + "select * from bindings.foo", + settings); + UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), "<main>:1:15: Warning: Please remove 'bindings.' from your query, the support for this syntax will be dropped soon, code: 4538\n"); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat3 = {{TString("MrTableConcat"), 0}}; - VerifyProgram(res, elementStat3, verifyLine2); + TWordCountHive elementStat3 = {{TString("MrTableConcat"), 0}}; + VerifyProgram(res, elementStat3, verifyLine2); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat3["MrTableConcat"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat3["MrTableConcat"]); +} - Y_UNIT_TEST(TableBindingsWithInsert) { - NSQLTranslation::TTranslationSettings settings = GetSettingsWithS3Binding("foo"); - NYql::TAstParseResult res = SqlToYqlWithSettings( - "insert into bindings.foo with truncate (x, y) values (1, 2);", - settings - ); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(TableBindingsWithInsert) { + NSQLTranslation::TTranslationSettings settings = GetSettingsWithS3Binding("foo"); + NYql::TAstParseResult res = SqlToYqlWithSettings( + "insert into bindings.foo with truncate (x, y) values (1, 2);", + settings); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((Write! world sink (Key '('table (String '"path"))) values '('('"bar" '"1") '('"compression" '"ccompression") '('"format" '"format") '('"partitionedby" '"key" '"subkey") '('"userschema" (SqlTypeFromYson)__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((Write! world sink (Key '('table (String '"path"))) values '('('"bar" '"1") '('"compression" '"ccompression") '('"format" '"format") '('"partitionedby" '"key" '"subkey") '('"userschema" (SqlTypeFromYson)__")); + } + }; - TWordCountHive elementStat = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]); - settings.DefaultCluster = "plato"; - settings.BindingsMode = NSQLTranslation::EBindingsMode::DISABLED; - res = SqlToYqlWithSettings( - "insert into bindings.foo with truncate (x, y) values (1, 2);", - settings - ); - UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), "<main>:1:13: Error: Please remove 'bindings.' from your query, the support for this syntax has ended, code: 4601\n"); - UNIT_ASSERT(!res.Root); + settings.DefaultCluster = "plato"; + settings.BindingsMode = NSQLTranslation::EBindingsMode::DISABLED; + res = SqlToYqlWithSettings( + "insert into bindings.foo with truncate (x, y) values (1, 2);", + settings); + UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), "<main>:1:13: Error: Please remove 'bindings.' from your query, the support for this syntax has ended, code: 4601\n"); + UNIT_ASSERT(!res.Root); - settings.BindingsMode = NSQLTranslation::EBindingsMode::DROP; - res = SqlToYqlWithSettings( - "insert into bindings.foo with truncate (x, y) values (1, 2);", - settings - ); - UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), ""); - UNIT_ASSERT(res.Root); + settings.BindingsMode = NSQLTranslation::EBindingsMode::DROP; + res = SqlToYqlWithSettings( + "insert into bindings.foo with truncate (x, y) values (1, 2);", + settings); + UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), ""); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine2 = [](const TString& word, const TString& line) { - if (word == "Write!") { - //UNIT_ASSERT_VALUES_EQUAL(line, ""); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__((Write! world sink (Key '('table (String '"foo"))) values '('('mode 'renew)))__")); - } - }; + TVerifyLineFunc verifyLine2 = [](const TString& word, const TString& line) { + if (word == "Write!") { + // UNIT_ASSERT_VALUES_EQUAL(line, ""); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__((Write! world sink (Key '('table (String '"foo"))) values '('('mode 'renew)))__")); + } + }; - TWordCountHive elementStat2 = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat2, verifyLine2); + TWordCountHive elementStat2 = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat2, verifyLine2); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat2["Write!"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat2["Write!"]); - settings.BindingsMode = NSQLTranslation::EBindingsMode::DROP_WITH_WARNING; - res = SqlToYqlWithSettings( - "insert into bindings.foo with truncate (x, y) values (1, 2);", - settings - ); - UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), "<main>:1:13: Warning: Please remove 'bindings.' from your query, the support for this syntax will be dropped soon, code: 4538\n"); - UNIT_ASSERT(res.Root); + settings.BindingsMode = NSQLTranslation::EBindingsMode::DROP_WITH_WARNING; + res = SqlToYqlWithSettings( + "insert into bindings.foo with truncate (x, y) values (1, 2);", + settings); + UNIT_ASSERT_VALUES_EQUAL(Err2Str(res), "<main>:1:13: Warning: Please remove 'bindings.' from your query, the support for this syntax will be dropped soon, code: 4538\n"); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat3 = {{TString("Write!"), 0}}; - VerifyProgram(res, elementStat3, verifyLine2); + TWordCountHive elementStat3 = {{TString("Write!"), 0}}; + VerifyProgram(res, elementStat3, verifyLine2); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat3["Write!"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat3["Write!"]); +} - Y_UNIT_TEST(TrailingCommaInWithout) { - UNIT_ASSERT(SqlToYql("SELECT * WITHOUT stream, FROM plato.Input").IsOk()); - UNIT_ASSERT(SqlToYql("SELECT a.* WITHOUT a.intersect, FROM plato.Input AS a").IsOk()); - UNIT_ASSERT(SqlToYql("SELECT a.* WITHOUT col1, col2, a.col3, FROM plato.Input AS a").IsOk()); - } +Y_UNIT_TEST(TrailingCommaInWithout) { + UNIT_ASSERT(SqlToYql("SELECT * WITHOUT stream, FROM plato.Input").IsOk()); + UNIT_ASSERT(SqlToYql("SELECT a.* WITHOUT a.intersect, FROM plato.Input AS a").IsOk()); + UNIT_ASSERT(SqlToYql("SELECT a.* WITHOUT col1, col2, a.col3, FROM plato.Input AS a").IsOk()); +} - Y_UNIT_TEST(NoStackOverflowOnBigCaseStatement) { - TStringBuilder req; - req << "select case 1 + 123"; - for (size_t i = 0; i < 20000; ++i) { - req << " when " << i << " then " << i + 1; - } - req << " else 100500 end;"; - UNIT_ASSERT(SqlToYql(req).IsOk()); +Y_UNIT_TEST(NoStackOverflowOnBigCaseStatement) { + TStringBuilder req; + req << "select case 1 + 123"; + for (size_t i = 0; i < 20000; ++i) { + req << " when " << i << " then " << i + 1; } + req << " else 100500 end;"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(CollectPreaggregatedInListLiteral) { - UNIT_ASSERT(SqlToYql("SELECT [COUNT(DISTINCT a+b)] FROM plato.Input").IsOk()); - } +Y_UNIT_TEST(CollectPreaggregatedInListLiteral) { + UNIT_ASSERT(SqlToYql("SELECT [COUNT(DISTINCT a+b)] FROM plato.Input").IsOk()); +} - Y_UNIT_TEST(SmartParenInGroupByClause) { - UNIT_ASSERT(SqlToYql("SELECT * FROM plato.Input GROUP BY (k, v)").IsOk()); - } +Y_UNIT_TEST(SmartParenInGroupByClause) { + UNIT_ASSERT(SqlToYql("SELECT * FROM plato.Input GROUP BY (k, v)").IsOk()); +} - Y_UNIT_TEST(AlterTableRenameToIsCorrect) { - UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table RENAME TO moved").IsOk()); - } +Y_UNIT_TEST(AlterTableRenameToIsCorrect) { + UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table RENAME TO moved").IsOk()); +} - Y_UNIT_TEST(AlterTableAddDropColumnIsCorrect) { - UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table ADD COLUMN addc uint64, DROP COLUMN dropc, ADD addagain uint64").IsOk()); - } +Y_UNIT_TEST(AlterTableAddDropColumnIsCorrect) { + UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table ADD COLUMN addc uint64, DROP COLUMN dropc, ADD addagain uint64").IsOk()); +} - Y_UNIT_TEST(AlterTableSetTTLIsCorrect) { - UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table SET (TTL = Interval(\"PT3H\") ON column)").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table SET (TTL = Interval(\"PT3H\") ON column AS SECONDS)").IsOk()); - } +Y_UNIT_TEST(AlterTableSetTTLIsCorrect) { + UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table SET (TTL = Interval(\"PT3H\") ON column)").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table SET (TTL = Interval(\"PT3H\") ON column AS SECONDS)").IsOk()); +} - Y_UNIT_TEST(AlterTableSetTieringIsCorrect) { - UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table SET (TIERING = 'my_tiering')").IsOk()); - } +Y_UNIT_TEST(AlterTableSetTieringIsCorrect) { + UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table SET (TIERING = 'my_tiering')").IsOk()); +} - Y_UNIT_TEST(AlterTableAddChangefeedIsCorrect) { - UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table ADD CHANGEFEED feed WITH (MODE = 'UPDATES', FORMAT = 'json')").IsOk()); - } +Y_UNIT_TEST(AlterTableAddChangefeedIsCorrect) { + UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table ADD CHANGEFEED feed WITH (MODE = 'UPDATES', FORMAT = 'json')").IsOk()); +} - Y_UNIT_TEST(AlterTableAlterChangefeedIsCorrect) { - UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table ALTER CHANGEFEED feed DISABLE").IsOk()); - ExpectFailWithError("USE plato; ALTER TABLE table ALTER CHANGEFEED feed SET (FORMAT = 'proto');", - "<main>:1:57: Error: FORMAT alter is not supported\n"); - } +Y_UNIT_TEST(AlterTableAlterChangefeedIsCorrect) { + UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table ALTER CHANGEFEED feed DISABLE").IsOk()); + ExpectFailWithError("USE plato; ALTER TABLE table ALTER CHANGEFEED feed SET (FORMAT = 'proto');", + "<main>:1:57: Error: FORMAT alter is not supported\n"); +} - Y_UNIT_TEST(AlterTableDropChangefeedIsCorrect) { - UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table DROP CHANGEFEED feed").IsOk()); - } +Y_UNIT_TEST(AlterTableDropChangefeedIsCorrect) { + UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table DROP CHANGEFEED feed").IsOk()); +} - Y_UNIT_TEST(AlterTableSetPartitioningIsCorrect) { - UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table SET (AUTO_PARTITIONING_BY_SIZE = DISABLED)").IsOk()); - } +Y_UNIT_TEST(AlterTableSetPartitioningIsCorrect) { + UNIT_ASSERT(SqlToYql("USE plato; ALTER TABLE table SET (AUTO_PARTITIONING_BY_SIZE = DISABLED)").IsOk()); +} - Y_UNIT_TEST(AlterTableAddIndexWithIsNotSupported) { +Y_UNIT_TEST(AlterTableAddIndexWithIsNotSupported) { #if ANTLR_VER == 3 - ExpectFailWithFuzzyError("USE plato; ALTER TABLE table ADD INDEX idx GLOBAL ON (col) WITH (a=b)", - "<main>:1:40: Error: with: alternative is not implemented yet: \\d+:\\d+: global_index\\n"); + ExpectFailWithFuzzyError("USE plato; ALTER TABLE table ADD INDEX idx GLOBAL ON (col) WITH (a=b)", + "<main>:1:40: Error: with: alternative is not implemented yet: \\d+:\\d+: global_index\\n"); #else - ExpectFailWithError("USE plato; ALTER TABLE table ADD INDEX idx GLOBAL ON (col) WITH (a=b)", - "<main>:1:40: Error: with: alternative is not implemented yet: \n"); + ExpectFailWithError("USE plato; ALTER TABLE table ADD INDEX idx GLOBAL ON (col) WITH (a=b)", + "<main>:1:40: Error: with: alternative is not implemented yet: \n"); #endif - } +} - Y_UNIT_TEST(AlterTableAddIndexLocalIsNotSupported) { +Y_UNIT_TEST(AlterTableAddIndexLocalIsNotSupported) { #if ANTLR_VER == 3 - ExpectFailWithFuzzyError("USE plato; ALTER TABLE table ADD INDEX idx LOCAL ON (col)", - "<main>:1:40: Error: local: alternative is not implemented yet: \\d+:\\d+: local_index\\n"); + ExpectFailWithFuzzyError("USE plato; ALTER TABLE table ADD INDEX idx LOCAL ON (col)", + "<main>:1:40: Error: local: alternative is not implemented yet: \\d+:\\d+: local_index\\n"); #else - ExpectFailWithError("USE plato; ALTER TABLE table ADD INDEX idx LOCAL ON (col)", - "<main>:1:40: Error: local: alternative is not implemented yet: \n"); + ExpectFailWithError("USE plato; ALTER TABLE table ADD INDEX idx LOCAL ON (col)", + "<main>:1:40: Error: local: alternative is not implemented yet: \n"); #endif - } +} - Y_UNIT_TEST(CreateTableAddIndexGlobalUnique) { - NYql::TAstParseResult result = SqlToYql(R"sql(USE plato; +Y_UNIT_TEST(CreateTableAddIndexGlobalUnique) { + NYql::TAstParseResult result = SqlToYql(R"sql(USE plato; CREATE TABLE table ( pk INT32 NOT NULL, col String, INDEX idx GLOBAL UNIQUE ON(col), PRIMARY KEY (pk)) )sql"); - UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); - UNIT_ASSERT(result.Root); + UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); + UNIT_ASSERT(result.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_STRING_CONTAINS(line, R"('indexType 'syncGlobalUnique)"); - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_STRING_CONTAINS(line, R"('indexType 'syncGlobalUnique)"); + }; - TWordCountHive elementStat({TString("\'indexName \'\"idx\"")}); - VerifyProgram(result, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'indexName \'\"idx\""]); - } + TWordCountHive elementStat({TString("\'indexName \'\"idx\"")}); + VerifyProgram(result, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'indexName \'\"idx\""]); +} - Y_UNIT_TEST(CreateTableAddIndexGlobalUniqueSync) { - NYql::TAstParseResult result = SqlToYql(R"sql(USE plato; +Y_UNIT_TEST(CreateTableAddIndexGlobalUniqueSync) { + NYql::TAstParseResult result = SqlToYql(R"sql(USE plato; CREATE TABLE table ( pk INT32 NOT NULL, col String, INDEX idx GLOBAL UNIQUE SYNC ON(col), PRIMARY KEY (pk)) )sql"); - UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); - UNIT_ASSERT(result.Root); + UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); + UNIT_ASSERT(result.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_STRING_CONTAINS(line, R"('indexType 'syncGlobalUnique)"); - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_STRING_CONTAINS(line, R"('indexType 'syncGlobalUnique)"); + }; - TWordCountHive elementStat({TString("\'indexName \'\"idx\"")}); - VerifyProgram(result, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'indexName \'\"idx\""]); - } + TWordCountHive elementStat({TString("\'indexName \'\"idx\"")}); + VerifyProgram(result, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'indexName \'\"idx\""]); +} - Y_UNIT_TEST(CreateTableAddIndexGlobalUniqueAsync) { +Y_UNIT_TEST(CreateTableAddIndexGlobalUniqueAsync) { #if ANTLR_VER == 3 - ExpectFailWithFuzzyError(R"sql(USE plato; + ExpectFailWithFuzzyError(R"sql(USE plato; CREATE TABLE table ( pk INT32 NOT NULL, col String, INDEX idx GLOBAL UNIQUE ASYNC ON(col), PRIMARY KEY (pk)) )sql", - "<main>:5:41: Error: unique: alternative is not implemented yet: \\d+:\\d+: global_index\\n"); + "<main>:5:41: Error: unique: alternative is not implemented yet: \\d+:\\d+: global_index\\n"); #else - ExpectFailWithError(R"sql(USE plato; + ExpectFailWithError(R"sql(USE plato; CREATE TABLE table ( pk INT32 NOT NULL, col String, INDEX idx GLOBAL UNIQUE ASYNC ON(col), PRIMARY KEY (pk)) )sql", - "<main>:5:41: Error: unique: alternative is not implemented yet: \n"); + "<main>:5:41: Error: unique: alternative is not implemented yet: \n"); #endif - } +} - Y_UNIT_TEST(AlterTableAddIndexGlobalUnique) { - NYql::TAstParseResult result = SqlToYql(R"sql(USE plato; +Y_UNIT_TEST(AlterTableAddIndexGlobalUnique) { + NYql::TAstParseResult result = SqlToYql(R"sql(USE plato; ALTER TABLE table ADD INDEX idx GLOBAL UNIQUE ON(col))sql"); - UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); - UNIT_ASSERT(result.Root); + UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); + UNIT_ASSERT(result.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_STRING_CONTAINS(line, R"('indexType 'syncGlobalUnique)"); - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_STRING_CONTAINS(line, R"('indexType 'syncGlobalUnique)"); + }; - TWordCountHive elementStat({TString("\'indexName \'\"idx\"")}); - VerifyProgram(result, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'indexName \'\"idx\""]); - } + TWordCountHive elementStat({TString("\'indexName \'\"idx\"")}); + VerifyProgram(result, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'indexName \'\"idx\""]); +} - Y_UNIT_TEST(AlterTableAddIndexGlobalUniqueSync) { - NYql::TAstParseResult result = SqlToYql(R"sql(USE plato; +Y_UNIT_TEST(AlterTableAddIndexGlobalUniqueSync) { + NYql::TAstParseResult result = SqlToYql(R"sql(USE plato; ALTER TABLE table ADD INDEX idx GLOBAL UNIQUE SYNC ON(col))sql"); - UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); - UNIT_ASSERT(result.Root); + UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); + UNIT_ASSERT(result.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_STRING_CONTAINS(line, R"('indexType 'syncGlobalUnique)"); - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_STRING_CONTAINS(line, R"('indexType 'syncGlobalUnique)"); + }; - TWordCountHive elementStat({TString("\'indexName \'\"idx\"")}); - VerifyProgram(result, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'indexName \'\"idx\""]); - } + TWordCountHive elementStat({TString("\'indexName \'\"idx\"")}); + VerifyProgram(result, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'indexName \'\"idx\""]); +} - Y_UNIT_TEST(AlterTableAddIndexGlobalUniqueAsync) { +Y_UNIT_TEST(AlterTableAddIndexGlobalUniqueAsync) { #if ANTLR_VER == 3 - ExpectFailWithFuzzyError(R"sql(USE plato; + ExpectFailWithFuzzyError(R"sql(USE plato; ALTER TABLE table ADD INDEX idx GLOBAL UNIQUE ASYNC ON(col))sql", - "<main>:2:59: Error: unique: alternative is not implemented yet: \\d+:\\d+: global_index\\n"); + "<main>:2:59: Error: unique: alternative is not implemented yet: \\d+:\\d+: global_index\\n"); #else - ExpectFailWithError(R"sql(USE plato; + ExpectFailWithError(R"sql(USE plato; ALTER TABLE table ADD INDEX idx GLOBAL UNIQUE ASYNC ON(col))sql", - "<main>:2:59: Error: unique: alternative is not implemented yet: \n"); + "<main>:2:59: Error: unique: alternative is not implemented yet: \n"); #endif - } +} - Y_UNIT_TEST(CreateTableAddIndexVector) { - const auto result = SqlToYql(R"sql(USE plato; +Y_UNIT_TEST(CreateTableAddIndexVector) { + const auto result = SqlToYql(R"sql(USE plato; CREATE TABLE table ( pk INT32 NOT NULL, col String, @@ -3664,81 +3614,78 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { WITH (distance=cosine, vector_type=float, vector_dimension=1024, levels=3, clusters=10), PRIMARY KEY (pk)) )sql"); - UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); - } + UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); +} - Y_UNIT_TEST(AlterTableAddIndexVector) { - const auto result = SqlToYql(R"sql(USE plato; +Y_UNIT_TEST(AlterTableAddIndexVector) { + const auto result = SqlToYql(R"sql(USE plato; ALTER TABLE table ADD INDEX idx GLOBAL USING vector_kmeans_tree ON (col) COVER (col) WITH (distance=cosine, vector_type="float", vector_dimension=1024, levels=3, clusters=10) )sql"); - UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); - } + UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); +} - Y_UNIT_TEST(AlterTableAddIndexDifferentSettings) { - // index settings and their types are checked in KQP - const auto result = SqlToYql(R"sql(USE plato; +Y_UNIT_TEST(AlterTableAddIndexDifferentSettings) { + // index settings and their types are checked in KQP + const auto result = SqlToYql(R"sql(USE plato; ALTER TABLE table ADD INDEX idx GLOBAL USING vector_kmeans_tree ON (col) COVER (col) WITH (distance=42, vector_type="float", vector_dimension=True, levels=none, clusters=10, asdf=qwerty) )sql"); - UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); - } + UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); +} - Y_UNIT_TEST(AlterTableAddIndexDuplicatedSetting) { - ExpectFailWithError(R"sql(USE plato; +Y_UNIT_TEST(AlterTableAddIndexDuplicatedSetting) { + ExpectFailWithError(R"sql(USE plato; ALTER TABLE table ADD INDEX idx GLOBAL USING vector_kmeans_tree ON (col) COVER (col) WITH (distance=cosine, distance=42) )sql", - "<main>:5:49: Error: Duplicated distance\n"); - } + "<main>:5:49: Error: Duplicated distance\n"); +} - Y_UNIT_TEST(AlterTableAddIndexUnknownSubtype) { - ExpectFailWithError("USE plato; ALTER TABLE table ADD INDEX idx GLOBAL USING unknown ON (col)", - "<main>:1:57: Error: UNKNOWN index subtype is not supported\n"); - } +Y_UNIT_TEST(AlterTableAddIndexUnknownSubtype) { + ExpectFailWithError("USE plato; ALTER TABLE table ADD INDEX idx GLOBAL USING unknown ON (col)", + "<main>:1:57: Error: UNKNOWN index subtype is not supported\n"); +} - Y_UNIT_TEST(AlterTableAlterIndexSetPartitioningIsCorrect) { - const auto result = SqlToYql("USE plato; ALTER TABLE table ALTER INDEX index SET AUTO_PARTITIONING_MIN_PARTITIONS_COUNT 10"); - UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); - } +Y_UNIT_TEST(AlterTableAlterIndexSetPartitioningIsCorrect) { + const auto result = SqlToYql("USE plato; ALTER TABLE table ALTER INDEX index SET AUTO_PARTITIONING_MIN_PARTITIONS_COUNT 10"); + UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); +} - Y_UNIT_TEST(AlterTableAlterIndexSetMultiplePartitioningSettings) { - const auto result = SqlToYql("USE plato; ALTER TABLE table ALTER INDEX index SET " - "(AUTO_PARTITIONING_BY_LOAD = ENABLED, AUTO_PARTITIONING_MIN_PARTITIONS_COUNT = 10)" - ); - UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); - } +Y_UNIT_TEST(AlterTableAlterIndexSetMultiplePartitioningSettings) { + const auto result = SqlToYql("USE plato; ALTER TABLE table ALTER INDEX index SET " + "(AUTO_PARTITIONING_BY_LOAD = ENABLED, AUTO_PARTITIONING_MIN_PARTITIONS_COUNT = 10)"); + UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); +} - Y_UNIT_TEST(AlterTableAlterIndexResetPartitioningIsNotSupported) { - ExpectFailWithError("USE plato; ALTER TABLE table ALTER INDEX index RESET (AUTO_PARTITIONING_MIN_PARTITIONS_COUNT)", - "<main>:1:55: Error: AUTO_PARTITIONING_MIN_PARTITIONS_COUNT reset is not supported\n" - ); - } +Y_UNIT_TEST(AlterTableAlterIndexResetPartitioningIsNotSupported) { + ExpectFailWithError("USE plato; ALTER TABLE table ALTER INDEX index RESET (AUTO_PARTITIONING_MIN_PARTITIONS_COUNT)", + "<main>:1:55: Error: AUTO_PARTITIONING_MIN_PARTITIONS_COUNT reset is not supported\n"); +} - Y_UNIT_TEST(AlterTableAlterIndexSetReadReplicasSettingsUncompatIsCorrect) { - const auto result = SqlToYql("USE plato; ALTER TABLE table ALTER INDEX index SET READ_REPLICAS_SETTINGS \"PER_AZ:1\""); - UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); - } +Y_UNIT_TEST(AlterTableAlterIndexSetReadReplicasSettingsUncompatIsCorrect) { + const auto result = SqlToYql("USE plato; ALTER TABLE table ALTER INDEX index SET READ_REPLICAS_SETTINGS \"PER_AZ:1\""); + UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); +} - Y_UNIT_TEST(AlterTableAlterIndexSetReadReplicasSettingsCompatIsCorrect) { - const auto result = SqlToYql("USE plato; ALTER TABLE table ALTER INDEX index SET (READ_REPLICAS_SETTINGS = \"PER_AZ:1\")"); - UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); - } +Y_UNIT_TEST(AlterTableAlterIndexSetReadReplicasSettingsCompatIsCorrect) { + const auto result = SqlToYql("USE plato; ALTER TABLE table ALTER INDEX index SET (READ_REPLICAS_SETTINGS = \"PER_AZ:1\")"); + UNIT_ASSERT_C(result.IsOk(), result.Issues.ToString()); +} - Y_UNIT_TEST(AlterTableAlterIndexResetReadReplicasSettingsIsNotSupported) { - ExpectFailWithError("USE plato; ALTER TABLE table ALTER INDEX index RESET (READ_REPLICAS_SETTINGS)", - "<main>:1:55: Error: READ_REPLICAS_SETTINGS reset is not supported\n" - ); - } +Y_UNIT_TEST(AlterTableAlterIndexResetReadReplicasSettingsIsNotSupported) { + ExpectFailWithError("USE plato; ALTER TABLE table ALTER INDEX index RESET (READ_REPLICAS_SETTINGS)", + "<main>:1:55: Error: READ_REPLICAS_SETTINGS reset is not supported\n"); +} - Y_UNIT_TEST(AlterTableAlterColumnDropNotNullAstCorrect) { - auto reqDropNotNull = SqlToYql(R"sql( +Y_UNIT_TEST(AlterTableAlterColumnDropNotNullAstCorrect) { + auto reqDropNotNull = SqlToYql(R"sql( USE plato; CREATE TABLE tableName ( id Uint32, @@ -3750,23 +3697,22 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ALTER TABLE tableName ALTER COLUMN val DROP NOT NULL; )sql"); - UNIT_ASSERT(reqDropNotNull.IsOk()); + UNIT_ASSERT(reqDropNotNull.IsOk()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - Y_UNUSED(word); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find( - "'('changeColumnConstraints '('('drop_not_null)))" - )); - }; + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find( + "'('changeColumnConstraints '('('drop_not_null)))")); + }; - TWordCountHive elementStat({TString("\'mode \'alter")}); - VerifyProgram(reqDropNotNull, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'mode \'alter"]); - } + TWordCountHive elementStat({TString("\'mode \'alter")}); + VerifyProgram(reqDropNotNull, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'mode \'alter"]); +} - Y_UNIT_TEST(AlterTableAlterColumnSetNotNullAstCorrect) { - auto reqSetNotNull = SqlToYql(R"sql( +Y_UNIT_TEST(AlterTableAlterColumnSetNotNullAstCorrect) { + auto reqSetNotNull = SqlToYql(R"sql( USE plato; CREATE TABLE tableName ( id Uint32, @@ -3778,271 +3724,276 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ALTER TABLE tableName ALTER COLUMN val SET NOT NULL; )sql"); - UNIT_ASSERT(reqSetNotNull.IsOk()); + UNIT_ASSERT(reqSetNotNull.IsOk()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - Y_UNUSED(word); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find( - "'('changeColumnConstraints '('('set_not_null)))" - )); - }; + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find( + "'('changeColumnConstraints '('('set_not_null)))")); + }; - TWordCountHive elementStat({TString("\'mode \'alter")}); - VerifyProgram(reqSetNotNull, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'mode \'alter"]); - } + TWordCountHive elementStat({TString("\'mode \'alter")}); + VerifyProgram(reqSetNotNull, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["\'mode \'alter"]); +} - Y_UNIT_TEST(AlterSequence) { - UNIT_ASSERT(SqlToYql(R"( +Y_UNIT_TEST(AlterSequence) { + UNIT_ASSERT(SqlToYql(R"( USE plato; ALTER SEQUENCE sequence START WITH 10 INCREMENT 2 RESTART WITH 5; - )").IsOk()); - UNIT_ASSERT(SqlToYql(R"( + )") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"( USE plato; ALTER SEQUENCE sequence INCREMENT 2; - )").IsOk()); - UNIT_ASSERT(SqlToYql(R"( + )") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"( USE plato; ALTER SEQUENCE sequence INCREMENT 2 START 1000; - )").IsOk()); - UNIT_ASSERT(SqlToYql(R"( + )") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"( USE plato; ALTER SEQUENCE sequence RESTART START 1000; - )").IsOk()); - UNIT_ASSERT(SqlToYql(R"( + )") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"( USE plato; ALTER SEQUENCE IF EXISTS sequence INCREMENT 1000 START 100 RESTART; - )").IsOk()); - UNIT_ASSERT(SqlToYql(R"( + )") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"( USE plato; ALTER SEQUENCE IF EXISTS sequence RESTART 1000 START WITH 100 INCREMENT BY 7; - )").IsOk()); - } + )") + .IsOk()); +} - Y_UNIT_TEST(AlterSequenceIncorrect) { - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence START WITH 10 INCREMENT 2 RESTART WITH 5 RESTART;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:75: Error: Restart value defined more than once\n"); - } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence START WITH 10 INCREMENT 2 START 100 RESTART WITH 5;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:60: Error: Start value defined more than once\n"); - } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence INCREMENT BY 7 START WITH 10 INCREMENT 2 RESTART WITH 5 RESTART;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:62: Error: Increment defined more than once\n"); - } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 100 START WITH 10 INCREMENT 2 RESTART WITH 5;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:77: Error: Restart value defined more than once\n"); - } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 1234234543563435151456 START WITH 10 INCREMENT 2;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:49: Error: Failed to parse number from string: 1234234543563435151456, number limit overflow\n"); - } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 1 START WITH 9223372036854775817 INCREMENT 4;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Start value: 9223372036854775817 cannot be greater than max value: 9223372036854775807\n"); - } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 9223372036854775827 START WITH 5 INCREMENT 4;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Restart value: 9223372036854775827 cannot be greater than max value: 9223372036854775807\n"); - } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 1 START WITH 4 INCREMENT 0;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Increment must not be zero\n"); - } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 0 START WITH 4 INCREMENT 1;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Restart value: 0 cannot be less than min value: 1\n"); - } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 1 START WITH 0 INCREMENT 1;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Start value: 0 cannot be less than min value: 1\n"); - } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 1 START WITH 1 INCREMENT 9223372036854775837;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Increment: 9223372036854775837 cannot be greater than max value: 9223372036854775807\n"); - } +Y_UNIT_TEST(AlterSequenceIncorrect) { + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence START WITH 10 INCREMENT 2 RESTART WITH 5 RESTART;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:75: Error: Restart value defined more than once\n"); + } + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence START WITH 10 INCREMENT 2 START 100 RESTART WITH 5;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:60: Error: Start value defined more than once\n"); + } + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence INCREMENT BY 7 START WITH 10 INCREMENT 2 RESTART WITH 5 RESTART;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:62: Error: Increment defined more than once\n"); + } + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 100 START WITH 10 INCREMENT 2 RESTART WITH 5;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:77: Error: Restart value defined more than once\n"); } + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 1234234543563435151456 START WITH 10 INCREMENT 2;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:49: Error: Failed to parse number from string: 1234234543563435151456, number limit overflow\n"); + } + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 1 START WITH 9223372036854775817 INCREMENT 4;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Start value: 9223372036854775817 cannot be greater than max value: 9223372036854775807\n"); + } + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 9223372036854775827 START WITH 5 INCREMENT 4;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Restart value: 9223372036854775827 cannot be greater than max value: 9223372036854775807\n"); + } + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 1 START WITH 4 INCREMENT 0;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Increment must not be zero\n"); + } + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 0 START WITH 4 INCREMENT 1;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Restart value: 0 cannot be less than min value: 1\n"); + } + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 1 START WITH 0 INCREMENT 1;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Start value: 0 cannot be less than min value: 1\n"); + } + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence RESTART WITH 1 START WITH 1 INCREMENT 9223372036854775837;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Increment: 9223372036854775837 cannot be greater than max value: 9223372036854775807\n"); + } +} - Y_UNIT_TEST(AlterSequenceCorrect) { - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence START WITH 10 INCREMENT 2 RESTART WITH 5;"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(AlterSequenceCorrect) { + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE sequence START WITH 10 INCREMENT 2 RESTART WITH 5;"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("sequence")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alter")); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("alter_if_exists")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("start")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("increment")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("restart")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("sequence")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alter")); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("alter_if_exists")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("start")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("increment")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("restart")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE IF EXISTS sequence INCREMENT 2 RESTART;"); - UNIT_ASSERT(res.Root); + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE IF EXISTS sequence INCREMENT 2 RESTART;"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("sequence")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alter_if_exists")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("increment")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("restart")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("sequence")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alter_if_exists")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("increment")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("restart")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + } - { - NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE IF EXISTS sequence START 10 INCREMENT BY 2;"); - UNIT_ASSERT(res.Root); + { + NYql::TAstParseResult res = SqlToYql("USE plato; ALTER SEQUENCE IF EXISTS sequence START 10 INCREMENT BY 2;"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("sequence")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alter_if_exists")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("start")); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("restart")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("increment")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("sequence")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alter_if_exists")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("start")); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("restart")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("increment")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); } +} - Y_UNIT_TEST(ShowCreateTable) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(ShowCreateTable) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; SHOW CREATE TABLE user; )"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Read") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("showCreateTable")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Read") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("showCreateTable")); + } + }; - TWordCountHive elementStat = {{TString("Read"), 0}, {TString("showCreateTable"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Read"), 0}, {TString("showCreateTable"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Read"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["showCreateTable"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Read"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["showCreateTable"]); +} - Y_UNIT_TEST(ShowCreateView) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(ShowCreateView) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; SHOW CREATE VIEW user; )"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Read") { - UNIT_ASSERT_STRING_CONTAINS(line, "showCreateView"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Read") { + UNIT_ASSERT_STRING_CONTAINS(line, "showCreateView"); + } + }; - TWordCountHive elementStat = {{"Read"}, {"showCreateView"}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{"Read"}, {"showCreateView"}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["Read"], 1); - UNIT_ASSERT_VALUES_EQUAL(elementStat["showCreateView"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["Read"], 1); + UNIT_ASSERT_VALUES_EQUAL(elementStat["showCreateView"], 1); +} - Y_UNIT_TEST(OptionalAliases) { - UNIT_ASSERT(SqlToYql("USE plato; SELECT foo FROM (SELECT key foo FROM Input);").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT a.x FROM Input1 a JOIN Input2 b ON a.key = b.key;").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; SELECT a.x FROM (VALUES (1,2), (3,4)) a(x,key) JOIN Input b ON a.key = b.key;").IsOk()); - } +Y_UNIT_TEST(OptionalAliases) { + UNIT_ASSERT(SqlToYql("USE plato; SELECT foo FROM (SELECT key foo FROM Input);").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT a.x FROM Input1 a JOIN Input2 b ON a.key = b.key;").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; SELECT a.x FROM (VALUES (1,2), (3,4)) a(x,key) JOIN Input b ON a.key = b.key;").IsOk()); +} - Y_UNIT_TEST(TableNameConstness) { - UNIT_ASSERT(SqlToYql("USE plato; $path = 'foo'; SELECT TableName($path), count(*) FROM Input;").IsOk()); - UNIT_ASSERT(SqlToYql("$path = 'foo'; SELECT TableName($path, 'yt'), count(*) FROM plato.Input;").IsOk()); - ExpectFailWithError("USE plato; SELECT TableName(), count(*) FROM plato.Input;", - "<main>:1:19: Error: Expression has to be an aggregation function or key column, because aggregation is used elsewhere in this subquery\n"); - } +Y_UNIT_TEST(TableNameConstness) { + UNIT_ASSERT(SqlToYql("USE plato; $path = 'foo'; SELECT TableName($path), count(*) FROM Input;").IsOk()); + UNIT_ASSERT(SqlToYql("$path = 'foo'; SELECT TableName($path, 'yt'), count(*) FROM plato.Input;").IsOk()); + ExpectFailWithError("USE plato; SELECT TableName(), count(*) FROM plato.Input;", + "<main>:1:19: Error: Expression has to be an aggregation function or key column, because aggregation is used elsewhere in this subquery\n"); +} - Y_UNIT_TEST(UseShouldWorkAsColumnName) { - UNIT_ASSERT(SqlToYql("select use from (select 1 as use);").IsOk()); - } +Y_UNIT_TEST(UseShouldWorkAsColumnName) { + UNIT_ASSERT(SqlToYql("select use from (select 1 as use);").IsOk()); +} - Y_UNIT_TEST(TrueFalseWorkAfterDollar) { - UNIT_ASSERT(SqlToYql("$ true = false; SELECT $ true or false;").IsOk()); - UNIT_ASSERT(SqlToYql("$False = 0; SELECT $False;").IsOk()); - } +Y_UNIT_TEST(TrueFalseWorkAfterDollar) { + UNIT_ASSERT(SqlToYql("$ true = false; SELECT $ true or false;").IsOk()); + UNIT_ASSERT(SqlToYql("$False = 0; SELECT $False;").IsOk()); +} - Y_UNIT_TEST(WithSchemaEquals) { - UNIT_ASSERT(SqlToYql("select * from plato.T with schema Struct<a:Int32, b:String>;").IsOk()); - UNIT_ASSERT(SqlToYql("select * from plato.T with columns = Struct<a:Int32, b:String>;").IsOk()); - } +Y_UNIT_TEST(WithSchemaEquals) { + UNIT_ASSERT(SqlToYql("select * from plato.T with schema Struct<a:Int32, b:String>;").IsOk()); + UNIT_ASSERT(SqlToYql("select * from plato.T with columns = Struct<a:Int32, b:String>;").IsOk()); +} - Y_UNIT_TEST(WithNonStructSchemaS3) { - NSQLTranslation::TTranslationSettings settings; - settings.ClusterMapping["s3bucket"] = NYql::S3ProviderName; - UNIT_ASSERT(SqlToYqlWithSettings("select * from s3bucket.`foo` with schema (col1 Int32, String as col2, Int64 as col3);", settings).IsOk()); - } +Y_UNIT_TEST(WithNonStructSchemaS3) { + NSQLTranslation::TTranslationSettings settings; + settings.ClusterMapping["s3bucket"] = NYql::S3ProviderName; + UNIT_ASSERT(SqlToYqlWithSettings("select * from s3bucket.`foo` with schema (col1 Int32, String as col2, Int64 as col3);", settings).IsOk()); +} - Y_UNIT_TEST(AllowNestedTuplesInGroupBy) { - NYql::TAstParseResult res = SqlToYql("select count(*) from plato.Input group by 1 + (x, y, z);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(AllowNestedTuplesInGroupBy) { + NYql::TAstParseResult res = SqlToYql("select count(*) from plato.Input group by 1 + (x, y, z);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Aggregate core '('\"group0\")")); - }; + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Aggregate core '('\"group0\")")); + }; - TWordCountHive elementStat({"Aggregate"}); - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat["Aggregate"] == 1); - } + TWordCountHive elementStat({"Aggregate"}); + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT(elementStat["Aggregate"] == 1); +} - Y_UNIT_TEST(AllowGroupByWithParens) { - NYql::TAstParseResult res = SqlToYql("select count(*) from plato.Input group by (x, y as alias1, z);"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(AllowGroupByWithParens) { + NYql::TAstParseResult res = SqlToYql("select count(*) from plato.Input group by (x, y as alias1, z);"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Aggregate core '('\"x\" '\"alias1\" '\"z\")")); - }; + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Aggregate core '('\"x\" '\"alias1\" '\"z\")")); + }; - TWordCountHive elementStat({"Aggregate"}); - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat["Aggregate"] == 1); - } + TWordCountHive elementStat({"Aggregate"}); + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT(elementStat["Aggregate"] == 1); +} - Y_UNIT_TEST(CreateAsyncReplicationParseCorrect) { - auto req = R"( +Y_UNIT_TEST(CreateAsyncReplicationParseCorrect) { + auto req = R"( USE plato; CREATE ASYNC REPLICATION MyReplication FOR table1 AS table2, table3 AS table4 @@ -4053,36 +4004,36 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { CA_CERT = "-----BEGIN CERTIFICATE-----" ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("MyReplication")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("create")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("table1")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("table2")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("table3")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("table4")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("connection_string")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("grpc://localhost:2135/?database=/MyDatabase")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("endpoint")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("localhost:2135")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("database")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("/MyDatabase")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("ca_cert")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("-----BEGIN CERTIFICATE-----")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("MyReplication")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("create")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("table1")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("table2")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("table3")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("table4")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("connection_string")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("grpc://localhost:2135/?database=/MyDatabase")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("endpoint")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("localhost:2135")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("database")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("/MyDatabase")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("ca_cert")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("-----BEGIN CERTIFICATE-----")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateAsyncReplicationUnsupportedSettings) { - auto reqTpl = R"( +Y_UNIT_TEST(CreateAsyncReplicationUnsupportedSettings) { + auto reqTpl = R"( USE plato; CREATE ASYNC REPLICATION MyReplication FOR table1 AS table2, table3 AS table4 @@ -4091,21 +4042,21 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ) )"; - auto settings = THashMap<TString, TString>{ - {"STATE", "DONE"}, - {"FAILOVER_MODE", "FORCE"}, - }; + auto settings = THashMap<TString, TString>{ + {"STATE", "DONE"}, + {"FAILOVER_MODE", "FORCE"}, + }; - for (const auto& [k, v] : settings) { - auto req = Sprintf(reqTpl, k.c_str(), v.c_str()); - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), Sprintf("<main>:6:%zu: Error: %s is not supported in CREATE\n", 20 + k.size(), k.c_str())); - } + for (const auto& [k, v] : settings) { + auto req = Sprintf(reqTpl, k.c_str(), v.c_str()); + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), Sprintf("<main>:6:%zu: Error: %s is not supported in CREATE\n", 20 + k.size(), k.c_str())); } +} - Y_UNIT_TEST(AsyncReplicationInvalidCommitInterval) { - auto req = R"( +Y_UNIT_TEST(AsyncReplicationInvalidCommitInterval) { + auto req = R"( USE plato; CREATE ASYNC REPLICATION MyReplication FOR table1 AS table2, table3 AS table4 @@ -4114,13 +4065,13 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:6:35: Error: Literal of Interval type is expected for COMMIT_INTERVAL\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:6:35: Error: Literal of Interval type is expected for COMMIT_INTERVAL\n"); +} - Y_UNIT_TEST(AlterAsyncReplicationParseCorrect) { - auto req = R"( +Y_UNIT_TEST(AlterAsyncReplicationParseCorrect) { + auto req = R"( USE plato; ALTER ASYNC REPLICATION MyReplication SET ( @@ -4128,28 +4079,28 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { FAILOVER_MODE = "FORCE" ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("MyReplication")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alter")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("state")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("DONE")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("failover_mode")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("FORCE")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("MyReplication")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alter")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("state")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("DONE")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("failover_mode")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("FORCE")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(AlterAsyncReplicationSettings) { - auto reqTpl = R"( +Y_UNIT_TEST(AlterAsyncReplicationSettings) { + auto reqTpl = R"( USE plato; ALTER ASYNC REPLICATION MyReplication SET ( @@ -4157,187 +4108,215 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { ) )"; - auto settings = THashMap<TString, TString>{ - {"connection_string", "grpc://localhost:2135/?database=/MyDatabase"}, - {"endpoint", "localhost:2135"}, - {"database", "/MyDatabase"}, - {"token", "foo"}, - {"token_secret_name", "foo_secret_name"}, - {"user", "user"}, - {"password", "bar"}, - {"password_secret_name", "bar_secret_name"}, - {"ca_cert", "-----BEGIN CERTIFICATE-----"}, - }; + auto settings = THashMap<TString, TString>{ + {"connection_string", "grpc://localhost:2135/?database=/MyDatabase"}, + {"endpoint", "localhost:2135"}, + {"database", "/MyDatabase"}, + {"token", "foo"}, + {"token_secret_name", "foo_secret_name"}, + {"user", "user"}, + {"password", "bar"}, + {"password_secret_name", "bar_secret_name"}, + {"ca_cert", "-----BEGIN CERTIFICATE-----"}, + }; - for (const auto& [k, v] : settings) { - auto req = Sprintf(reqTpl, k.c_str(), v.c_str()); - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); + for (const auto& [k, v] : settings) { + auto req = Sprintf(reqTpl, k.c_str(), v.c_str()); + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [&k, &v](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("MyReplication")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alter")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(k)); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(v)); - } - }; + TVerifyLineFunc verifyLine = [&k, &v](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("MyReplication")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alter")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(k)); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(v)); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); } +} - Y_UNIT_TEST(AlterAsyncReplicationUnsupportedSettings) { - { - auto req = R"( +Y_UNIT_TEST(AlterAsyncReplicationUnsupportedSettings) { + { + auto req = R"( USE plato; ALTER ASYNC REPLICATION MyReplication SET (CONSISTENCY_LEVEL = "GLOBAL"); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:80: Error: CONSISTENCY_LEVEL is not supported in ALTER\n"); - } - { - auto req = R"( + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:80: Error: CONSISTENCY_LEVEL is not supported in ALTER\n"); + } + { + auto req = R"( USE plato; ALTER ASYNC REPLICATION MyReplication SET (COMMIT_INTERVAL = Interval("PT10S")); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:87: Error: COMMIT_INTERVAL is not supported in ALTER\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:87: Error: COMMIT_INTERVAL is not supported in ALTER\n"); } +} - Y_UNIT_TEST(AsyncReplicationInvalidSettings) { - auto req = R"( +Y_UNIT_TEST(AsyncReplicationInvalidSettings) { + auto req = R"( USE plato; ALTER ASYNC REPLICATION MyReplication SET (FOO = "BAR"); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:62: Error: Unknown replication setting: FOO\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:62: Error: Unknown replication setting: FOO\n"); +} - Y_UNIT_TEST(DropAsyncReplicationParseCorrect) { - auto req = R"( +Y_UNIT_TEST(DropAsyncReplicationParseCorrect) { + auto req = R"( USE plato; DROP ASYNC REPLICATION MyReplication; )"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("MyReplication")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("drop")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("MyReplication")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("drop")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DropAsyncReplicationCascade) { - auto req = R"( +Y_UNIT_TEST(DropAsyncReplicationCascade) { + auto req = R"( USE plato; DROP ASYNC REPLICATION MyReplication CASCADE; )"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropCascade")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropCascade")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(PragmaCompactGroupBy) { - auto req = "PRAGMA CompactGroupBy; SELECT key, COUNT(*) FROM plato.Input GROUP BY key;"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(PragmaCompactGroupBy) { + auto req = "PRAGMA CompactGroupBy; SELECT key, COUNT(*) FROM plato.Input GROUP BY key;"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Aggregate") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('compact)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Aggregate") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('compact)")); + } + }; - TWordCountHive elementStat = { {TString("Aggregate"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Aggregate"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Aggregate"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Aggregate"]); +} - Y_UNIT_TEST(PragmaDisableCompactGroupBy) { - auto req = "PRAGMA DisableCompactGroupBy; SELECT key, COUNT(*) FROM plato.Input GROUP /*+ compact() */ BY key;"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(PragmaDisableCompactGroupBy) { + auto req = "PRAGMA DisableCompactGroupBy; SELECT key, COUNT(*) FROM plato.Input GROUP /*+ compact() */ BY key;"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Aggregate") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'('compact)")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Aggregate") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'('compact)")); + } + }; - TWordCountHive elementStat = { {TString("Aggregate"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Aggregate"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Aggregate"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Aggregate"]); +} - Y_UNIT_TEST(AutoSampleWorksWithNamedSubquery) { - UNIT_ASSERT(SqlToYql("$src = select * from plato.Input; select * from $src sample 0.2").IsOk()); - } +Y_UNIT_TEST(AutoSampleWorksWithNamedSubquery) { + UNIT_ASSERT(SqlToYql("$src = select * from plato.Input; select * from $src sample 0.2").IsOk()); +} - Y_UNIT_TEST(AutoSampleWorksWithSubquery) { - UNIT_ASSERT(SqlToYql("select * from (select * from plato.Input) sample 0.2").IsOk()); - } +Y_UNIT_TEST(AutoSampleWorksWithSubquery) { + UNIT_ASSERT(SqlToYql("select * from (select * from plato.Input) sample 0.2").IsOk()); +} - Y_UNIT_TEST(CreateTableTrailingComma) { - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE tableName (Key Uint32, PRIMARY KEY (Key),);").IsOk()); - UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE tableName (Key Uint32,);").IsOk()); - } +Y_UNIT_TEST(CreateTableTrailingComma) { + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE tableName (Key Uint32, PRIMARY KEY (Key),);").IsOk()); + UNIT_ASSERT(SqlToYql("USE plato; CREATE TABLE tableName (Key Uint32,);").IsOk()); +} - Y_UNIT_TEST(BetweenSymmetric) { - UNIT_ASSERT(SqlToYql("select 3 between symmetric 5 and 4;").IsOk()); - UNIT_ASSERT(SqlToYql("select 3 between asymmetric 5 and 4;").IsOk()); - UNIT_ASSERT(SqlToYql("use plato; select key between symmetric and and and from Input;").IsOk()); - UNIT_ASSERT(SqlToYql("use plato; select key between and and and from Input;").IsOk()); - } +Y_UNIT_TEST(BetweenSymmetric) { + UNIT_ASSERT(SqlToYql("select 3 between symmetric 5 and 4;").IsOk()); + UNIT_ASSERT(SqlToYql("select 3 between asymmetric 5 and 4;").IsOk()); + UNIT_ASSERT(SqlToYql("use plato; select key between symmetric and and and from Input;").IsOk()); + UNIT_ASSERT(SqlToYql("use plato; select key between and and and from Input;").IsOk()); +} - Y_UNIT_TEST(CreateSecret) { - UNIT_ASSERT(SqlToYql(R"sql( +Y_UNIT_TEST(CreateSecret) { + UNIT_ASSERT(SqlToYql(R"sql( USE plato; CREATE SECRET `secret-name` WITH (value = "secret-value"); - )sql").IsOk()); - UNIT_ASSERT(SqlToYql(R"sql( + )sql") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"sql( USE plato; CREATE SECRET `secret-name` WITH (value = ""); - )sql").IsOk()); - UNIT_ASSERT(SqlToYql(R"sql( + )sql") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"sql( USE plato; PRAGMA TablePathPrefix = "/PathPrefix"; CREATE SECRET `secret-name` WITH (value = "secret-value"); - )sql").IsOk()); - UNIT_ASSERT(SqlToYql(R"sql( + )sql") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"sql( USE plato; CREATE SECRET `secret-name` WITH (value = "secret-value", inherit_permissions = FALSE); - )sql").IsOk()); - UNIT_ASSERT(SqlToYql(R"sql( + )sql") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"sql( USE plato; CREATE SECRET `secret-name` WITH (inherit_permissions = true, value = "secret-value"); - )sql").IsOk()); - } + )sql") + .IsOk()); +} - Y_UNIT_TEST(CreateSecretWithDeclare) { - const auto res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateSecretWithDeclare) { + const auto res = SqlToYql(R"sql( USE plato; declare $foo as String; CREATE SECRET `secret-name` WITH (value = $foo); )sql"); + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'create")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-name")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"("value" (EvaluateAtom "$foo"))")); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("inherit_permissions")); + } + }; + + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} + +Y_UNIT_TEST(CreateSecretCorrect) { + { // basic case: some value, no other params are set + auto res = SqlToYql(R"sql( + USE plato; CREATE SECRET `secret-name` WITH (value = "secret-value"); + )sql"); UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { @@ -4345,1368 +4324,1341 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) { UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'create")); UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-name")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"("value" (EvaluateAtom "$foo"))")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-value")); UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("inherit_permissions")); } }; - TWordCountHive elementStat = { {TString("Write"), 0}}; + TWordCountHive elementStat = {{TString("Write"), 0}}; VerifyProgram(res, elementStat, verifyLine); UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); } - - Y_UNIT_TEST(CreateSecretCorrect) { - { // basic case: some value, no other params are set - auto res = SqlToYql(R"sql( - USE plato; CREATE SECRET `secret-name` WITH (value = "secret-value"); - )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'create")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-name")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-value")); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("inherit_permissions")); - } - }; - - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); - - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } - { // empty value; inherit_permissions is set to True - auto res = SqlToYql(R"sql( + { // empty value; inherit_permissions is set to True + auto res = SqlToYql(R"sql( USE plato; CREATE SECRET `secret-name` WITH (value = "", inherit_permissions = TRUE); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'create")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-name")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"("inherit_permissions" '"1")")); - } - }; + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'create")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-name")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"("inherit_permissions" '"1")")); + } + }; - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } - { // inherit_permissions is set explicitly to its default value - auto res = SqlToYql(R"sql( + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + } + { // inherit_permissions is set explicitly to its default value + auto res = SqlToYql(R"sql( USE plato; PRAGMA TablePathPrefix = "/PathPrefix"; CREATE SECRET `secret-name` WITH (value = "secret-value", inherit_permissions = FALSE); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'create")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("/PathPrefix/secret-name")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-value")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"("inherit_permissions" '"0")")); - } - }; + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'create")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("/PathPrefix/secret-name")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-value")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"("inherit_permissions" '"0")")); + } + }; - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); } +} - Y_UNIT_TEST(CreateSecretIncorrect) { - { // no value - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateSecretIncorrect) { + { // no value + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE SECRET `secret-name` WITH (inherit_permissions = FALSE); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:28: Error: parameter VALUE must be set\n"); - } - { // value is not a string - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:28: Error: parameter VALUE must be set\n"); + } + { // value is not a string + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE SECRET `secret-name` WITH (value = true); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:70: Error: Unsupported type for parameter: VALUE. String (or named expression with type String) was expected\n"); - } - { // value is set twice - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:70: Error: Unsupported type for parameter: VALUE. String (or named expression with type String) was expected\n"); + } + { // value is set twice + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE SECRET `secret-name` WITH (value = "value1", value = "value2"); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:80: Error: Duplicate parameter: VALUE\n"); - } - { // inherit_permissions is set twice - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:80: Error: Duplicate parameter: VALUE\n"); + } + { // inherit_permissions is set twice + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE SECRET `secret-name` WITH (inherit_permissions = FALSE, inherit_permissions = TRUE); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:91: Error: Duplicate parameter: INHERIT_PERMISSIONS\n"); - } - { // inherit_permissions is not bool - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:91: Error: Duplicate parameter: INHERIT_PERMISSIONS\n"); + } + { // inherit_permissions is not bool + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE SECRET `secret-name` WITH (inherit_permissions = "TRUE"); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:84: Error: Unsupported type for parameter: INHERIT_PERMISSIONS. Bool was expected\n"); - } - { // unknown parameter - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:84: Error: Unsupported type for parameter: INHERIT_PERMISSIONS. Bool was expected\n"); + } + { // unknown parameter + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE SECRET `secret-name` WITH (value = "secret-value", abc = "abc"); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:86: Error: Unknown parameter: ABC\n"); - } - { // temporal object in secret name - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:86: Error: Unknown parameter: ABC\n"); + } + { // temporal object in secret name + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE SECRET @tmp WITH (value = "abc"); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:43: Error: '@' is not allowed prefix for secret name\n"); - } - { // empty secret name - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:43: Error: '@' is not allowed prefix for secret name\n"); + } + { // empty secret name + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE SECRET `` WITH (inherit_permissions = FALSE); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:42: Error: Empty secret name\n"); - } + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:42: Error: Empty secret name\n"); } +} - Y_UNIT_TEST(AlterSecret) { - UNIT_ASSERT(SqlToYql(R"sql( +Y_UNIT_TEST(AlterSecret) { + UNIT_ASSERT(SqlToYql(R"sql( USE plato; ALTER SECRET `secret-name` WITH (value = "secret-value"); - )sql").IsOk()); - UNIT_ASSERT(SqlToYql(R"sql( + )sql") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"sql( USE plato; ALTER SECRET `secret-name` WITH (value = ""); - )sql").IsOk()); - UNIT_ASSERT(SqlToYql(R"sql( + )sql") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"sql( USE plato; PRAGMA TablePathPrefix = "/PathPrefix"; ALTER SECRET `secret-name` WITH (value = "secret-value"); - )sql").IsOk()); - } + )sql") + .IsOk()); +} - Y_UNIT_TEST(AlterSecretWithDeclare) { - const auto res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterSecretWithDeclare) { + const auto res = SqlToYql(R"sql( USE plato; declare $foo as String; ALTER SECRET `secret-name` WITH (value = $foo); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'alter")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-name")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"("value" (EvaluateAtom "$foo"))")); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("inherit_permissions")); - } - }; + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'alter")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-name")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"("value" (EvaluateAtom "$foo"))")); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("inherit_permissions")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(AlterSecretCorrect) { - auto res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterSecretCorrect) { + auto res = SqlToYql(R"sql( USE plato; ALTER SECRET `secret-name` WITH (value = "secret-value"); )sql"); - UNIT_ASSERT(res.IsOk()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'alter")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-name")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-value")); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("inherit_permissions")); - } - }; - } + UNIT_ASSERT(res.IsOk()); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'alter")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-name")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-value")); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("inherit_permissions")); + } + }; +} - Y_UNIT_TEST(AlterSecretIncorrect) { - { // no value - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterSecretIncorrect) { + { // no value + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER SECRET `secret-name`; )sql"); - UNIT_ASSERT(!res.Root); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:53: Error: Unexpected token ';' : syntax error...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:53: Error: Unexpected token ';' : syntax error...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:53: Error: mismatched input ';' expecting WITH\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:53: Error: mismatched input ';' expecting WITH\n"); #endif - } - { // value is not a string - NYql::TAstParseResult res = SqlToYql(R"sql( + } + { // value is not a string + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER SECRET `secret-name` WITH (value = true); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:69: Error: Unsupported type for parameter: VALUE. String (or named expression with type String) was expected\n"); - } - { // value is set twice - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:69: Error: Unsupported type for parameter: VALUE. String (or named expression with type String) was expected\n"); + } + { // value is set twice + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER SECRET `secret-name` WITH (value = "value1", value = "value2"); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:79: Error: Duplicate parameter: VALUE\n"); - } - { // inherit_permissions is set - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:79: Error: Duplicate parameter: VALUE\n"); + } + { // inherit_permissions is set + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER SECRET `secret-name` WITH (value = "value", inherit_permissions = FALSE); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:28: Error: parameter INHERIT_PERMISSIONS is not supported for alter operation\n"); - } - { // unknown parameter - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:28: Error: parameter INHERIT_PERMISSIONS is not supported for alter operation\n"); + } + { // unknown parameter + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER SECRET `secret-name` WITH (value = "secret-value", abc = "abc"); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:85: Error: Unknown parameter: ABC\n"); - } - { // temporal object in secret name - NYql::TAstParseResult res = SqlToYql(R"sql( + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:85: Error: Unknown parameter: ABC\n"); + } + { // temporal object in secret name + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER SECRET @tmp WITH (value = "abc"); )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:42: Error: '@' is not allowed prefix for secret name\n"); - } + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:42: Error: '@' is not allowed prefix for secret name\n"); } +} - Y_UNIT_TEST(DropSecret) { - UNIT_ASSERT(SqlToYql(R"sql( +Y_UNIT_TEST(DropSecret) { + UNIT_ASSERT(SqlToYql(R"sql( USE plato; DROP SECRET `secret-name`; - )sql").IsOk()); - UNIT_ASSERT(SqlToYql(R"sql( + )sql") + .IsOk()); + UNIT_ASSERT(SqlToYql(R"sql( USE plato; PRAGMA TablePathPrefix = "/PathPrefix"; DROP SECRET `secret-name`; - )sql").IsOk()); - } + )sql") + .IsOk()); +} - Y_UNIT_TEST(DropSecretCorrect) { - auto res = SqlToYql(R"sql( +Y_UNIT_TEST(DropSecretCorrect) { + auto res = SqlToYql(R"sql( USE plato; DROP SECRET `secret-name`; )sql"); - UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.IsOk()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'drop")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-name")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("Key '('secret")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'mode 'drop")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("secret-name")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DropSecretIncorrect) { - { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropSecretIncorrect) { + { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP SECRET `secret-name` WITH (value = "abc"); )sql"); - UNIT_ASSERT(!res.Root); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:53: Error: Unexpected token 'WITH' : cannot match to any predicted input...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:53: Error: Unexpected token 'WITH' : cannot match to any predicted input...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:53: Error: extraneous input 'WITH' expecting {<EOF>, ';'}\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:53: Error: extraneous input 'WITH' expecting {<EOF>, ';'}\n"); #endif - } - { - NYql::TAstParseResult res = SqlToYql(R"sql( + } + { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP SECRET SECRET `secret-name`; )sql"); - UNIT_ASSERT(!res.Root); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:46: Error: Unexpected token '`secret-name`' : cannot match to any predicted input...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:46: Error: Unexpected token '`secret-name`' : cannot match to any predicted input...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:46: Error: extraneous input '`secret-name`' expecting {<EOF>, ';'}\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:46: Error: extraneous input '`secret-name`' expecting {<EOF>, ';'}\n"); #endif - } - { // temporal object in secret name - NYql::TAstParseResult res = SqlToYql(R"sql( + } + { // temporal object in secret name + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP SECRET @tmp; )sql"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:41: Error: '@' is not allowed prefix for secret name\n"); - } + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:41: Error: '@' is not allowed prefix for secret name\n"); } } +} // Y_UNIT_TEST_SUITE(SqlParsingOnly) Y_UNIT_TEST_SUITE(ExternalFunction) { - Y_UNIT_TEST(ValidUseFunctions) { - - UNIT_ASSERT(SqlToYql( - "PROCESS plato.Input" - " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo', <|a: 123, b: a + 641|>)" - " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>," - " CONCURRENCY=3, OPTIMIZE_FOR='CALLS'").IsOk()); - - // use CALLS without quotes, as keyword - UNIT_ASSERT(SqlToYql( - "PROCESS plato.Input" - " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo')" - " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>," - " OPTIMIZE_FOR=CALLS").IsOk()); - - UNIT_ASSERT(SqlToYql( - "PROCESS plato.Input" - " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo', TableRow())" - " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>," - " CONCURRENCY=3").IsOk()); - - UNIT_ASSERT(SqlToYql( - "PROCESS plato.Input" - " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo')" - " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>," - " CONCURRENCY=3, BATCH_SIZE=1000000, CONNECTION='yc-folder34fse-con'," - " INIT=[0, 900]").IsOk()); - - UNIT_ASSERT(SqlToYql( - "PROCESS plato.Input" - " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'bar', TableRow())" - " WITH UNKNOWN_PARAM_1='837747712', UNKNOWN_PARAM_2=Tuple<Uint16, Utf8>," - " INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>").IsOk()); - } - - - Y_UNIT_TEST(InValidUseFunctions) { - ExpectFailWithError("PROCESS plato.Input USING some::udf(*) WITH INPUT_TYPE=Struct<a:Int32>", - "<main>:1:33: Error: PROCESS without USING EXTERNAL FUNCTION doesn't allow WITH block\n"); - - ExpectFailWithError("PROCESS plato.Input USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'jhhjfh88134d')" - " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>" - " ASSUME ORDER BY key", - "<main>:1:129: Error: PROCESS with USING EXTERNAL FUNCTION doesn't allow ASSUME block\n"); - - ExpectFailWithError("PROCESS plato.Input USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo', 'bar', 'baz')", - "<main>:1:15: Error: EXTERNAL FUNCTION requires from 2 to 3 arguments, but got: 4\n"); +Y_UNIT_TEST(ValidUseFunctions) { + UNIT_ASSERT(SqlToYql( + "PROCESS plato.Input" + " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo', <|a: 123, b: a + 641|>)" + " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>," + " CONCURRENCY=3, OPTIMIZE_FOR='CALLS'") + .IsOk()); + + // use CALLS without quotes, as keyword + UNIT_ASSERT(SqlToYql( + "PROCESS plato.Input" + " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo')" + " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>," + " OPTIMIZE_FOR=CALLS") + .IsOk()); + + UNIT_ASSERT(SqlToYql( + "PROCESS plato.Input" + " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo', TableRow())" + " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>," + " CONCURRENCY=3") + .IsOk()); + + UNIT_ASSERT(SqlToYql( + "PROCESS plato.Input" + " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo')" + " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>," + " CONCURRENCY=3, BATCH_SIZE=1000000, CONNECTION='yc-folder34fse-con'," + " INIT=[0, 900]") + .IsOk()); + + UNIT_ASSERT(SqlToYql( + "PROCESS plato.Input" + " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'bar', TableRow())" + " WITH UNKNOWN_PARAM_1='837747712', UNKNOWN_PARAM_2=Tuple<Uint16, Utf8>," + " INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>") + .IsOk()); +} - ExpectFailWithError("PROCESS plato.Input\n" - " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo', <|field_1: a1, field_b: b1|>)\n" - " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>,\n" - " CONCURRENCY=3, BATCH_SIZE=1000000, CONNECTION='yc-folder34fse-con',\n" - " CONCURRENCY=5, INPUT_TYPE=Struct<b:Bool>,\n" - " INIT=[0, 900]\n", - "<main>:5:2: Error: WITH \"CONCURRENCY\" clause should be specified only once\n" - "<main>:5:17: Error: WITH \"INPUT_TYPE\" clause should be specified only once\n"); - } +Y_UNIT_TEST(InValidUseFunctions) { + ExpectFailWithError("PROCESS plato.Input USING some::udf(*) WITH INPUT_TYPE=Struct<a:Int32>", + "<main>:1:33: Error: PROCESS without USING EXTERNAL FUNCTION doesn't allow WITH block\n"); + + ExpectFailWithError("PROCESS plato.Input USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'jhhjfh88134d')" + " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>" + " ASSUME ORDER BY key", + "<main>:1:129: Error: PROCESS with USING EXTERNAL FUNCTION doesn't allow ASSUME block\n"); + + ExpectFailWithError("PROCESS plato.Input USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo', 'bar', 'baz')", + "<main>:1:15: Error: EXTERNAL FUNCTION requires from 2 to 3 arguments, but got: 4\n"); + + ExpectFailWithError("PROCESS plato.Input\n" + " USING EXTERNAL FUNCTION('YANDEX-CLOUD', 'foo', <|field_1: a1, field_b: b1|>)\n" + " WITH INPUT_TYPE=Struct<a:Int32>, OUTPUT_TYPE=Struct<b:Int32>,\n" + " CONCURRENCY=3, BATCH_SIZE=1000000, CONNECTION='yc-folder34fse-con',\n" + " CONCURRENCY=5, INPUT_TYPE=Struct<b:Bool>,\n" + " INIT=[0, 900]\n", + "<main>:5:2: Error: WITH \"CONCURRENCY\" clause should be specified only once\n" + "<main>:5:17: Error: WITH \"INPUT_TYPE\" clause should be specified only once\n"); } +} // Y_UNIT_TEST_SUITE(ExternalFunction) Y_UNIT_TEST_SUITE(SqlToYQLErrors) { - Y_UNIT_TEST(UdfSyntaxSugarMissingCall) { - auto req = "SELECT Udf(DateTime::FromString, \"foo\" as RunConfig);"; - auto res = SqlToYql(req); - TString a1 = Err2Str(res); - TString a2("<main>:1:8: Error: Abstract Udf Node can't be used as a part of expression.\n"); - UNIT_ASSERT_NO_DIFF(a1, a2); - } +Y_UNIT_TEST(UdfSyntaxSugarMissingCall) { + auto req = "SELECT Udf(DateTime::FromString, \"foo\" as RunConfig);"; + auto res = SqlToYql(req); + TString a1 = Err2Str(res); + TString a2("<main>:1:8: Error: Abstract Udf Node can't be used as a part of expression.\n"); + UNIT_ASSERT_NO_DIFF(a1, a2); +} - Y_UNIT_TEST(UdfSyntaxSugarIsNotCallable) { - auto req = "SELECT Udf(123, \"foo\" as RunConfig);"; - auto res = SqlToYql(req); - TString a1 = Err2Str(res); - TString a2("<main>:1:8: Error: Udf: first argument must be a callable, like Foo::Bar\n"); - UNIT_ASSERT_NO_DIFF(a1, a2); - } +Y_UNIT_TEST(UdfSyntaxSugarIsNotCallable) { + auto req = "SELECT Udf(123, \"foo\" as RunConfig);"; + auto res = SqlToYql(req); + TString a1 = Err2Str(res); + TString a2("<main>:1:8: Error: Udf: first argument must be a callable, like Foo::Bar\n"); + UNIT_ASSERT_NO_DIFF(a1, a2); +} - Y_UNIT_TEST(UdfSyntaxSugarNoArgs) { - auto req = "SELECT Udf()();"; - auto res = SqlToYql(req); - TString a1 = Err2Str(res); - TString a2("<main>:1:8: Error: Udf: expected at least one argument\n"); - UNIT_ASSERT_NO_DIFF(a1, a2); - } +Y_UNIT_TEST(UdfSyntaxSugarNoArgs) { + auto req = "SELECT Udf()();"; + auto res = SqlToYql(req); + TString a1 = Err2Str(res); + TString a2("<main>:1:8: Error: Udf: expected at least one argument\n"); + UNIT_ASSERT_NO_DIFF(a1, a2); +} - Y_UNIT_TEST(StrayUTF8) { - /// 'c' in plato is russian here - NYql::TAstParseResult res = SqlToYql("select * from сedar.Input"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(StrayUTF8) { + /// 'c' in plato is russian here + NYql::TAstParseResult res = SqlToYql("select * from сedar.Input"); + UNIT_ASSERT(!res.Root); - TString a1 = Err2Str(res); + TString a1 = Err2Str(res); #if ANTLR_VER == 3 - TString a2(R"foo(<main>:1:14: Error: Unexpected character 'с' (Unicode character <1089>) : cannot match to any predicted input... + TString a2(R"foo(<main>:1:14: Error: Unexpected character 'с' (Unicode character <1089>) : cannot match to any predicted input... <main>:1:15: Error: Unexpected character : cannot match to any predicted input... )foo"); #else - TString a2(R"foo(<main>:1:14: Error: token recognition error at: 'с' + TString a2(R"foo(<main>:1:14: Error: token recognition error at: 'с' )foo"); #endif - UNIT_ASSERT_NO_DIFF(a1, a2); - } + UNIT_ASSERT_NO_DIFF(a1, a2); +} - Y_UNIT_TEST(IvalidStringLiteralWithEscapedBackslash) { - NYql::TAstParseResult res1 = SqlToYql(R"foo($bar = 'a\\'b';)foo"); - NYql::TAstParseResult res2 = SqlToYql(R"foo($bar = "a\\"b";)foo"); - UNIT_ASSERT(!res1.Root); - UNIT_ASSERT(!res2.Root); +Y_UNIT_TEST(IvalidStringLiteralWithEscapedBackslash) { + NYql::TAstParseResult res1 = SqlToYql(R"foo($bar = 'a\\'b';)foo"); + NYql::TAstParseResult res2 = SqlToYql(R"foo($bar = "a\\"b";)foo"); + UNIT_ASSERT(!res1.Root); + UNIT_ASSERT(!res2.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res1), "<main>:1:15: Error: Unexpected character : syntax error...\n\n"); - UNIT_ASSERT_NO_DIFF(Err2Str(res2), "<main>:1:15: Error: Unexpected character : syntax error...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res1), "<main>:1:15: Error: Unexpected character : syntax error...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res2), "<main>:1:15: Error: Unexpected character : syntax error...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res1), "<main>:1:13: Error: token recognition error at: '';'\n"); - UNIT_ASSERT_NO_DIFF(Err2Str(res2), "<main>:1:13: Error: token recognition error at: '\";'\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res1), "<main>:1:13: Error: token recognition error at: '';'\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res2), "<main>:1:13: Error: token recognition error at: '\";'\n"); #endif - } +} - Y_UNIT_TEST(InvalidHexInStringLiteral) { - NYql::TAstParseResult res = SqlToYql("select \"foo\\x1\\xfe\""); - UNIT_ASSERT(!res.Root); - TString a1 = Err2Str(res); - TString a2 = "<main>:1:15: Error: Failed to parse string literal: Invalid hexadecimal value\n"; +Y_UNIT_TEST(InvalidHexInStringLiteral) { + NYql::TAstParseResult res = SqlToYql("select \"foo\\x1\\xfe\""); + UNIT_ASSERT(!res.Root); + TString a1 = Err2Str(res); + TString a2 = "<main>:1:15: Error: Failed to parse string literal: Invalid hexadecimal value\n"; - UNIT_ASSERT_NO_DIFF(a1, a2); - } + UNIT_ASSERT_NO_DIFF(a1, a2); +} - Y_UNIT_TEST(InvalidOctalInMultilineStringLiteral) { - NYql::TAstParseResult res = SqlToYql("select \"foo\n" - "bar\n" - "\\01\""); - UNIT_ASSERT(!res.Root); - TString a1 = Err2Str(res); - TString a2 = "<main>:3:4: Error: Failed to parse string literal: Invalid octal value\n"; +Y_UNIT_TEST(InvalidOctalInMultilineStringLiteral) { + NYql::TAstParseResult res = SqlToYql("select \"foo\n" + "bar\n" + "\\01\""); + UNIT_ASSERT(!res.Root); + TString a1 = Err2Str(res); + TString a2 = "<main>:3:4: Error: Failed to parse string literal: Invalid octal value\n"; - UNIT_ASSERT_NO_DIFF(a1, a2); - } + UNIT_ASSERT_NO_DIFF(a1, a2); +} - Y_UNIT_TEST(InvalidDoubleAtString) { - NYql::TAstParseResult res = SqlToYql("select @@@@@@"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(InvalidDoubleAtString) { + NYql::TAstParseResult res = SqlToYql("select @@@@@@"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:13: Error: Unexpected character : syntax error...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:13: Error: Unexpected character : syntax error...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: extraneous input '@' expecting {<EOF>, ';'}\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: extraneous input '@' expecting {<EOF>, ';'}\n"); #endif - } +} - Y_UNIT_TEST(InvalidDoubleAtStringWhichWasAcceptedEarlier) { - NYql::TAstParseResult res = SqlToYql("SELECT @@foo@@ @ @@bar@@"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(InvalidDoubleAtStringWhichWasAcceptedEarlier) { + NYql::TAstParseResult res = SqlToYql("SELECT @@foo@@ @ @@bar@@"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:7: Error: Unexpected token '@@foo@@' : cannot match to any predicted input...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:7: Error: Unexpected token '@@foo@@' : cannot match to any predicted input...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:15: Error: mismatched input '@' expecting {<EOF>, ';'}\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:15: Error: mismatched input '@' expecting {<EOF>, ';'}\n"); #endif - } +} - Y_UNIT_TEST(InvalidStringFromTable) { - NYql::TAstParseResult res = SqlToYql("select \"FOO\"\"BAR from plato.foo"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(InvalidStringFromTable) { + NYql::TAstParseResult res = SqlToYql("select \"FOO\"\"BAR from plato.foo"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:31: Error: Unexpected character : syntax error...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:31: Error: Unexpected character : syntax error...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: token recognition error at: '\"BAR from plato.foo'\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: token recognition error at: '\"BAR from plato.foo'\n"); #endif - } +} - Y_UNIT_TEST(InvalidDoubleAtStringFromTable) { - NYql::TAstParseResult res = SqlToYql("select @@@@@@ from plato.foo"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(InvalidDoubleAtStringFromTable) { + NYql::TAstParseResult res = SqlToYql("select @@@@@@ from plato.foo"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:28: Error: Unexpected character : syntax error...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:28: Error: Unexpected character : syntax error...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: mismatched input '@' expecting {<EOF>, ';'}\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: mismatched input '@' expecting {<EOF>, ';'}\n"); #endif - } +} - Y_UNIT_TEST(SelectInvalidSyntax) { - NYql::TAstParseResult res = SqlToYql("select 1 form Wat"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(SelectInvalidSyntax) { + NYql::TAstParseResult res = SqlToYql("select 1 form Wat"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:14: Error: Unexpected token 'Wat' : cannot match to any predicted input...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:14: Error: Unexpected token 'Wat' : cannot match to any predicted input...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:14: Error: extraneous input 'Wat' expecting {<EOF>, ';'}\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:14: Error: extraneous input 'Wat' expecting {<EOF>, ';'}\n"); #endif - } +} - Y_UNIT_TEST(SelectNoCluster) { - NYql::TAstParseResult res = SqlToYql("select foo from bar"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: No cluster name given and no default cluster is selected\n"); - } +Y_UNIT_TEST(SelectNoCluster) { + NYql::TAstParseResult res = SqlToYql("select foo from bar"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: No cluster name given and no default cluster is selected\n"); +} - Y_UNIT_TEST(SelectDuplicateColumns) { - NYql::TAstParseResult res = SqlToYql("select a, a from plato.Input"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:11: Error: Unable to use duplicate column names. Collision in name: a\n"); - } +Y_UNIT_TEST(SelectDuplicateColumns) { + NYql::TAstParseResult res = SqlToYql("select a, a from plato.Input"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:11: Error: Unable to use duplicate column names. Collision in name: a\n"); +} - Y_UNIT_TEST(SelectDuplicateLabels) { - NYql::TAstParseResult res = SqlToYql("select a as foo, b as foo from plato.Input"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:18: Error: Unable to use duplicate column names. Collision in name: foo\n"); - } +Y_UNIT_TEST(SelectDuplicateLabels) { + NYql::TAstParseResult res = SqlToYql("select a as foo, b as foo from plato.Input"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:18: Error: Unable to use duplicate column names. Collision in name: foo\n"); +} - Y_UNIT_TEST(SelectCaseWithoutThen) { - NYql::TAstParseResult res = SqlToYql("select case when true 1;"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(SelectCaseWithoutThen) { + NYql::TAstParseResult res = SqlToYql("select case when true 1;"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), - "<main>:1:22: Error: Unexpected token absence : Missing THEN \n\n" - "<main>:1:23: Error: Unexpected token absence : Missing END \n\n" - ); + UNIT_ASSERT_NO_DIFF(Err2Str(res), + "<main>:1:22: Error: Unexpected token absence : Missing THEN \n\n" + "<main>:1:23: Error: Unexpected token absence : Missing END \n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), - "<main>:1:22: Error: missing THEN at \'1\'\n" - "<main>:1:23: Error: extraneous input \';\' expecting {ELSE, END, WHEN}\n" - ); + UNIT_ASSERT_NO_DIFF(Err2Str(res), + "<main>:1:22: Error: missing THEN at \'1\'\n" + "<main>:1:23: Error: extraneous input \';\' expecting {ELSE, END, WHEN}\n"); #endif - } +} - Y_UNIT_TEST(SelectComplexCaseWithoutThen) { - NYql::TAstParseResult res = SqlToYql( - "SELECT *\n" - "FROM plato.Input AS a\n" - "WHERE CASE WHEN a.key = \"foo\" a.subkey ELSE a.value END\n" - ); +Y_UNIT_TEST(SelectComplexCaseWithoutThen) { + NYql::TAstParseResult res = SqlToYql( + "SELECT *\n" + "FROM plato.Input AS a\n" + "WHERE CASE WHEN a.key = \"foo\" a.subkey ELSE a.value END\n"); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:30: Error: Unexpected token absence : Missing THEN \n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:30: Error: Unexpected token absence : Missing THEN \n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:30: Error: missing THEN at 'a'\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:30: Error: missing THEN at 'a'\n"); #endif - } +} - Y_UNIT_TEST(SelectCaseWithoutEnd) { - NYql::TAstParseResult res = SqlToYql("select case a when b then c end from plato.Input"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: ELSE is required\n"); - } +Y_UNIT_TEST(SelectCaseWithoutEnd) { + NYql::TAstParseResult res = SqlToYql("select case a when b then c end from plato.Input"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: ELSE is required\n"); +} - Y_UNIT_TEST(SelectWithBadAggregationNoInput) { - NYql::TAstParseResult res = SqlToYql("select a, Min(b), c"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), - "<main>:1:1: Error: Column references are not allowed without FROM\n" - "<main>:1:8: Error: Column reference 'a'\n" - "<main>:1:1: Error: Column references are not allowed without FROM\n" - "<main>:1:15: Error: Column reference 'b'\n" - "<main>:1:1: Error: Column references are not allowed without FROM\n" - "<main>:1:19: Error: Column reference 'c'\n" - ); - } +Y_UNIT_TEST(SelectWithBadAggregationNoInput) { + NYql::TAstParseResult res = SqlToYql("select a, Min(b), c"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), + "<main>:1:1: Error: Column references are not allowed without FROM\n" + "<main>:1:8: Error: Column reference 'a'\n" + "<main>:1:1: Error: Column references are not allowed without FROM\n" + "<main>:1:15: Error: Column reference 'b'\n" + "<main>:1:1: Error: Column references are not allowed without FROM\n" + "<main>:1:19: Error: Column reference 'c'\n"); +} - Y_UNIT_TEST(SelectWithBadAggregation) { - ExpectFailWithError("select count(*), 1 + key from plato.Input", - "<main>:1:22: Error: Column `key` must either be a key column in GROUP BY or it should be used in aggregation function\n"); - } +Y_UNIT_TEST(SelectWithBadAggregation) { + ExpectFailWithError("select count(*), 1 + key from plato.Input", + "<main>:1:22: Error: Column `key` must either be a key column in GROUP BY or it should be used in aggregation function\n"); +} - Y_UNIT_TEST(SelectWithBadAggregatedTerms) { - ExpectFailWithError("select key, 2 * subkey from plato.Input group by key", - "<main>:1:17: Error: Column `subkey` must either be a key column in GROUP BY or it should be used in aggregation function\n"); - } +Y_UNIT_TEST(SelectWithBadAggregatedTerms) { + ExpectFailWithError("select key, 2 * subkey from plato.Input group by key", + "<main>:1:17: Error: Column `subkey` must either be a key column in GROUP BY or it should be used in aggregation function\n"); +} - Y_UNIT_TEST(SelectDistinctWithBadAggregation) { - ExpectFailWithError("select distinct count(*), 1 + key from plato.Input", - "<main>:1:31: Error: Column `key` must either be a key column in GROUP BY or it should be used in aggregation function\n"); - ExpectFailWithError("select distinct key, 2 * subkey from plato.Input group by key", - "<main>:1:26: Error: Column `subkey` must either be a key column in GROUP BY or it should be used in aggregation function\n"); - } +Y_UNIT_TEST(SelectDistinctWithBadAggregation) { + ExpectFailWithError("select distinct count(*), 1 + key from plato.Input", + "<main>:1:31: Error: Column `key` must either be a key column in GROUP BY or it should be used in aggregation function\n"); + ExpectFailWithError("select distinct key, 2 * subkey from plato.Input group by key", + "<main>:1:26: Error: Column `subkey` must either be a key column in GROUP BY or it should be used in aggregation function\n"); +} - Y_UNIT_TEST(SelectWithBadAggregationInHaving) { - ExpectFailWithError("select key from plato.Input group by key\n" - "having \"f\" || value == \"foo\"", - "<main>:2:15: Error: Column `value` must either be a key column in GROUP BY or it should be used in aggregation function\n"); - } +Y_UNIT_TEST(SelectWithBadAggregationInHaving) { + ExpectFailWithError("select key from plato.Input group by key\n" + "having \"f\" || value == \"foo\"", + "<main>:2:15: Error: Column `value` must either be a key column in GROUP BY or it should be used in aggregation function\n"); +} - Y_UNIT_TEST(JoinWithNonAggregatedColumnInProjection) { - ExpectFailWithError("select a.key, 1 + b.subkey\n" - "from plato.Input1 as a join plato.Input2 as b using(key)\n" - "group by a.key;", - "<main>:1:19: Error: Column `b.subkey` must either be a key column in GROUP BY or it should be used in aggregation function\n"); +Y_UNIT_TEST(JoinWithNonAggregatedColumnInProjection) { + ExpectFailWithError("select a.key, 1 + b.subkey\n" + "from plato.Input1 as a join plato.Input2 as b using(key)\n" + "group by a.key;", + "<main>:1:19: Error: Column `b.subkey` must either be a key column in GROUP BY or it should be used in aggregation function\n"); - ExpectFailWithError("select a.key, 1 + b.subkey.x\n" - "from plato.Input1 as a join plato.Input2 as b using(key)\n" - "group by a.key;", - "<main>:1:19: Error: Column must either be a key column in GROUP BY or it should be used in aggregation function\n"); - } + ExpectFailWithError("select a.key, 1 + b.subkey.x\n" + "from plato.Input1 as a join plato.Input2 as b using(key)\n" + "group by a.key;", + "<main>:1:19: Error: Column must either be a key column in GROUP BY or it should be used in aggregation function\n"); +} - Y_UNIT_TEST(SelectWithBadAggregatedTermsWithSources) { - ExpectFailWithError("select key, 1 + a.subkey\n" - "from plato.Input1 as a\n" - "group by a.key;", - "<main>:1:17: Error: Column `a.subkey` must either be a key column in GROUP BY or it should be used in aggregation function\n"); - ExpectFailWithError("select key, 1 + a.subkey.x\n" - "from plato.Input1 as a\n" - "group by a.key;", - "<main>:1:17: Error: Column must either be a key column in GROUP BY or it should be used in aggregation function\n"); - } +Y_UNIT_TEST(SelectWithBadAggregatedTermsWithSources) { + ExpectFailWithError("select key, 1 + a.subkey\n" + "from plato.Input1 as a\n" + "group by a.key;", + "<main>:1:17: Error: Column `a.subkey` must either be a key column in GROUP BY or it should be used in aggregation function\n"); + ExpectFailWithError("select key, 1 + a.subkey.x\n" + "from plato.Input1 as a\n" + "group by a.key;", + "<main>:1:17: Error: Column must either be a key column in GROUP BY or it should be used in aggregation function\n"); +} - Y_UNIT_TEST(WarnForAggregationBySelectAlias) { - NYql::TAstParseResult res = SqlToYql("select c + 1 as c from plato.Input\n" - "group by c"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), - "<main>:2:11: Warning: GROUP BY will aggregate by column `c` instead of aggregating by SELECT expression with same alias, code: 4532\n" - "<main>:1:10: Warning: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n"); +Y_UNIT_TEST(WarnForAggregationBySelectAlias) { + NYql::TAstParseResult res = SqlToYql("select c + 1 as c from plato.Input\n" + "group by c"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), + "<main>:2:11: Warning: GROUP BY will aggregate by column `c` instead of aggregating by SELECT expression with same alias, code: 4532\n" + "<main>:1:10: Warning: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n"); - res = SqlToYql("select c + 1 as c from plato.Input\n" - "group by Math::Floor(c + 2) as c;"); + res = SqlToYql("select c + 1 as c from plato.Input\n" + "group by Math::Floor(c + 2) as c;"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), - "<main>:2:22: Warning: GROUP BY will aggregate by column `c` instead of aggregating by SELECT expression with same alias, code: 4532\n" - "<main>:1:10: Warning: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n"); - } + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), + "<main>:2:22: Warning: GROUP BY will aggregate by column `c` instead of aggregating by SELECT expression with same alias, code: 4532\n" + "<main>:1:10: Warning: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n"); +} - Y_UNIT_TEST(WarnForAggregationBySelectAliasAsError) { - NSQLTranslation::TTranslationSettings settings; +Y_UNIT_TEST(WarnForAggregationBySelectAliasAsError) { + NSQLTranslation::TTranslationSettings settings; - NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( + NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( PRAGMA Warning("error", "*"); SELECT c + 1 AS c FROM plato.Input GROUP BY c; )sql", settings); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - UNIT_ASSERT_NO_DIFF(Err2Str(res), - "<main>:5:22: Error: GROUP BY will aggregate by column `c` instead of aggregating by SELECT expression with same alias, code: 4532\n" - "<main>:3:22: Error: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n"); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); + UNIT_ASSERT_NO_DIFF(Err2Str(res), + "<main>:5:22: Error: GROUP BY will aggregate by column `c` instead of aggregating by SELECT expression with same alias, code: 4532\n" + "<main>:3:22: Error: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n"); +} - Y_UNIT_TEST(WarnForAggregationBySelectAliasAsErrorStrict) { - NSQLTranslation::TTranslationSettings settings; - settings.Flags.emplace("StrictWarningAsError"); +Y_UNIT_TEST(WarnForAggregationBySelectAliasAsErrorStrict) { + NSQLTranslation::TTranslationSettings settings; + settings.Flags.emplace("StrictWarningAsError"); - NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( + NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( PRAGMA Warning("error", "*"); SELECT c + 1 AS c FROM plato.Input GROUP BY c; )sql", settings); - UNIT_ASSERT_C(!res.IsOk(), res.Issues.ToString()); - UNIT_ASSERT_NO_DIFF(Err2Str(res), - "<main>:5:22: Error: GROUP BY will aggregate by column `c` instead of aggregating by SELECT expression with same alias, code: 4532\n" - "<main>:3:22: Error: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n"); - } + UNIT_ASSERT_C(!res.IsOk(), res.Issues.ToString()); + UNIT_ASSERT_NO_DIFF(Err2Str(res), + "<main>:5:22: Error: GROUP BY will aggregate by column `c` instead of aggregating by SELECT expression with same alias, code: 4532\n" + "<main>:3:22: Error: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n"); +} - Y_UNIT_TEST(NoWarnForAggregationBySelectAliasWhenAggrFunctionsAreUsedInAlias) { - NYql::TAstParseResult res = SqlToYql("select\n" - " cast(avg(val) as int) as value,\n" - " value as key\n" - "from\n" - " plato.Input\n" - "group by value"); +Y_UNIT_TEST(NoWarnForAggregationBySelectAliasWhenAggrFunctionsAreUsedInAlias) { + NYql::TAstParseResult res = SqlToYql("select\n" + " cast(avg(val) as int) as value,\n" + " value as key\n" + "from\n" + " plato.Input\n" + "group by value"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT(res.Issues.Size() == 0); + UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Issues.Size() == 0); - res = SqlToYql("select\n" - " cast(avg(val) over w as int) as value,\n" - " value as key\n" - "from\n" - " plato.Input\n" - "group by value\n" - "window w as ()"); + res = SqlToYql("select\n" + " cast(avg(val) over w as int) as value,\n" + " value as key\n" + "from\n" + " plato.Input\n" + "group by value\n" + "window w as ()"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT(res.Issues.Size() == 0); - } + UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Issues.Size() == 0); +} - Y_UNIT_TEST(NoWarnForAggregationBySelectAliasWhenQualifiedNameIsUsed) { - NYql::TAstParseResult res = SqlToYql("select\n" - " Unwrap(a.key) as key\n" - "from plato.Input as a\n" - "join plato.Input2 as b using(k)\n" - "group by a.key;"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT(res.Issues.Size() == 0); +Y_UNIT_TEST(NoWarnForAggregationBySelectAliasWhenQualifiedNameIsUsed) { + NYql::TAstParseResult res = SqlToYql("select\n" + " Unwrap(a.key) as key\n" + "from plato.Input as a\n" + "join plato.Input2 as b using(k)\n" + "group by a.key;"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Issues.Size() == 0); - res = SqlToYql("select Unwrap(a.key) as key\n" - "from plato.Input as a\n" - "group by a.key;"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT(res.Issues.Size() == 0); - } + res = SqlToYql("select Unwrap(a.key) as key\n" + "from plato.Input as a\n" + "group by a.key;"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Issues.Size() == 0); +} - Y_UNIT_TEST(NoWarnForAggregationBySelectAliasWhenTrivialRenamingIsUsed) { - NYql::TAstParseResult res = SqlToYql("select a.key as key\n" - "from plato.Input as a\n" - "group by key;"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT(res.Issues.Size() == 0); +Y_UNIT_TEST(NoWarnForAggregationBySelectAliasWhenTrivialRenamingIsUsed) { + NYql::TAstParseResult res = SqlToYql("select a.key as key\n" + "from plato.Input as a\n" + "group by key;"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Issues.Size() == 0); - res = SqlToYql("select key as key\n" - "from plato.Input\n" - "group by key;"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT(res.Issues.Size() == 0); - } + res = SqlToYql("select key as key\n" + "from plato.Input\n" + "group by key;"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Issues.Size() == 0); +} - Y_UNIT_TEST(ErrorByAggregatingByExpressionWithSameExpressionInSelect) { - ExpectFailWithError("select k * 2 from plato.Input group by k * 2", - "<main>:1:8: Error: Column `k` must either be a key column in GROUP BY or it should be used in aggregation function\n"); - } +Y_UNIT_TEST(ErrorByAggregatingByExpressionWithSameExpressionInSelect) { + ExpectFailWithError("select k * 2 from plato.Input group by k * 2", + "<main>:1:8: Error: Column `k` must either be a key column in GROUP BY or it should be used in aggregation function\n"); +} - Y_UNIT_TEST(ErrorForAggregationBySelectAlias) { - ExpectFailWithError("select key, Math::Floor(1.1 + a.subkey) as foo\n" - "from plato.Input as a\n" - "group by a.key, foo;", - "<main>:3:17: Warning: GROUP BY will aggregate by column `foo` instead of aggregating by SELECT expression with same alias, code: 4532\n" - "<main>:1:19: Warning: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n" - "<main>:1:31: Error: Column `a.subkey` must either be a key column in GROUP BY or it should be used in aggregation function\n"); - - ExpectFailWithError("select c + 1 as c from plato.Input\n" - "group by Math::Floor(c + 2);", - "<main>:2:22: Warning: GROUP BY will aggregate by column `c` instead of aggregating by SELECT expression with same alias, code: 4532\n" - "<main>:1:10: Warning: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n" - "<main>:1:8: Error: Column `c` must either be a key column in GROUP BY or it should be used in aggregation function\n"); - } +Y_UNIT_TEST(ErrorForAggregationBySelectAlias) { + ExpectFailWithError("select key, Math::Floor(1.1 + a.subkey) as foo\n" + "from plato.Input as a\n" + "group by a.key, foo;", + "<main>:3:17: Warning: GROUP BY will aggregate by column `foo` instead of aggregating by SELECT expression with same alias, code: 4532\n" + "<main>:1:19: Warning: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n" + "<main>:1:31: Error: Column `a.subkey` must either be a key column in GROUP BY or it should be used in aggregation function\n"); + + ExpectFailWithError("select c + 1 as c from plato.Input\n" + "group by Math::Floor(c + 2);", + "<main>:2:22: Warning: GROUP BY will aggregate by column `c` instead of aggregating by SELECT expression with same alias, code: 4532\n" + "<main>:1:10: Warning: You should probably use alias in GROUP BY instead of using it here. Please consult documentation for more details, code: 4532\n" + "<main>:1:8: Error: Column `c` must either be a key column in GROUP BY or it should be used in aggregation function\n"); +} - Y_UNIT_TEST(SelectWithDuplicateGroupingColumns) { - NYql::TAstParseResult res = SqlToYql("select c from plato.Input group by c, c"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Duplicate grouping column: c\n"); - } +Y_UNIT_TEST(SelectWithDuplicateGroupingColumns) { + NYql::TAstParseResult res = SqlToYql("select c from plato.Input group by c, c"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Duplicate grouping column: c\n"); +} - Y_UNIT_TEST(SelectWithBadAggregationInGrouping) { - NYql::TAstParseResult res = SqlToYql("select a, Min(b), c group by c"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Column references are not allowed without FROM\n" - "<main>:1:30: Error: Column reference 'c'\n"); - } +Y_UNIT_TEST(SelectWithBadAggregationInGrouping) { + NYql::TAstParseResult res = SqlToYql("select a, Min(b), c group by c"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Column references are not allowed without FROM\n" + "<main>:1:30: Error: Column reference 'c'\n"); +} - Y_UNIT_TEST(SelectWithOpOnBadAggregation) { - ExpectFailWithError("select 1 + a + Min(b) from plato.Input", - "<main>:1:12: Error: Column `a` must either be a key column in GROUP BY or it should be used in aggregation function\n"); - } +Y_UNIT_TEST(SelectWithOpOnBadAggregation) { + ExpectFailWithError("select 1 + a + Min(b) from plato.Input", + "<main>:1:12: Error: Column `a` must either be a key column in GROUP BY or it should be used in aggregation function\n"); +} - Y_UNIT_TEST(SelectOrderByConstantNum) { - NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by 1"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:36: Error: Unable to ORDER BY constant expression\n"); - } +Y_UNIT_TEST(SelectOrderByConstantNum) { + NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by 1"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:36: Error: Unable to ORDER BY constant expression\n"); +} - Y_UNIT_TEST(SelectOrderByConstantExpr) { - NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by 1 * 42"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:38: Error: Unable to ORDER BY constant expression\n"); - } +Y_UNIT_TEST(SelectOrderByConstantExpr) { + NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by 1 * 42"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:38: Error: Unable to ORDER BY constant expression\n"); +} - Y_UNIT_TEST(SelectOrderByConstantString) { - NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by \"nest\""); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:36: Error: Unable to ORDER BY constant expression\n"); - } +Y_UNIT_TEST(SelectOrderByConstantString) { + NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by \"nest\""); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:36: Error: Unable to ORDER BY constant expression\n"); +} - Y_UNIT_TEST(SelectOrderByAggregated) { - NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by min(a)"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:36: Error: Unable to ORDER BY aggregated values\n"); - } +Y_UNIT_TEST(SelectOrderByAggregated) { + NYql::TAstParseResult res = SqlToYql("select a from plato.Input order by min(a)"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:36: Error: Unable to ORDER BY aggregated values\n"); +} - Y_UNIT_TEST(ErrorInOrderByExpresison) { - NYql::TAstParseResult res = SqlToYql("select key, value from plato.Input order by (key as zey)"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:45: Error: You should use in ORDER BY column name, qualified field, callable function or expression\n"); - } +Y_UNIT_TEST(ErrorInOrderByExpresison) { + NYql::TAstParseResult res = SqlToYql("select key, value from plato.Input order by (key as zey)"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:45: Error: You should use in ORDER BY column name, qualified field, callable function or expression\n"); +} - Y_UNIT_TEST(ErrorsInOrderByWhenColumnIsMissingInProjection) { - ExpectFailWithError("select subkey from (select 1 as subkey) order by key", "<main>:1:50: Error: Column key is not in source column set\n"); - ExpectFailWithError("select subkey from plato.Input as a order by x.key", "<main>:1:46: Error: Unknown correlation name: x\n"); - ExpectFailWithError("select distinct a, b from plato.Input order by c", "<main>:1:48: Error: Column c is not in source column set. Did you mean a?\n"); - ExpectFailWithError("select count(*) as a from plato.Input order by c", "<main>:1:48: Error: Column c is not in source column set. Did you mean a?\n"); - ExpectFailWithError("select count(*) as a, b, from plato.Input group by b order by c", "<main>:1:63: Error: Column c is not in source column set. Did you mean a?\n"); - UNIT_ASSERT(SqlToYql("select a, b from plato.Input order by c").IsOk()); - } +Y_UNIT_TEST(ErrorsInOrderByWhenColumnIsMissingInProjection) { + ExpectFailWithError("select subkey from (select 1 as subkey) order by key", "<main>:1:50: Error: Column key is not in source column set\n"); + ExpectFailWithError("select subkey from plato.Input as a order by x.key", "<main>:1:46: Error: Unknown correlation name: x\n"); + ExpectFailWithError("select distinct a, b from plato.Input order by c", "<main>:1:48: Error: Column c is not in source column set. Did you mean a?\n"); + ExpectFailWithError("select count(*) as a from plato.Input order by c", "<main>:1:48: Error: Column c is not in source column set. Did you mean a?\n"); + ExpectFailWithError("select count(*) as a, b, from plato.Input group by b order by c", "<main>:1:63: Error: Column c is not in source column set. Did you mean a?\n"); + UNIT_ASSERT(SqlToYql("select a, b from plato.Input order by c").IsOk()); +} - Y_UNIT_TEST(SelectAggregatedWhere) { - NYql::TAstParseResult res = SqlToYql("select * from plato.Input where count(key)"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:33: Error: Can not use aggregated values in filtering\n"); - } +Y_UNIT_TEST(SelectAggregatedWhere) { + NYql::TAstParseResult res = SqlToYql("select * from plato.Input where count(key)"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:33: Error: Can not use aggregated values in filtering\n"); +} - Y_UNIT_TEST(DoubleFrom) { - NYql::TAstParseResult res = SqlToYql("from plato.Input select * from plato.Input"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:27: Error: Only one FROM clause is allowed\n"); - } +Y_UNIT_TEST(DoubleFrom) { + NYql::TAstParseResult res = SqlToYql("from plato.Input select * from plato.Input"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:27: Error: Only one FROM clause is allowed\n"); +} - Y_UNIT_TEST(SelectJoinMissingCorrName) { - NYql::TAstParseResult res = SqlToYql("select * from plato.Input1 as a join plato.Input2 as b on a.key == key"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:65: Error: JOIN: column requires correlation name\n"); - } +Y_UNIT_TEST(SelectJoinMissingCorrName) { + NYql::TAstParseResult res = SqlToYql("select * from plato.Input1 as a join plato.Input2 as b on a.key == key"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:65: Error: JOIN: column requires correlation name\n"); +} - Y_UNIT_TEST(SelectJoinMissingCorrName1) { - NYql::TAstParseResult res = SqlToYql( - "use plato;\n" - "$foo = select * from Input1;\n" - "select * from Input2 join $foo USING(key);\n" - ); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:27: Error: JOIN: missing correlation name for source\n"); - } +Y_UNIT_TEST(SelectJoinMissingCorrName1) { + NYql::TAstParseResult res = SqlToYql( + "use plato;\n" + "$foo = select * from Input1;\n" + "select * from Input2 join $foo USING(key);\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:27: Error: JOIN: missing correlation name for source\n"); +} - Y_UNIT_TEST(SelectJoinMissingCorrName2) { - NYql::TAstParseResult res = SqlToYql( - "use plato;\n" - "$foo = select * from Input1;\n" - "select * from Input2 cross join $foo;\n" - ); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:33: Error: JOIN: missing correlation name for source\n"); - } +Y_UNIT_TEST(SelectJoinMissingCorrName2) { + NYql::TAstParseResult res = SqlToYql( + "use plato;\n" + "$foo = select * from Input1;\n" + "select * from Input2 cross join $foo;\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:33: Error: JOIN: missing correlation name for source\n"); +} - Y_UNIT_TEST(SelectJoinEmptyCorrNames) { - NYql::TAstParseResult res = SqlToYql( - "$left = (SELECT * FROM plato.Input1 LIMIT 2);\n" - "$right = (SELECT * FROM plato.Input2 LIMIT 2);\n" - "SELECT * FROM $left FULL JOIN $right USING (key);\n" - ); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:45: Error: At least one correlation name is required in join\n"); - } +Y_UNIT_TEST(SelectJoinEmptyCorrNames) { + NYql::TAstParseResult res = SqlToYql( + "$left = (SELECT * FROM plato.Input1 LIMIT 2);\n" + "$right = (SELECT * FROM plato.Input2 LIMIT 2);\n" + "SELECT * FROM $left FULL JOIN $right USING (key);\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:45: Error: At least one correlation name is required in join\n"); +} - Y_UNIT_TEST(SelectJoinSameCorrNames) { - NYql::TAstParseResult res = SqlToYql("SELECT Input.key FROM plato.Input JOIN plato.Input1 ON Input.key == Input.subkey\n"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:66: Error: JOIN: different correlation names are required for joined tables\n"); - } +Y_UNIT_TEST(SelectJoinSameCorrNames) { + NYql::TAstParseResult res = SqlToYql("SELECT Input.key FROM plato.Input JOIN plato.Input1 ON Input.key == Input.subkey\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:66: Error: JOIN: different correlation names are required for joined tables\n"); +} - Y_UNIT_TEST(SelectJoinConstPredicateArg) { - NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input1 as A JOIN plato.Input2 as B ON A.key == B.key AND A.subkey == \"wtf\"\n"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:87: Error: JOIN: each equality predicate argument must depend on exactly one JOIN input\n"); - } +Y_UNIT_TEST(SelectJoinConstPredicateArg) { + NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input1 as A JOIN plato.Input2 as B ON A.key == B.key AND A.subkey == \"wtf\"\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:87: Error: JOIN: each equality predicate argument must depend on exactly one JOIN input\n"); +} - Y_UNIT_TEST(SelectJoinNonEqualityPredicate) { - NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input1 as A JOIN plato.Input2 as B ON A.key == B.key AND A.subkey > B.subkey\n"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:87: Error: JOIN ON expression must be a conjunction of equality predicates\n"); - } +Y_UNIT_TEST(SelectJoinNonEqualityPredicate) { + NYql::TAstParseResult res = SqlToYql("SELECT * FROM plato.Input1 as A JOIN plato.Input2 as B ON A.key == B.key AND A.subkey > B.subkey\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:87: Error: JOIN ON expression must be a conjunction of equality predicates\n"); +} - Y_UNIT_TEST(SelectEquiJoinCorrNameOutOfScope) { - NYql::TAstParseResult res = SqlToYql( - "PRAGMA equijoin;\n" - "SELECT * FROM plato.A JOIN plato.B ON A.key == C.key JOIN plato.C ON A.subkey == C.subkey;\n" - ); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:45: Error: JOIN: can not use source: C in equality predicate, it is out of current join scope\n"); - } +Y_UNIT_TEST(SelectEquiJoinCorrNameOutOfScope) { + NYql::TAstParseResult res = SqlToYql( + "PRAGMA equijoin;\n" + "SELECT * FROM plato.A JOIN plato.B ON A.key == C.key JOIN plato.C ON A.subkey == C.subkey;\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:45: Error: JOIN: can not use source: C in equality predicate, it is out of current join scope\n"); +} - Y_UNIT_TEST(SelectEquiJoinNoRightSource) { - NYql::TAstParseResult res = SqlToYql( - "PRAGMA equijoin;\n" - "SELECT * FROM plato.A JOIN plato.B ON A.key == B.key JOIN plato.C ON A.subkey == B.subkey;\n" - ); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:79: Error: JOIN ON equality predicate must have one of its arguments from the rightmost source\n"); - } +Y_UNIT_TEST(SelectEquiJoinNoRightSource) { + NYql::TAstParseResult res = SqlToYql( + "PRAGMA equijoin;\n" + "SELECT * FROM plato.A JOIN plato.B ON A.key == B.key JOIN plato.C ON A.subkey == B.subkey;\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:79: Error: JOIN ON equality predicate must have one of its arguments from the rightmost source\n"); +} - Y_UNIT_TEST(SelectEquiJoinOuterWithoutType) { - NYql::TAstParseResult res = SqlToYql( - "SELECT * FROM plato.A Outer JOIN plato.B ON A.key == B.key;\n" - ); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:23: Error: Invalid join type: OUTER JOIN. OUTER keyword is optional and can only be used after LEFT, RIGHT or FULL\n"); - } +Y_UNIT_TEST(SelectEquiJoinOuterWithoutType) { + NYql::TAstParseResult res = SqlToYql( + "SELECT * FROM plato.A Outer JOIN plato.B ON A.key == B.key;\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:23: Error: Invalid join type: OUTER JOIN. OUTER keyword is optional and can only be used after LEFT, RIGHT or FULL\n"); +} - Y_UNIT_TEST(SelectEquiJoinOuterWithWrongType) { - NYql::TAstParseResult res = SqlToYql( - "SELECT * FROM plato.A LEFT semi OUTER JOIN plato.B ON A.key == B.key;\n" - ); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:33: Error: Invalid join type: LEFT SEMI OUTER JOIN. OUTER keyword is optional and can only be used after LEFT, RIGHT or FULL\n"); - } +Y_UNIT_TEST(SelectEquiJoinOuterWithWrongType) { + NYql::TAstParseResult res = SqlToYql( + "SELECT * FROM plato.A LEFT semi OUTER JOIN plato.B ON A.key == B.key;\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:33: Error: Invalid join type: LEFT SEMI OUTER JOIN. OUTER keyword is optional and can only be used after LEFT, RIGHT or FULL\n"); +} - Y_UNIT_TEST(InsertNoCluster) { - NYql::TAstParseResult res = SqlToYql("insert into Output (foo) values (1)"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: No cluster name given and no default cluster is selected\n"); - } +Y_UNIT_TEST(InsertNoCluster) { + NYql::TAstParseResult res = SqlToYql("insert into Output (foo) values (1)"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: No cluster name given and no default cluster is selected\n"); +} - Y_UNIT_TEST(InsertValuesNoLabels) { - NYql::TAstParseResult res = SqlToYql("insert into plato.Output values (1)"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: INSERT INTO ... VALUES requires specification of table columns\n"); - } +Y_UNIT_TEST(InsertValuesNoLabels) { + NYql::TAstParseResult res = SqlToYql("insert into plato.Output values (1)"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: INSERT INTO ... VALUES requires specification of table columns\n"); +} - Y_UNIT_TEST(UpsertValuesNoLabelsKikimr) { - NYql::TAstParseResult res = SqlToYql("upsert into plato.Output values (1)", 10, TString(NYql::KikimrProviderName)); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: UPSERT INTO ... VALUES requires specification of table columns\n"); - } +Y_UNIT_TEST(UpsertValuesNoLabelsKikimr) { + NYql::TAstParseResult res = SqlToYql("upsert into plato.Output values (1)", 10, TString(NYql::KikimrProviderName)); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: UPSERT INTO ... VALUES requires specification of table columns\n"); +} - Y_UNIT_TEST(ReplaceValuesNoLabelsKikimr) { - NYql::TAstParseResult res = SqlToYql("replace into plato.Output values (1)", 10, TString(NYql::KikimrProviderName)); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:20: Error: REPLACE INTO ... VALUES requires specification of table columns\n"); - } +Y_UNIT_TEST(ReplaceValuesNoLabelsKikimr) { + NYql::TAstParseResult res = SqlToYql("replace into plato.Output values (1)", 10, TString(NYql::KikimrProviderName)); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:20: Error: REPLACE INTO ... VALUES requires specification of table columns\n"); +} - Y_UNIT_TEST(InsertValuesInvalidLabels) { - NYql::TAstParseResult res = SqlToYql("insert into plato.Output (foo) values (1, 2)"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:27: Error: VALUES have 2 columns, INSERT INTO expects: 1\n"); - } +Y_UNIT_TEST(InsertValuesInvalidLabels) { + NYql::TAstParseResult res = SqlToYql("insert into plato.Output (foo) values (1, 2)"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:27: Error: VALUES have 2 columns, INSERT INTO expects: 1\n"); +} - Y_UNIT_TEST(BuiltinFileOpNoArgs) { - NYql::TAstParseResult res = SqlToYql("select FilePath()"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: FilePath() requires exactly 1 arguments, given: 0\n"); - } +Y_UNIT_TEST(BuiltinFileOpNoArgs) { + NYql::TAstParseResult res = SqlToYql("select FilePath()"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: FilePath() requires exactly 1 arguments, given: 0\n"); +} - Y_UNIT_TEST(ProcessWithHaving) { - NYql::TAstParseResult res = SqlToYql("process plato.Input using some::udf(value) having value == 1"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:15: Error: PROCESS does not allow HAVING yet! You may request it on yql@ maillist.\n"); - } +Y_UNIT_TEST(ProcessWithHaving) { + NYql::TAstParseResult res = SqlToYql("process plato.Input using some::udf(value) having value == 1"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:15: Error: PROCESS does not allow HAVING yet! You may request it on yql@ maillist.\n"); +} - Y_UNIT_TEST(ReduceNoBy) { - NYql::TAstParseResult res = SqlToYql("reduce plato.Input using some::udf(value)"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(ReduceNoBy) { + NYql::TAstParseResult res = SqlToYql("reduce plato.Input using some::udf(value)"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: Unexpected token absence : Missing ON \n\n<main>:1:25: Error: Unexpected token absence : Missing USING \n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: Unexpected token absence : Missing ON \n\n<main>:1:25: Error: Unexpected token absence : Missing USING \n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: mismatched input 'using' expecting {',', ON, PRESORT}\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: mismatched input 'using' expecting {',', ON, PRESORT}\n"); #endif - } +} - Y_UNIT_TEST(ReduceDistinct) { - NYql::TAstParseResult res = SqlToYql("reduce plato.Input on key using some::udf(distinct value)"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:43: Error: DISTINCT can not be used in PROCESS/REDUCE\n"); - } +Y_UNIT_TEST(ReduceDistinct) { + NYql::TAstParseResult res = SqlToYql("reduce plato.Input on key using some::udf(distinct value)"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:43: Error: DISTINCT can not be used in PROCESS/REDUCE\n"); +} - Y_UNIT_TEST(CreateTableWithView) { - NYql::TAstParseResult res = SqlToYql("CREATE TABLE plato.foo:bar (key INT);"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(CreateTableWithView) { + NYql::TAstParseResult res = SqlToYql("CREATE TABLE plato.foo:bar (key INT);"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:22: Error: Unexpected token ':' : syntax error...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:22: Error: Unexpected token ':' : syntax error...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:22: Error: mismatched input ':' expecting '('\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:22: Error: mismatched input ':' expecting '('\n"); #endif - } +} - Y_UNIT_TEST(AsteriskWithSomethingAfter) { - NYql::TAstParseResult res = SqlToYql("select *, LENGTH(value) from plato.Input;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Unable to use plain '*' with other projection items. Please use qualified asterisk instead: '<table>.*' (<table> can be either table name or table alias).\n"); - } +Y_UNIT_TEST(AsteriskWithSomethingAfter) { + NYql::TAstParseResult res = SqlToYql("select *, LENGTH(value) from plato.Input;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Unable to use plain '*' with other projection items. Please use qualified asterisk instead: '<table>.*' (<table> can be either table name or table alias).\n"); +} - Y_UNIT_TEST(AsteriskWithSomethingBefore) { - NYql::TAstParseResult res = SqlToYql("select LENGTH(value), * from plato.Input;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:23: Error: Unable to use plain '*' with other projection items. Please use qualified asterisk instead: '<table>.*' (<table> can be either table name or table alias).\n"); - } +Y_UNIT_TEST(AsteriskWithSomethingBefore) { + NYql::TAstParseResult res = SqlToYql("select LENGTH(value), * from plato.Input;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:23: Error: Unable to use plain '*' with other projection items. Please use qualified asterisk instead: '<table>.*' (<table> can be either table name or table alias).\n"); +} - Y_UNIT_TEST(DuplicatedQualifiedAsterisk) { - NYql::TAstParseResult res = SqlToYql("select in.*, key, in.* from plato.Input as in;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: Unable to use twice same quialified asterisk. Invalid source: in\n"); - } +Y_UNIT_TEST(DuplicatedQualifiedAsterisk) { + NYql::TAstParseResult res = SqlToYql("select in.*, key, in.* from plato.Input as in;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: Unable to use twice same quialified asterisk. Invalid source: in\n"); +} - Y_UNIT_TEST(BrokenLabel) { - NYql::TAstParseResult res = SqlToYql("select in.*, key as `funny.label` from plato.Input as in;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:14: Error: Unable to use '.' in column name. Invalid column name: funny.label\n"); - } +Y_UNIT_TEST(BrokenLabel) { + NYql::TAstParseResult res = SqlToYql("select in.*, key as `funny.label` from plato.Input as in;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:14: Error: Unable to use '.' in column name. Invalid column name: funny.label\n"); +} - Y_UNIT_TEST(KeyConflictDetect0) { - NYql::TAstParseResult res = SqlToYql("select key, in.key as key from plato.Input as in;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:13: Error: Unable to use duplicate column names. Collision in name: key\n"); - } +Y_UNIT_TEST(KeyConflictDetect0) { + NYql::TAstParseResult res = SqlToYql("select key, in.key as key from plato.Input as in;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:13: Error: Unable to use duplicate column names. Collision in name: key\n"); +} - Y_UNIT_TEST(KeyConflictDetect1) { - NYql::TAstParseResult res = SqlToYql("select length(key) as key, key from plato.Input;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:28: Error: Unable to use duplicate column names. Collision in name: key\n"); - } +Y_UNIT_TEST(KeyConflictDetect1) { + NYql::TAstParseResult res = SqlToYql("select length(key) as key, key from plato.Input;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:28: Error: Unable to use duplicate column names. Collision in name: key\n"); +} - Y_UNIT_TEST(KeyConflictDetect2) { - NYql::TAstParseResult res = SqlToYql("select key, in.key from plato.Input as in;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Duplicate column: key\n"); - } +Y_UNIT_TEST(KeyConflictDetect2) { + NYql::TAstParseResult res = SqlToYql("select key, in.key from plato.Input as in;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Duplicate column: key\n"); +} - Y_UNIT_TEST(AutogenerationAliasWithCollisionConflict1) { - UNIT_ASSERT(SqlToYql("select LENGTH(Value), key as column0 from plato.Input;").IsOk()); - } +Y_UNIT_TEST(AutogenerationAliasWithCollisionConflict1) { + UNIT_ASSERT(SqlToYql("select LENGTH(Value), key as column0 from plato.Input;").IsOk()); +} - Y_UNIT_TEST(AutogenerationAliasWithCollisionConflict2) { - UNIT_ASSERT(SqlToYql("select key as column1, LENGTH(Value) from plato.Input;").IsOk()); - } +Y_UNIT_TEST(AutogenerationAliasWithCollisionConflict2) { + UNIT_ASSERT(SqlToYql("select key as column1, LENGTH(Value) from plato.Input;").IsOk()); +} - Y_UNIT_TEST(MissedSourceTableForQualifiedAsteriskOnSimpleSelect) { - NYql::TAstParseResult res = SqlToYql("use plato; select Intop.*, Input.key from plato.Input;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: Unknown correlation name: Intop\n"); - } +Y_UNIT_TEST(MissedSourceTableForQualifiedAsteriskOnSimpleSelect) { + NYql::TAstParseResult res = SqlToYql("use plato; select Intop.*, Input.key from plato.Input;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: Unknown correlation name: Intop\n"); +} - Y_UNIT_TEST(MissedSourceTableForQualifiedAsteriskOnJoin) { - NYql::TAstParseResult res = SqlToYql("use plato; select tmissed.*, t2.*, t1.key from plato.Input as t1 join plato.Input as t2 on t1.key==t2.key;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: Unknown correlation name for asterisk: tmissed\n"); - } +Y_UNIT_TEST(MissedSourceTableForQualifiedAsteriskOnJoin) { + NYql::TAstParseResult res = SqlToYql("use plato; select tmissed.*, t2.*, t1.key from plato.Input as t1 join plato.Input as t2 on t1.key==t2.key;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:19: Error: Unknown correlation name for asterisk: tmissed\n"); +} - Y_UNIT_TEST(UnableToReferenceOnNotExistSubcolumn) { - NYql::TAstParseResult res = SqlToYql("select b.subkey from (select key from plato.Input as a) as b;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Column subkey is not in source column set\n"); - } +Y_UNIT_TEST(UnableToReferenceOnNotExistSubcolumn) { + NYql::TAstParseResult res = SqlToYql("select b.subkey from (select key from plato.Input as a) as b;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Column subkey is not in source column set\n"); +} - Y_UNIT_TEST(ConflictOnSameNameWithQualify0) { - NYql::TAstParseResult res = SqlToYql("select in.key, in.key as key from plato.Input as in;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Duplicate column: key\n"); - } +Y_UNIT_TEST(ConflictOnSameNameWithQualify0) { + NYql::TAstParseResult res = SqlToYql("select in.key, in.key as key from plato.Input as in;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Duplicate column: key\n"); +} - Y_UNIT_TEST(ConflictOnSameNameWithQualify1) { - NYql::TAstParseResult res = SqlToYql("select in.key, length(key) as key from plato.Input as in;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Duplicate column: key\n"); - } +Y_UNIT_TEST(ConflictOnSameNameWithQualify1) { + NYql::TAstParseResult res = SqlToYql("select in.key, length(key) as key from plato.Input as in;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Duplicate column: key\n"); +} - Y_UNIT_TEST(ConflictOnSameNameWithQualify2) { - NYql::TAstParseResult res = SqlToYql("select key, in.key from plato.Input as in;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Duplicate column: key\n"); - } +Y_UNIT_TEST(ConflictOnSameNameWithQualify2) { + NYql::TAstParseResult res = SqlToYql("select key, in.key from plato.Input as in;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Duplicate column: key\n"); +} - Y_UNIT_TEST(ConflictOnSameNameWithQualify3) { - NYql::TAstParseResult res = SqlToYql("select in.key, subkey as key from plato.Input as in;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Duplicate column: key\n"); - } +Y_UNIT_TEST(ConflictOnSameNameWithQualify3) { + NYql::TAstParseResult res = SqlToYql("select in.key, subkey as key from plato.Input as in;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Duplicate column: key\n"); +} - Y_UNIT_TEST(SelectFlattenBySameColumns) { - NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key, key as kk)"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:46: Error: Duplicate column name found: key in FlattenBy section\n"); - } +Y_UNIT_TEST(SelectFlattenBySameColumns) { + NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key, key as kk)"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:46: Error: Duplicate column name found: key in FlattenBy section\n"); +} - Y_UNIT_TEST(SelectFlattenBySameAliases) { - NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key as kk, subkey as kk);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:52: Error: Duplicate alias found: kk in FlattenBy section\n"); - } +Y_UNIT_TEST(SelectFlattenBySameAliases) { + NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key as kk, subkey as kk);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:52: Error: Duplicate alias found: kk in FlattenBy section\n"); +} - Y_UNIT_TEST(SelectFlattenByExprSameAliases) { - NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key as kk, ListSkip(subkey,1) as kk);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:52: Error: Collision between alias and column name: kk in FlattenBy section\n"); - } +Y_UNIT_TEST(SelectFlattenByExprSameAliases) { + NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key as kk, ListSkip(subkey,1) as kk);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:52: Error: Collision between alias and column name: kk in FlattenBy section\n"); +} - Y_UNIT_TEST(SelectFlattenByConflictNameAndAlias0) { - NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key, subkey as key);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:46: Error: Collision between alias and column name: key in FlattenBy section\n"); - } +Y_UNIT_TEST(SelectFlattenByConflictNameAndAlias0) { + NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key, subkey as key);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:46: Error: Collision between alias and column name: key in FlattenBy section\n"); +} - Y_UNIT_TEST(SelectFlattenByConflictNameAndAlias1) { - NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key as kk, subkey as key);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:52: Error: Collision between alias and column name: key in FlattenBy section\n"); - } +Y_UNIT_TEST(SelectFlattenByConflictNameAndAlias1) { + NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key as kk, subkey as key);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:52: Error: Collision between alias and column name: key in FlattenBy section\n"); +} - Y_UNIT_TEST(SelectFlattenByExprConflictNameAndAlias1) { - NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key as kk, ListSkip(subkey,1) as key);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:52: Error: Duplicate column name found: key in FlattenBy section\n"); - } +Y_UNIT_TEST(SelectFlattenByExprConflictNameAndAlias1) { + NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key as kk, ListSkip(subkey,1) as key);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:52: Error: Duplicate column name found: key in FlattenBy section\n"); +} - Y_UNIT_TEST(SelectFlattenByUnnamedExpr) { - NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key, ListSkip(key, 1))"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:46: Error: Unnamed expression after FLATTEN BY is not allowed\n"); - } +Y_UNIT_TEST(SelectFlattenByUnnamedExpr) { + NYql::TAstParseResult res = SqlToYql("select key from plato.Input flatten by (key, ListSkip(key, 1))"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:46: Error: Unnamed expression after FLATTEN BY is not allowed\n"); +} - Y_UNIT_TEST(UseInOnStrings) { - NYql::TAstParseResult res = SqlToYql("select * from plato.Input where \"foo\" in \"foovalue\";"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:42: Error: Unable to use IN predicate with string argument, it won't search substring - " - "expecting tuple, list, dict or single column table source\n"); - } +Y_UNIT_TEST(UseInOnStrings) { + NYql::TAstParseResult res = SqlToYql("select * from plato.Input where \"foo\" in \"foovalue\";"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:42: Error: Unable to use IN predicate with string argument, it won't search substring - " + "expecting tuple, list, dict or single column table source\n"); +} - Y_UNIT_TEST(UseSubqueryInScalarContextInsideIn) { - NYql::TAstParseResult res = SqlToYql("$q = (select key from plato.Input); select * from plato.Input where subkey in ($q);"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:79: Warning: Using subrequest in scalar context after IN, " - "perhaps you should remove parenthesis here, code: 4501\n"); - } +Y_UNIT_TEST(UseSubqueryInScalarContextInsideIn) { + NYql::TAstParseResult res = SqlToYql("$q = (select key from plato.Input); select * from plato.Input where subkey in ($q);"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:79: Warning: Using subrequest in scalar context after IN, " + "perhaps you should remove parenthesis here, code: 4501\n"); +} - Y_UNIT_TEST(InHintsWithKeywordClash) { - NYql::TAstParseResult res = SqlToYql("SELECT COMPACT FROM plato.Input WHERE COMPACT IN COMPACT `COMPACT`(1,2,3)"); - UNIT_ASSERT(!res.Root); - // should try to parse last compact as call expression - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:58: Error: Unknown builtin: COMPACT\n"); - } +Y_UNIT_TEST(InHintsWithKeywordClash) { + NYql::TAstParseResult res = SqlToYql("SELECT COMPACT FROM plato.Input WHERE COMPACT IN COMPACT `COMPACT`(1,2,3)"); + UNIT_ASSERT(!res.Root); + // should try to parse last compact as call expression + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:58: Error: Unknown builtin: COMPACT\n"); +} - Y_UNIT_TEST(ErrorColumnPosition) { - NYql::TAstParseResult res = SqlToYql( - "USE plato;\n" - "SELECT \n" - "value FROM (\n" - "select key from Input\n" - ");\n" - ); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:1: Error: Column value is not in source column set\n"); - } +Y_UNIT_TEST(ErrorColumnPosition) { + NYql::TAstParseResult res = SqlToYql( + "USE plato;\n" + "SELECT \n" + "value FROM (\n" + "select key from Input\n" + ");\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:1: Error: Column value is not in source column set\n"); +} - Y_UNIT_TEST(PrimaryViewAbortMapReduce) { - NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input VIEW PRIMARY KEY"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:17: Error: primary view is not supported for yt tables\n"); - } +Y_UNIT_TEST(PrimaryViewAbortMapReduce) { + NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input VIEW PRIMARY KEY"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:17: Error: primary view is not supported for yt tables\n"); +} - Y_UNIT_TEST(InsertAbortMapReduce) { - NYql::TAstParseResult res = SqlToYql("INSERT OR ABORT INTO plato.Output SELECT key FROM plato.Input"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: INSERT OR ABORT INTO is not supported for yt tables\n"); - } +Y_UNIT_TEST(InsertAbortMapReduce) { + NYql::TAstParseResult res = SqlToYql("INSERT OR ABORT INTO plato.Output SELECT key FROM plato.Input"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: INSERT OR ABORT INTO is not supported for yt tables\n"); +} - Y_UNIT_TEST(ReplaceIntoMapReduce) { - NYql::TAstParseResult res = SqlToYql("REPLACE INTO plato.Output SELECT key FROM plato.Input"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: Meaning of REPLACE INTO has been changed, now you should use INSERT INTO <table> WITH TRUNCATE ... for yt\n"); - } +Y_UNIT_TEST(ReplaceIntoMapReduce) { + NYql::TAstParseResult res = SqlToYql("REPLACE INTO plato.Output SELECT key FROM plato.Input"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: Meaning of REPLACE INTO has been changed, now you should use INSERT INTO <table> WITH TRUNCATE ... for yt\n"); +} - Y_UNIT_TEST(UpsertIntoMapReduce) { - NYql::TAstParseResult res = SqlToYql("UPSERT INTO plato.Output SELECT key FROM plato.Input"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: UPSERT INTO is not supported for yt tables\n"); - } +Y_UNIT_TEST(UpsertIntoMapReduce) { + NYql::TAstParseResult res = SqlToYql("UPSERT INTO plato.Output SELECT key FROM plato.Input"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: UPSERT INTO is not supported for yt tables\n"); +} - Y_UNIT_TEST(UpdateMapReduce) { - NYql::TAstParseResult res = SqlToYql("UPDATE plato.Output SET value = value + 1 WHERE key < 1"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: UPDATE is unsupported for yt\n"); - } +Y_UNIT_TEST(UpdateMapReduce) { + NYql::TAstParseResult res = SqlToYql("UPDATE plato.Output SET value = value + 1 WHERE key < 1"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: UPDATE is unsupported for yt\n"); +} - Y_UNIT_TEST(DeleteMapReduce) { - NYql::TAstParseResult res = SqlToYql("DELETE FROM plato.Output WHERE key < 1"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: DELETE is unsupported for yt\n"); - } +Y_UNIT_TEST(DeleteMapReduce) { + NYql::TAstParseResult res = SqlToYql("DELETE FROM plato.Output WHERE key < 1"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: DELETE is unsupported for yt\n"); +} - Y_UNIT_TEST(ReplaceIntoWithTruncate) { - NYql::TAstParseResult res = SqlToYql("REPLACE INTO plato.Output WITH TRUNCATE SELECT key FROM plato.Input"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:32: Error: Unable REPLACE INTO with truncate mode\n"); - } +Y_UNIT_TEST(ReplaceIntoWithTruncate) { + NYql::TAstParseResult res = SqlToYql("REPLACE INTO plato.Output WITH TRUNCATE SELECT key FROM plato.Input"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:32: Error: Unable REPLACE INTO with truncate mode\n"); +} - Y_UNIT_TEST(UpsertIntoWithTruncate) { - NYql::TAstParseResult res = SqlToYql("UPSERT INTO plato.Output WITH TRUNCATE SELECT key FROM plato.Input"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:31: Error: Unable UPSERT INTO with truncate mode\n"); - } +Y_UNIT_TEST(UpsertIntoWithTruncate) { + NYql::TAstParseResult res = SqlToYql("UPSERT INTO plato.Output WITH TRUNCATE SELECT key FROM plato.Input"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:31: Error: Unable UPSERT INTO with truncate mode\n"); +} - Y_UNIT_TEST(InsertIntoWithTruncateKikimr) { - NYql::TAstParseResult res = SqlToYql("INSERT INTO plato.Output WITH TRUNCATE SELECT key FROM plato.Input", 10, TString(NYql::KikimrProviderName)); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: INSERT INTO WITH TRUNCATE is not supported for kikimr tables\n"); - } +Y_UNIT_TEST(InsertIntoWithTruncateKikimr) { + NYql::TAstParseResult res = SqlToYql("INSERT INTO plato.Output WITH TRUNCATE SELECT key FROM plato.Input", 10, TString(NYql::KikimrProviderName)); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:0: Error: INSERT INTO WITH TRUNCATE is not supported for kikimr tables\n"); +} - Y_UNIT_TEST(InsertIntoWithWrongArgumentCount) { - NYql::TAstParseResult res = SqlToYql("insert into plato.Output with truncate (key, value, subkey) values (5, '1', '2', '3');"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:53: Error: VALUES have 4 columns, INSERT INTO ... WITH TRUNCATE expects: 3\n"); - } +Y_UNIT_TEST(InsertIntoWithWrongArgumentCount) { + NYql::TAstParseResult res = SqlToYql("insert into plato.Output with truncate (key, value, subkey) values (5, '1', '2', '3');"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:53: Error: VALUES have 4 columns, INSERT INTO ... WITH TRUNCATE expects: 3\n"); +} - Y_UNIT_TEST(UpsertWithWrongArgumentCount) { - NYql::TAstParseResult res = SqlToYql("upsert into plato.Output (key, value, subkey) values (2, '3');", 10, TString(NYql::KikimrProviderName)); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:39: Error: VALUES have 2 columns, UPSERT INTO expects: 3\n"); - } +Y_UNIT_TEST(UpsertWithWrongArgumentCount) { + NYql::TAstParseResult res = SqlToYql("upsert into plato.Output (key, value, subkey) values (2, '3');", 10, TString(NYql::KikimrProviderName)); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:39: Error: VALUES have 2 columns, UPSERT INTO expects: 3\n"); +} - Y_UNIT_TEST(GroupingSetByExprWithoutAlias) { - NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY GROUPING SETS (cast(key as uint32), subkey);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:53: Error: Unnamed expressions are not supported in GROUPING SETS. Please use '<expr> AS <name>'.\n"); - } +Y_UNIT_TEST(GroupingSetByExprWithoutAlias) { + NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY GROUPING SETS (cast(key as uint32), subkey);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:53: Error: Unnamed expressions are not supported in GROUPING SETS. Please use '<expr> AS <name>'.\n"); +} - Y_UNIT_TEST(GroupingSetByExprWithoutAlias2) { - NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY subkey || subkey, GROUPING SETS (\n" - "cast(key as uint32), subkey);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:1: Error: Unnamed expressions are not supported in GROUPING SETS. Please use '<expr> AS <name>'.\n"); - } +Y_UNIT_TEST(GroupingSetByExprWithoutAlias2) { + NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY subkey || subkey, GROUPING SETS (\n" + "cast(key as uint32), subkey);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:1: Error: Unnamed expressions are not supported in GROUPING SETS. Please use '<expr> AS <name>'.\n"); +} - Y_UNIT_TEST(CubeByExprWithoutAlias) { - NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY CUBE (key, subkey / key);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:56: Error: Unnamed expressions are not supported in CUBE. Please use '<expr> AS <name>'.\n"); - } +Y_UNIT_TEST(CubeByExprWithoutAlias) { + NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY CUBE (key, subkey / key);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:56: Error: Unnamed expressions are not supported in CUBE. Please use '<expr> AS <name>'.\n"); +} - Y_UNIT_TEST(RollupByExprWithoutAlias) { - NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY ROLLUP (subkey / key);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:53: Error: Unnamed expressions are not supported in ROLLUP. Please use '<expr> AS <name>'.\n"); - } +Y_UNIT_TEST(RollupByExprWithoutAlias) { + NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY ROLLUP (subkey / key);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:53: Error: Unnamed expressions are not supported in ROLLUP. Please use '<expr> AS <name>'.\n"); +} - Y_UNIT_TEST(GroupByHugeCubeDeniedNoPragma) { - NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY CUBE (key, subkey, value, key + subkey as sum, key - subkey as sub, key + val as keyval);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:119: Error: GROUP BY CUBE is allowed only for 5 columns, but you use 6\n"); - } +Y_UNIT_TEST(GroupByHugeCubeDeniedNoPragma) { + NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY CUBE (key, subkey, value, key + subkey as sum, key - subkey as sub, key + val as keyval);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:119: Error: GROUP BY CUBE is allowed only for 5 columns, but you use 6\n"); +} - Y_UNIT_TEST(GroupByInvalidPragma) { - NYql::TAstParseResult res = SqlToYql("PRAGMA GroupByCubeLimit = '-4';"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:27: Error: Expected unsigned integer literal as a single argument for: GroupByCubeLimit\n"); - } +Y_UNIT_TEST(GroupByInvalidPragma) { + NYql::TAstParseResult res = SqlToYql("PRAGMA GroupByCubeLimit = '-4';"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:27: Error: Expected unsigned integer literal as a single argument for: GroupByCubeLimit\n"); +} - Y_UNIT_TEST(GroupByHugeCubeDeniedPragme) { - NYql::TAstParseResult res = SqlToYql("PRAGMA GroupByCubeLimit = '4'; SELECT key FROM plato.Input GROUP BY CUBE (key, subkey, value, key + subkey as sum, key - subkey as sub);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:132: Error: GROUP BY CUBE is allowed only for 4 columns, but you use 5\n"); - } +Y_UNIT_TEST(GroupByHugeCubeDeniedPragme) { + NYql::TAstParseResult res = SqlToYql("PRAGMA GroupByCubeLimit = '4'; SELECT key FROM plato.Input GROUP BY CUBE (key, subkey, value, key + subkey as sum, key - subkey as sub);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:132: Error: GROUP BY CUBE is allowed only for 4 columns, but you use 5\n"); +} - Y_UNIT_TEST(GroupByFewBigCubes) { - NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY CUBE(key, subkey, key + subkey as sum), CUBE(value, value + key + subkey as total);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Unable to GROUP BY more than 64 groups, you try use 80 groups\n"); - } +Y_UNIT_TEST(GroupByFewBigCubes) { + NYql::TAstParseResult res = SqlToYql("SELECT key FROM plato.Input GROUP BY CUBE(key, subkey, key + subkey as sum), CUBE(value, value + key + subkey as total);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Unable to GROUP BY more than 64 groups, you try use 80 groups\n"); +} - Y_UNIT_TEST(GroupByFewBigCubesWithPragmaLimit) { - NYql::TAstParseResult res = SqlToYql("PRAGMA GroupByLimit = '16'; SELECT key FROM plato.Input GROUP BY GROUPING SETS(key, subkey, key + subkey as sum), ROLLUP(value, value + key + subkey as total);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:29: Error: Unable to GROUP BY more than 16 groups, you try use 18 groups\n"); - } +Y_UNIT_TEST(GroupByFewBigCubesWithPragmaLimit) { + NYql::TAstParseResult res = SqlToYql("PRAGMA GroupByLimit = '16'; SELECT key FROM plato.Input GROUP BY GROUPING SETS(key, subkey, key + subkey as sum), ROLLUP(value, value + key + subkey as total);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:29: Error: Unable to GROUP BY more than 16 groups, you try use 18 groups\n"); +} - Y_UNIT_TEST(NoGroupingColumn0) { - NYql::TAstParseResult res = SqlToYql( - "select count(1), key_first, val_first, grouping(key_first, val_first, nomind) as group\n" - "from plato.Input group by grouping sets (cast(key as uint32) /100 as key_first, Substring(value, 1, 1) as val_first);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:71: Error: Column 'nomind' is not a grouping column\n"); - } +Y_UNIT_TEST(NoGroupingColumn0) { + NYql::TAstParseResult res = SqlToYql( + "select count(1), key_first, val_first, grouping(key_first, val_first, nomind) as group\n" + "from plato.Input group by grouping sets (cast(key as uint32) /100 as key_first, Substring(value, 1, 1) as val_first);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:71: Error: Column 'nomind' is not a grouping column\n"); +} - Y_UNIT_TEST(NoGroupingColumn1) { - NYql::TAstParseResult res = SqlToYql("select count(1), grouping(key, value) as group_duo from plato.Input group by cube (key, subkey);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:32: Error: Column 'value' is not a grouping column\n"); - } +Y_UNIT_TEST(NoGroupingColumn1) { + NYql::TAstParseResult res = SqlToYql("select count(1), grouping(key, value) as group_duo from plato.Input group by cube (key, subkey);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:32: Error: Column 'value' is not a grouping column\n"); +} - Y_UNIT_TEST(EmptyAccess0) { - NYql::TAstParseResult res = SqlToYql("insert into plato.Output (list0, list1) values (AsList(0, 1, 2), AsList(``));"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:73: Error: Column reference \"\" is not allowed in current scope\n"); - } +Y_UNIT_TEST(EmptyAccess0) { + NYql::TAstParseResult res = SqlToYql("insert into plato.Output (list0, list1) values (AsList(0, 1, 2), AsList(``));"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:73: Error: Column reference \"\" is not allowed in current scope\n"); +} - Y_UNIT_TEST(EmptyAccess1) { - NYql::TAstParseResult res = SqlToYql("insert into plato.Output (list0, list1) values (AsList(0, 1, 2), ``);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:66: Error: Column reference \"\" is not allowed in current scope\n"); - } +Y_UNIT_TEST(EmptyAccess1) { + NYql::TAstParseResult res = SqlToYql("insert into plato.Output (list0, list1) values (AsList(0, 1, 2), ``);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:66: Error: Column reference \"\" is not allowed in current scope\n"); +} - Y_UNIT_TEST(UseUnknownColumnInInsert) { - NYql::TAstParseResult res = SqlToYql("insert into plato.Output (list0, list1) values (AsList(0, 1, 2), AsList(`test`));"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:73: Error: Column reference \"test\" is not allowed in current scope\n"); - } +Y_UNIT_TEST(UseUnknownColumnInInsert) { + NYql::TAstParseResult res = SqlToYql("insert into plato.Output (list0, list1) values (AsList(0, 1, 2), AsList(`test`));"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:73: Error: Column reference \"test\" is not allowed in current scope\n"); +} - Y_UNIT_TEST(GroupByEmptyColumn) { - NYql::TAstParseResult res = SqlToYql("select count(1) from plato.Input group by ``;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:43: Error: Column name can not be empty\n"); - } +Y_UNIT_TEST(GroupByEmptyColumn) { + NYql::TAstParseResult res = SqlToYql("select count(1) from plato.Input group by ``;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:43: Error: Column name can not be empty\n"); +} - Y_UNIT_TEST(ConvertNumberOutOfBase) { - NYql::TAstParseResult res = SqlToYql("select 0o80l;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Failed to parse number from string: 0o80l, char: '8' is out of base: 8\n"); - } +Y_UNIT_TEST(ConvertNumberOutOfBase) { + NYql::TAstParseResult res = SqlToYql("select 0o80l;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Failed to parse number from string: 0o80l, char: '8' is out of base: 8\n"); +} - Y_UNIT_TEST(ConvertNumberOutOfRangeForInt64ButFitsInUint64) { - NYql::TAstParseResult res = SqlToYql("select 0xc000000000000000l;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Failed to parse 13835058055282163712 as integer literal of Int64 type: value out of range for Int64\n"); - } +Y_UNIT_TEST(ConvertNumberOutOfRangeForInt64ButFitsInUint64) { + NYql::TAstParseResult res = SqlToYql("select 0xc000000000000000l;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Failed to parse 13835058055282163712 as integer literal of Int64 type: value out of range for Int64\n"); +} - Y_UNIT_TEST(ConvertNumberOutOfRangeUint64) { - NYql::TAstParseResult res = SqlToYql("select 0xc0000000000000000l;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Failed to parse number from string: 0xc0000000000000000l, number limit overflow\n"); +Y_UNIT_TEST(ConvertNumberOutOfRangeUint64) { + NYql::TAstParseResult res = SqlToYql("select 0xc0000000000000000l;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Failed to parse number from string: 0xc0000000000000000l, number limit overflow\n"); - res = SqlToYql("select 1234234543563435151456;\n"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Failed to parse number from string: 1234234543563435151456, number limit overflow\n"); - } + res = SqlToYql("select 1234234543563435151456;\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Failed to parse number from string: 1234234543563435151456, number limit overflow\n"); +} - Y_UNIT_TEST(ConvertNumberNegativeOutOfRange) { - NYql::TAstParseResult res = SqlToYql("select -9223372036854775808;\n" - "select -9223372036854775809;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:8: Error: Failed to parse negative integer: -9223372036854775809, number limit overflow\n"); - } +Y_UNIT_TEST(ConvertNumberNegativeOutOfRange) { + NYql::TAstParseResult res = SqlToYql("select -9223372036854775808;\n" + "select -9223372036854775809;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:8: Error: Failed to parse negative integer: -9223372036854775809, number limit overflow\n"); +} - Y_UNIT_TEST(InvaildUsageReal0) { - NYql::TAstParseResult res = SqlToYql("select .0;"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(InvaildUsageReal0) { + NYql::TAstParseResult res = SqlToYql("select .0;"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:7: Error: Unexpected token '.' : cannot match to any predicted input...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:7: Error: Unexpected token '.' : cannot match to any predicted input...\n\n"); #else - UNIT_ASSERT_STRING_CONTAINS(Err2Str(res), "<main>:1:7: Error: extraneous input '.' expecting {"); + UNIT_ASSERT_STRING_CONTAINS(Err2Str(res), "<main>:1:7: Error: extraneous input '.' expecting {"); #endif - } +} - Y_UNIT_TEST(InvaildUsageReal1) { - NYql::TAstParseResult res = SqlToYql("select .0f;"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(InvaildUsageReal1) { + NYql::TAstParseResult res = SqlToYql("select .0f;"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:7: Error: Unexpected token '.' : cannot match to any predicted input...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:7: Error: Unexpected token '.' : cannot match to any predicted input...\n\n"); #else - UNIT_ASSERT_STRING_CONTAINS(Err2Str(res), "<main>:1:7: Error: extraneous input '.' expecting {"); + UNIT_ASSERT_STRING_CONTAINS(Err2Str(res), "<main>:1:7: Error: extraneous input '.' expecting {"); #endif - } +} - Y_UNIT_TEST(InvaildUsageWinFunctionWithoutWindow) { - NYql::TAstParseResult res = SqlToYql("select lead(key, 2) from plato.Input;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Failed to use window function Lead without window specification\n"); - } +Y_UNIT_TEST(InvaildUsageWinFunctionWithoutWindow) { + NYql::TAstParseResult res = SqlToYql("select lead(key, 2) from plato.Input;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Failed to use window function Lead without window specification\n"); +} - Y_UNIT_TEST(DropTableWithIfExists) { - NYql::TAstParseResult res = SqlToYql("DROP TABLE IF EXISTS plato.foo;"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(DropTableWithIfExists) { + NYql::TAstParseResult res = SqlToYql("DROP TABLE IF EXISTS plato.foo;"); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("drop_if_exists")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("drop_if_exists")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DropTableNamedNode) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropTableNamedNode) { + NYql::TAstParseResult res = SqlToYql(R"sql( $x = "y"; DROP TABLE plato.$x; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - } + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); +} - Y_UNIT_TEST(TooManyErrors) { - const char* q = R"( +Y_UNIT_TEST(TooManyErrors) { + const char* q = R"( USE plato; select A, B, C, D, E, F, G, H, I, J, K, L, M, N from (select b from `abc`); )"; - NYql::TAstParseResult res = SqlToYql(q, 10); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), - R"(<main>:3:16: Error: Column A is not in source column set. Did you mean b? + NYql::TAstParseResult res = SqlToYql(q, 10); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), + R"(<main>:3:16: Error: Column A is not in source column set. Did you mean b? <main>:3:19: Error: Column B is not in source column set. Did you mean b? <main>:3:22: Error: Column C is not in source column set. Did you mean b? <main>:3:25: Error: Column D is not in source column set. Did you mean b? @@ -5717,10 +5669,10 @@ Y_UNIT_TEST_SUITE(SqlToYQLErrors) { <main>:3:40: Error: Column I is not in source column set. Did you mean b? <main>: Error: Too many issues, code: 1 )"); - }; +}; - Y_UNIT_TEST(ShouldCloneBindingForNamedParameter) { - NYql::TAstParseResult res = SqlToYql(R"($f = () -> { +Y_UNIT_TEST(ShouldCloneBindingForNamedParameter) { + NYql::TAstParseResult res = SqlToYql(R"($f = () -> { $value_type = TypeOf(1); $pair_type = StructType( TypeOf("2") AS key, @@ -5734,726 +5686,723 @@ Y_UNIT_TEST_SUITE(SqlToYQLErrors) { select FormatType($f()); )"); - UNIT_ASSERT(res.Root); - } + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(BlockedInvalidFrameBounds) { - auto check = [](const TString& frame, const TString& err) { - const TString prefix = "SELECT SUM(x) OVER w FROM plato.Input WINDOW w AS (PARTITION BY key ORDER BY subkey\n"; - NYql::TAstParseResult res = SqlToYql(prefix + frame + ")"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), err); - }; +Y_UNIT_TEST(BlockedInvalidFrameBounds) { + auto check = [](const TString& frame, const TString& err) { + const TString prefix = "SELECT SUM(x) OVER w FROM plato.Input WINDOW w AS (PARTITION BY key ORDER BY subkey\n"; + NYql::TAstParseResult res = SqlToYql(prefix + frame + ")"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), err); + }; - check("ROWS UNBOUNDED FOLLOWING", "<main>:2:5: Error: Frame cannot start from UNBOUNDED FOLLOWING\n"); - check("ROWS BETWEEN 5 PRECEDING AND UNBOUNDED PRECEDING", "<main>:2:29: Error: Frame cannot end with UNBOUNDED PRECEDING\n"); - check("ROWS BETWEEN CURRENT ROW AND 5 PRECEDING", "<main>:2:13: Error: Frame cannot start from CURRENT ROW and end with PRECEDING\n"); - check("ROWS BETWEEN 5 FOLLOWING AND CURRENT ROW", "<main>:2:14: Error: Frame cannot start from FOLLOWING and end with CURRENT ROW\n"); - check("ROWS BETWEEN 5 FOLLOWING AND 5 PRECEDING", "<main>:2:14: Error: Frame cannot start from FOLLOWING and end with PRECEDING\n"); - } + check("ROWS UNBOUNDED FOLLOWING", "<main>:2:5: Error: Frame cannot start from UNBOUNDED FOLLOWING\n"); + check("ROWS BETWEEN 5 PRECEDING AND UNBOUNDED PRECEDING", "<main>:2:29: Error: Frame cannot end with UNBOUNDED PRECEDING\n"); + check("ROWS BETWEEN CURRENT ROW AND 5 PRECEDING", "<main>:2:13: Error: Frame cannot start from CURRENT ROW and end with PRECEDING\n"); + check("ROWS BETWEEN 5 FOLLOWING AND CURRENT ROW", "<main>:2:14: Error: Frame cannot start from FOLLOWING and end with CURRENT ROW\n"); + check("ROWS BETWEEN 5 FOLLOWING AND 5 PRECEDING", "<main>:2:14: Error: Frame cannot start from FOLLOWING and end with PRECEDING\n"); +} - Y_UNIT_TEST(BlockedRangeValueWithoutSingleOrderBy) { - UNIT_ASSERT(SqlToYql("SELECT COUNT(*) OVER (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM plato.Input").IsOk()); - UNIT_ASSERT(SqlToYql("SELECT COUNT(*) OVER (RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM plato.Input").IsOk()); +Y_UNIT_TEST(BlockedRangeValueWithoutSingleOrderBy) { + UNIT_ASSERT(SqlToYql("SELECT COUNT(*) OVER (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM plato.Input").IsOk()); + UNIT_ASSERT(SqlToYql("SELECT COUNT(*) OVER (RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) FROM plato.Input").IsOk()); - auto res = SqlToYql("SELECT COUNT(*) OVER (RANGE 5 PRECEDING) FROM plato.Input"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:29: Error: RANGE with <offset> PRECEDING/FOLLOWING requires exactly one expression in ORDER BY partition clause\n"); + auto res = SqlToYql("SELECT COUNT(*) OVER (RANGE 5 PRECEDING) FROM plato.Input"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:29: Error: RANGE with <offset> PRECEDING/FOLLOWING requires exactly one expression in ORDER BY partition clause\n"); - res = SqlToYql("SELECT COUNT(*) OVER (ORDER BY key, value RANGE 5 PRECEDING) FROM plato.Input"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:49: Error: RANGE with <offset> PRECEDING/FOLLOWING requires exactly one expression in ORDER BY partition clause\n"); - } + res = SqlToYql("SELECT COUNT(*) OVER (ORDER BY key, value RANGE 5 PRECEDING) FROM plato.Input"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:49: Error: RANGE with <offset> PRECEDING/FOLLOWING requires exactly one expression in ORDER BY partition clause\n"); +} - Y_UNIT_TEST(NoColumnsInFrameBounds) { - NYql::TAstParseResult res = SqlToYql( - "SELECT SUM(x) OVER w FROM plato.Input WINDOW w AS (ROWS BETWEEN\n" - " 1 + key PRECEDING AND 2 + key FOLLOWING);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:6: Error: Column reference \"key\" is not allowed in current scope\n"); - } +Y_UNIT_TEST(NoColumnsInFrameBounds) { + NYql::TAstParseResult res = SqlToYql( + "SELECT SUM(x) OVER w FROM plato.Input WINDOW w AS (ROWS BETWEEN\n" + " 1 + key PRECEDING AND 2 + key FOLLOWING);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:6: Error: Column reference \"key\" is not allowed in current scope\n"); +} - Y_UNIT_TEST(WarnOnEmptyFrameBounds) { - NYql::TAstParseResult res = SqlToYql( - "SELECT SUM(x) OVER w FROM plato.Input WINDOW w AS (PARTITION BY key ORDER BY subkey\n" - "ROWS BETWEEN 10 FOLLOWING AND 5 FOLLOWING)"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:14: Warning: Used frame specification implies empty window frame, code: 4520\n"); - } +Y_UNIT_TEST(WarnOnEmptyFrameBounds) { + NYql::TAstParseResult res = SqlToYql( + "SELECT SUM(x) OVER w FROM plato.Input WINDOW w AS (PARTITION BY key ORDER BY subkey\n" + "ROWS BETWEEN 10 FOLLOWING AND 5 FOLLOWING)"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:14: Warning: Used frame specification implies empty window frame, code: 4520\n"); +} - Y_UNIT_TEST(WarnOnRankWithUnorderedWindow) { - NYql::TAstParseResult res = SqlToYql("SELECT RANK() OVER w FROM plato.Input WINDOW w AS ()"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Warning: Rank() is used with unordered window - all rows will be considered equal to each other, code: 4521\n"); - } +Y_UNIT_TEST(WarnOnRankWithUnorderedWindow) { + NYql::TAstParseResult res = SqlToYql("SELECT RANK() OVER w FROM plato.Input WINDOW w AS ()"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Warning: Rank() is used with unordered window - all rows will be considered equal to each other, code: 4521\n"); +} - Y_UNIT_TEST(WarnOnRankExprWithUnorderedWindow) { - NYql::TAstParseResult res = SqlToYql("SELECT RANK(key) OVER w FROM plato.Input WINDOW w AS ()"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Warning: Rank(<expression>) is used with unordered window - the result is likely to be undefined, code: 4521\n"); - } +Y_UNIT_TEST(WarnOnRankExprWithUnorderedWindow) { + NYql::TAstParseResult res = SqlToYql("SELECT RANK(key) OVER w FROM plato.Input WINDOW w AS ()"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Warning: Rank(<expression>) is used with unordered window - the result is likely to be undefined, code: 4521\n"); +} - Y_UNIT_TEST(AnyAsTableName) { - NYql::TAstParseResult res = SqlToYql("use plato; select * from any;"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(AnyAsTableName) { + NYql::TAstParseResult res = SqlToYql("use plato; select * from any;"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:28: Error: Unexpected token ';' : syntax error...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:28: Error: Unexpected token ';' : syntax error...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:28: Error: no viable alternative at input 'any;'\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:28: Error: no viable alternative at input 'any;'\n"); #endif - } +} - Y_UNIT_TEST(IncorrectOrderOfLambdaOptionalArgs) { - NYql::TAstParseResult res = SqlToYql("$f = ($x?, $y)->($x + $y); select $f(1);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Non-optional argument can not follow optional one\n"); - } +Y_UNIT_TEST(IncorrectOrderOfLambdaOptionalArgs) { + NYql::TAstParseResult res = SqlToYql("$f = ($x?, $y)->($x + $y); select $f(1);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Non-optional argument can not follow optional one\n"); +} - Y_UNIT_TEST(IncorrectOrderOfActionOptionalArgs) { - NYql::TAstParseResult res = SqlToYql("define action $f($x?, $y) as select $x,$y; end define; do $f(1);"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:23: Error: Non-optional argument can not follow optional one\n"); - } +Y_UNIT_TEST(IncorrectOrderOfActionOptionalArgs) { + NYql::TAstParseResult res = SqlToYql("define action $f($x?, $y) as select $x,$y; end define; do $f(1);"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:23: Error: Non-optional argument can not follow optional one\n"); +} - Y_UNIT_TEST(NotAllowedQuestionOnNamedNode) { - NYql::TAstParseResult res = SqlToYql("$f = 1; select $f?;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:18: Error: Unexpected token '?' at the end of expression\n"); - } +Y_UNIT_TEST(NotAllowedQuestionOnNamedNode) { + NYql::TAstParseResult res = SqlToYql("$f = 1; select $f?;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:18: Error: Unexpected token '?' at the end of expression\n"); +} - Y_UNIT_TEST(AnyAndCrossJoin) { - NYql::TAstParseResult res = SqlToYql("use plato; select * from any Input1 cross join Input2"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:26: Error: ANY should not be used with Cross JOIN\n"); +Y_UNIT_TEST(AnyAndCrossJoin) { + NYql::TAstParseResult res = SqlToYql("use plato; select * from any Input1 cross join Input2"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:26: Error: ANY should not be used with Cross JOIN\n"); - res = SqlToYql("use plato; select * from Input1 cross join any Input2"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:44: Error: ANY should not be used with Cross JOIN\n"); - } + res = SqlToYql("use plato; select * from Input1 cross join any Input2"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:44: Error: ANY should not be used with Cross JOIN\n"); +} - Y_UNIT_TEST(AnyWithCartesianProduct) { - NYql::TAstParseResult res = SqlToYql("pragma AnsiImplicitCrossJoin; use plato; select * from any Input1, Input2"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:56: Error: ANY should not be used with Cross JOIN\n"); +Y_UNIT_TEST(AnyWithCartesianProduct) { + NYql::TAstParseResult res = SqlToYql("pragma AnsiImplicitCrossJoin; use plato; select * from any Input1, Input2"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:56: Error: ANY should not be used with Cross JOIN\n"); - res = SqlToYql("pragma AnsiImplicitCrossJoin; use plato; select * from Input1, any Input2"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:64: Error: ANY should not be used with Cross JOIN\n"); - } + res = SqlToYql("pragma AnsiImplicitCrossJoin; use plato; select * from Input1, any Input2"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:64: Error: ANY should not be used with Cross JOIN\n"); +} - Y_UNIT_TEST(ErrorPlainEndAsInlineActionTerminator) { - NYql::TAstParseResult res = SqlToYql( - "do begin\n" - " select 1\n" - "; end\n"); - UNIT_ASSERT(!res.Root); +Y_UNIT_TEST(ErrorPlainEndAsInlineActionTerminator) { + NYql::TAstParseResult res = SqlToYql( + "do begin\n" + " select 1\n" + "; end\n"); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:0: Error: Unexpected token absence : Missing DO \n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:0: Error: Unexpected token absence : Missing DO \n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:0: Error: missing DO at '<EOF>'\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:0: Error: missing DO at '<EOF>'\n"); #endif - } +} - Y_UNIT_TEST(ErrorMultiWayJoinWithUsing) { - NYql::TAstParseResult res = SqlToYql( - "USE plato;\n" - "PRAGMA DisableSimpleColumns;\n" - "SELECT *\n" - "FROM Input1 AS a\n" - "JOIN Input2 AS b USING(key)\n" - "JOIN Input3 AS c ON a.key = c.key;\n" - ); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), - "<main>:5:24: Error: Multi-way JOINs should be connected with ON clause instead of USING clause\n" - ); - } +Y_UNIT_TEST(ErrorMultiWayJoinWithUsing) { + NYql::TAstParseResult res = SqlToYql( + "USE plato;\n" + "PRAGMA DisableSimpleColumns;\n" + "SELECT *\n" + "FROM Input1 AS a\n" + "JOIN Input2 AS b USING(key)\n" + "JOIN Input3 AS c ON a.key = c.key;\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), + "<main>:5:24: Error: Multi-way JOINs should be connected with ON clause instead of USING clause\n"); +} - Y_UNIT_TEST(RequireLabelInFlattenByWithDot) { - NYql::TAstParseResult res = SqlToYql("select * from plato.Input flatten by x.y"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), - "<main>:1:40: Error: Unnamed expression after FLATTEN BY is not allowed\n" - ); - } +Y_UNIT_TEST(RequireLabelInFlattenByWithDot) { + NYql::TAstParseResult res = SqlToYql("select * from plato.Input flatten by x.y"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), + "<main>:1:40: Error: Unnamed expression after FLATTEN BY is not allowed\n"); +} - Y_UNIT_TEST(WarnUnnamedColumns) { - NYql::TAstParseResult res = SqlToYql( - "PRAGMA WarnUnnamedColumns;\n" - "\n" - "SELECT key, subkey, key || subkey FROM plato.Input ORDER BY subkey;\n"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:28: Warning: Autogenerated column name column2 will be used for expression, code: 4516\n"); - } +Y_UNIT_TEST(WarnUnnamedColumns) { + NYql::TAstParseResult res = SqlToYql( + "PRAGMA WarnUnnamedColumns;\n" + "\n" + "SELECT key, subkey, key || subkey FROM plato.Input ORDER BY subkey;\n"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:28: Warning: Autogenerated column name column2 will be used for expression, code: 4516\n"); +} - Y_UNIT_TEST(WarnSourceColumnMismatch) { - NYql::TAstParseResult res = SqlToYql( - "insert into plato.Output (key, subkey, new_value, one_more_value) select key as Key, subkey, value, \"x\" from plato.Input;"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:51: Warning: Column names in SELECT don't match column specification in parenthesis. \"key\" doesn't match \"Key\". \"new_value\" doesn't match \"value\", code: 4517\n"); - } +Y_UNIT_TEST(WarnSourceColumnMismatch) { + NYql::TAstParseResult res = SqlToYql( + "insert into plato.Output (key, subkey, new_value, one_more_value) select key as Key, subkey, value, \"x\" from plato.Input;"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:51: Warning: Column names in SELECT don't match column specification in parenthesis. \"key\" doesn't match \"Key\". \"new_value\" doesn't match \"value\", code: 4517\n"); +} - Y_UNIT_TEST(YtCaseInsensitive) { - NYql::TAstParseResult res = SqlToYql("select * from PlatO.foo;"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(YtCaseInsensitive) { + NYql::TAstParseResult res = SqlToYql("select * from PlatO.foo;"); + UNIT_ASSERT(res.Root); - res = SqlToYql("use PlatO; select * from foo;"); - UNIT_ASSERT(res.Root); - } + res = SqlToYql("use PlatO; select * from foo;"); + UNIT_ASSERT(res.Root); +} - Y_UNIT_TEST(KikimrCaseSensitive) { - NYql::TAstParseResult res = SqlToYql("select * from PlatO.foo;", 10, "kikimr"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:15: Error: Unknown cluster: PlatO\n"); +Y_UNIT_TEST(KikimrCaseSensitive) { + NYql::TAstParseResult res = SqlToYql("select * from PlatO.foo;", 10, "kikimr"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:15: Error: Unknown cluster: PlatO\n"); - res = SqlToYql("use PlatO; select * from foo;", 10, "kikimr"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:5: Error: Unknown cluster: PlatO\n"); - } + res = SqlToYql("use PlatO; select * from foo;", 10, "kikimr"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:5: Error: Unknown cluster: PlatO\n"); +} - Y_UNIT_TEST(DiscoveryModeForbidden) { - NYql::TAstParseResult res = SqlToYqlWithMode("insert into plato.Output select * from plato.range(\"\", Input1, Input4)", NSQLTranslation::ESqlMode::DISCOVERY); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:40: Error: range is not allowed in Discovery mode, code: 4600\n"); +Y_UNIT_TEST(DiscoveryModeForbidden) { + NYql::TAstParseResult res = SqlToYqlWithMode("insert into plato.Output select * from plato.range(\"\", Input1, Input4)", NSQLTranslation::ESqlMode::DISCOVERY); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:40: Error: range is not allowed in Discovery mode, code: 4600\n"); - res = SqlToYqlWithMode("insert into plato.Output select * from plato.like(\"\", \"Input%\")", NSQLTranslation::ESqlMode::DISCOVERY); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:40: Error: like is not allowed in Discovery mode, code: 4600\n"); + res = SqlToYqlWithMode("insert into plato.Output select * from plato.like(\"\", \"Input%\")", NSQLTranslation::ESqlMode::DISCOVERY); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:40: Error: like is not allowed in Discovery mode, code: 4600\n"); - res = SqlToYqlWithMode("insert into plato.Output select * from plato.regexp(\"\", \"Input.\")", NSQLTranslation::ESqlMode::DISCOVERY); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:40: Error: regexp is not allowed in Discovery mode, code: 4600\n"); + res = SqlToYqlWithMode("insert into plato.Output select * from plato.regexp(\"\", \"Input.\")", NSQLTranslation::ESqlMode::DISCOVERY); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:40: Error: regexp is not allowed in Discovery mode, code: 4600\n"); - res = SqlToYqlWithMode("insert into plato.Output select * from plato.filter(\"\", ($name) -> { return find($name, \"Input\") is not null; })", NSQLTranslation::ESqlMode::DISCOVERY); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:40: Error: filter is not allowed in Discovery mode, code: 4600\n"); + res = SqlToYqlWithMode("insert into plato.Output select * from plato.filter(\"\", ($name) -> { return find($name, \"Input\") is not null; })", NSQLTranslation::ESqlMode::DISCOVERY); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:40: Error: filter is not allowed in Discovery mode, code: 4600\n"); - res = SqlToYqlWithMode("select Path from plato.folder(\"\") where Type == \"table\"", NSQLTranslation::ESqlMode::DISCOVERY); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:18: Error: folder is not allowed in Discovery mode, code: 4600\n"); - } + res = SqlToYqlWithMode("select Path from plato.folder(\"\") where Type == \"table\"", NSQLTranslation::ESqlMode::DISCOVERY); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:18: Error: folder is not allowed in Discovery mode, code: 4600\n"); +} - Y_UNIT_TEST(YsonFuncWithoutArgs) { - UNIT_ASSERT(SqlToYql("SELECT Yson::SerializeText(Yson::From());").IsOk()); - } +Y_UNIT_TEST(YsonFuncWithoutArgs) { + UNIT_ASSERT(SqlToYql("SELECT Yson::SerializeText(Yson::From());").IsOk()); +} - Y_UNIT_TEST(CanNotUseOrderByInNonLastSelectInUnionAllChain) { - auto req = "pragma AnsiOrderByLimitInUnionAll;\n" - "use plato;\n" - "\n" - "select * from Input order by key\n" - "union all\n" - "select * from Input order by key limit 1;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:21: Error: ORDER BY within UNION ALL is only allowed after last subquery\n"); - } +Y_UNIT_TEST(CanNotUseOrderByInNonLastSelectInUnionAllChain) { + auto req = "pragma AnsiOrderByLimitInUnionAll;\n" + "use plato;\n" + "\n" + "select * from Input order by key\n" + "union all\n" + "select * from Input order by key limit 1;"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:21: Error: ORDER BY within UNION ALL is only allowed after last subquery\n"); +} - Y_UNIT_TEST(CanNotUseLimitInNonLastSelectInUnionAllChain) { - auto req = "pragma AnsiOrderByLimitInUnionAll;\n" - "use plato;\n" - "\n" - "select * from Input limit 1\n" - "union all\n" - "select * from Input order by key limit 1;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:21: Error: LIMIT within UNION ALL is only allowed after last subquery\n"); - } +Y_UNIT_TEST(CanNotUseLimitInNonLastSelectInUnionAllChain) { + auto req = "pragma AnsiOrderByLimitInUnionAll;\n" + "use plato;\n" + "\n" + "select * from Input limit 1\n" + "union all\n" + "select * from Input order by key limit 1;"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:21: Error: LIMIT within UNION ALL is only allowed after last subquery\n"); +} - Y_UNIT_TEST(CanNotUseDiscardInNonFirstSelectInUnionAllChain) { - auto req = "pragma AnsiOrderByLimitInUnionAll;\n" - "use plato;\n" - "\n" - "select * from Input\n" - "union all\n" - "discard select * from Input;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:6:1: Error: DISCARD within UNION ALL is only allowed before first subquery\n"); - } +Y_UNIT_TEST(CanNotUseDiscardInNonFirstSelectInUnionAllChain) { + auto req = "pragma AnsiOrderByLimitInUnionAll;\n" + "use plato;\n" + "\n" + "select * from Input\n" + "union all\n" + "discard select * from Input;"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:6:1: Error: DISCARD within UNION ALL is only allowed before first subquery\n"); +} - Y_UNIT_TEST(CanNotUseIntoResultInNonLastSelectInUnionAllChain) { - auto req = "use plato;\n" - "pragma AnsiOrderByLimitInUnionAll;\n" - "\n" - "select * from Input\n" - "union all\n" - "discard select * from Input;"; +Y_UNIT_TEST(CanNotUseIntoResultInNonLastSelectInUnionAllChain) { + auto req = "use plato;\n" + "pragma AnsiOrderByLimitInUnionAll;\n" + "\n" + "select * from Input\n" + "union all\n" + "discard select * from Input;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:6:1: Error: DISCARD within UNION ALL is only allowed before first subquery\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:6:1: Error: DISCARD within UNION ALL is only allowed before first subquery\n"); +} - Y_UNIT_TEST(YsonStrictInvalidPragma) { - auto res = SqlToYql("pragma yson.Strict = \"wrong\";"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:22: Error: Expected 'true', 'false' or no parameter for: Strict\n"); - } +Y_UNIT_TEST(YsonStrictInvalidPragma) { + auto res = SqlToYql("pragma yson.Strict = \"wrong\";"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:22: Error: Expected 'true', 'false' or no parameter for: Strict\n"); +} - Y_UNIT_TEST(WarnTableNameInSomeContexts) { - UNIT_ASSERT(SqlToYql("use plato; select TableName() from Input;").IsOk()); - UNIT_ASSERT(SqlToYql("use plato; select TableName(\"aaaa\");").IsOk()); - UNIT_ASSERT(SqlToYql("select TableName(\"aaaa\", \"yt\");").IsOk()); +Y_UNIT_TEST(WarnTableNameInSomeContexts) { + UNIT_ASSERT(SqlToYql("use plato; select TableName() from Input;").IsOk()); + UNIT_ASSERT(SqlToYql("use plato; select TableName(\"aaaa\");").IsOk()); + UNIT_ASSERT(SqlToYql("select TableName(\"aaaa\", \"yt\");").IsOk()); - auto res = SqlToYql("select TableName() from plato.Input;"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: TableName requires either service name as second argument or current cluster name\n"); + auto res = SqlToYql("select TableName() from plato.Input;"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: TableName requires either service name as second argument or current cluster name\n"); - res = SqlToYql("use plato;\n" - "select TableName() from Input1 as a join Input2 as b using(key);"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:8: Warning: TableName() may produce empty result when used in ambiguous context (with JOIN), code: 4525\n"); + res = SqlToYql("use plato;\n" + "select TableName() from Input1 as a join Input2 as b using(key);"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:8: Warning: TableName() may produce empty result when used in ambiguous context (with JOIN), code: 4525\n"); - res = SqlToYql("use plato;\n" - "select SOME(TableName()), key from Input group by key;"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:13: Warning: TableName() will produce empty result when used with aggregation.\n" - "Please consult documentation for possible workaround, code: 4525\n"); - } + res = SqlToYql("use plato;\n" + "select SOME(TableName()), key from Input group by key;"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:13: Warning: TableName() will produce empty result when used with aggregation.\n" + "Please consult documentation for possible workaround, code: 4525\n"); +} - Y_UNIT_TEST(WarnOnDistincWithHavingWithoutAggregations) { - auto res = SqlToYql("select distinct key from plato.Input having key != '0';"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:49: Warning: The usage of HAVING without aggregations with SELECT DISTINCT is non-standard and will stop working soon. Please use WHERE instead., code: 4526\n"); - } +Y_UNIT_TEST(WarnOnDistincWithHavingWithoutAggregations) { + auto res = SqlToYql("select distinct key from plato.Input having key != '0';"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:49: Warning: The usage of HAVING without aggregations with SELECT DISTINCT is non-standard and will stop working soon. Please use WHERE instead., code: 4526\n"); +} - Y_UNIT_TEST(FlattenByExprWithNestedNull) { - auto res = SqlToYql("USE plato;\n" - "\n" - "SELECT * FROM (SELECT 1 AS region_id)\n" - "FLATTEN BY (\n" - " CAST($unknown(region_id) AS List<String>) AS region\n" - ")"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:10: Error: Unknown name: $unknown\n"); - } +Y_UNIT_TEST(FlattenByExprWithNestedNull) { + auto res = SqlToYql("USE plato;\n" + "\n" + "SELECT * FROM (SELECT 1 AS region_id)\n" + "FLATTEN BY (\n" + " CAST($unknown(region_id) AS List<String>) AS region\n" + ")"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:10: Error: Unknown name: $unknown\n"); +} - Y_UNIT_TEST(EmptySymbolNameIsForbidden) { - auto req = " $`` = 1; select $``;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:5: Error: Empty symbol name is not allowed\n"); - } +Y_UNIT_TEST(EmptySymbolNameIsForbidden) { + auto req = " $`` = 1; select $``;"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:5: Error: Empty symbol name is not allowed\n"); +} - Y_UNIT_TEST(WarnOnBinaryOpWithNullArg) { - auto req = "select * from plato.Input where cast(key as Int32) != NULL"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:52: Warning: Binary operation != will return NULL here, code: 4529\n"); +Y_UNIT_TEST(WarnOnBinaryOpWithNullArg) { + auto req = "select * from plato.Input where cast(key as Int32) != NULL"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:52: Warning: Binary operation != will return NULL here, code: 4529\n"); - req = "select 1 or null"; - res = SqlToYql(req); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), ""); - } + req = "select 1 or null"; + res = SqlToYql(req); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), ""); +} - Y_UNIT_TEST(ErrorIfTableSampleArgUsesColumns) { - auto req = "SELECT key FROM plato.Input TABLESAMPLE BERNOULLI(MIN_OF(100.0, CAST(subkey as Int32)));"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:70: Error: Column reference \"subkey\" is not allowed in current scope\n"); - } +Y_UNIT_TEST(ErrorIfTableSampleArgUsesColumns) { + auto req = "SELECT key FROM plato.Input TABLESAMPLE BERNOULLI(MIN_OF(100.0, CAST(subkey as Int32)));"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:70: Error: Column reference \"subkey\" is not allowed in current scope\n"); +} - Y_UNIT_TEST(DerivedColumnListForSelectIsNotSupportedYet) { - auto req = "SELECT a,b,c FROM plato.Input as t(x,y,z);"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:35: Error: Derived column list is only supported for VALUES\n"); - } +Y_UNIT_TEST(DerivedColumnListForSelectIsNotSupportedYet) { + auto req = "SELECT a,b,c FROM plato.Input as t(x,y,z);"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:35: Error: Derived column list is only supported for VALUES\n"); +} - Y_UNIT_TEST(ErrorIfValuesHasDifferentCountOfColumns) { - auto req = "VALUES (1,2,3), (4,5);"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:17: Error: All VALUES items should have same size: expecting 3, got 2\n"); - } +Y_UNIT_TEST(ErrorIfValuesHasDifferentCountOfColumns) { + auto req = "VALUES (1,2,3), (4,5);"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:17: Error: All VALUES items should have same size: expecting 3, got 2\n"); +} - Y_UNIT_TEST(ErrorIfDerivedColumnSizeExceedValuesColumnCount) { - auto req = "SELECT * FROM(VALUES (1,2), (3,4)) as t(x,y,z);"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:40: Error: Derived column list size exceeds column count in VALUES\n"); - } +Y_UNIT_TEST(ErrorIfDerivedColumnSizeExceedValuesColumnCount) { + auto req = "SELECT * FROM(VALUES (1,2), (3,4)) as t(x,y,z);"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:40: Error: Derived column list size exceeds column count in VALUES\n"); +} - Y_UNIT_TEST(WarnoOnAutogeneratedNamesForValues) { - auto req = "PRAGMA WarnUnnamedColumns;\n" - "SELECT * FROM (VALUES (1,2,3,4), (5,6,7,8)) as t(x,y);"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:16: Warning: Autogenerated column names column2...column3 will be used here, code: 4516\n"); - } +Y_UNIT_TEST(WarnoOnAutogeneratedNamesForValues) { + auto req = "PRAGMA WarnUnnamedColumns;\n" + "SELECT * FROM (VALUES (1,2,3,4), (5,6,7,8)) as t(x,y);"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:16: Warning: Autogenerated column names column2...column3 will be used here, code: 4516\n"); +} - Y_UNIT_TEST(ErrUnionAllWithOrderByWithoutExplicitLegacyMode) { - auto req = "use plato;\n" - "\n" - "select * from Input order by key\n" - "union all\n" - "select * from Input order by key;"; +Y_UNIT_TEST(ErrUnionAllWithOrderByWithoutExplicitLegacyMode) { + auto req = "use plato;\n" + "\n" + "select * from Input order by key\n" + "union all\n" + "select * from Input order by key;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:21: Error: ORDER BY within UNION ALL is only allowed after last subquery\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:21: Error: ORDER BY within UNION ALL is only allowed after last subquery\n"); +} - Y_UNIT_TEST(ErrUnionAllWithLimitWithoutExplicitLegacyMode) { - auto req = "use plato;\n" - "\n" - "select * from Input limit 10\n" - "union all\n" - "select * from Input limit 1;"; +Y_UNIT_TEST(ErrUnionAllWithLimitWithoutExplicitLegacyMode) { + auto req = "use plato;\n" + "\n" + "select * from Input limit 10\n" + "union all\n" + "select * from Input limit 1;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:21: Error: LIMIT within UNION ALL is only allowed after last subquery\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:21: Error: LIMIT within UNION ALL is only allowed after last subquery\n"); +} - Y_UNIT_TEST(ErrUnionAllWithIntoResultWithoutExplicitLegacyMode) { - auto req = "use plato;\n" - "\n" - "select * from Input into result aaa\n" - "union all\n" - "select * from Input;"; +Y_UNIT_TEST(ErrUnionAllWithIntoResultWithoutExplicitLegacyMode) { + auto req = "use plato;\n" + "\n" + "select * from Input into result aaa\n" + "union all\n" + "select * from Input;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:21: Error: INTO RESULT within UNION ALL is only allowed after last subquery\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:21: Error: INTO RESULT within UNION ALL is only allowed after last subquery\n"); +} - Y_UNIT_TEST(ErrUnionAllWithDiscardWithoutExplicitLegacyMode) { - auto req = "use plato;\n" - "\n" - "select * from Input\n" - "union all\n" - "discard select * from Input;"; +Y_UNIT_TEST(ErrUnionAllWithDiscardWithoutExplicitLegacyMode) { + auto req = "use plato;\n" + "\n" + "select * from Input\n" + "union all\n" + "discard select * from Input;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:1: Error: DISCARD within UNION ALL is only allowed before first subquery\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:1: Error: DISCARD within UNION ALL is only allowed before first subquery\n"); +} - Y_UNIT_TEST(ErrUnionAllKeepsIgnoredOrderByWarning) { - auto req = "use plato;\n" - "\n" - "SELECT * FROM (\n" - " SELECT * FROM Input\n" - " UNION ALL\n" - " SELECT t.* FROM Input AS t ORDER BY t.key\n" - ");"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:3: Warning: ORDER BY without LIMIT in subquery will be ignored, code: 4504\n" - "<main>:6:39: Error: Unknown correlation name: t\n"); - } +Y_UNIT_TEST(ErrUnionAllKeepsIgnoredOrderByWarning) { + auto req = "use plato;\n" + "\n" + "SELECT * FROM (\n" + " SELECT * FROM Input\n" + " UNION ALL\n" + " SELECT t.* FROM Input AS t ORDER BY t.key\n" + ");"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:3: Warning: ORDER BY without LIMIT in subquery will be ignored, code: 4504\n" + "<main>:6:39: Error: Unknown correlation name: t\n"); +} - Y_UNIT_TEST(ErrOrderByIgnoredButCheckedForMissingColumns) { - auto req = "$src = SELECT key FROM (SELECT 1 as key, 2 as subkey) ORDER BY x; SELECT * FROM $src;"; - ExpectFailWithError(req, "<main>:1:8: Warning: ORDER BY without LIMIT in subquery will be ignored, code: 4504\n" - "<main>:1:64: Error: Column x is not in source column set\n"); +Y_UNIT_TEST(ErrOrderByIgnoredButCheckedForMissingColumns) { + auto req = "$src = SELECT key FROM (SELECT 1 as key, 2 as subkey) ORDER BY x; SELECT * FROM $src;"; + ExpectFailWithError(req, "<main>:1:8: Warning: ORDER BY without LIMIT in subquery will be ignored, code: 4504\n" + "<main>:1:64: Error: Column x is not in source column set\n"); - req = "$src = SELECT key FROM plato.Input ORDER BY x; SELECT * FROM $src;"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Warning: ORDER BY without LIMIT in subquery will be ignored, code: 4504\n"); - } + req = "$src = SELECT key FROM plato.Input ORDER BY x; SELECT * FROM $src;"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Warning: ORDER BY without LIMIT in subquery will be ignored, code: 4504\n"); +} - Y_UNIT_TEST(InvalidTtlInterval) { - auto req = R"( +Y_UNIT_TEST(InvalidTtlInterval) { + auto req = R"( USE plato; CREATE TABLE tableName (Key Uint32, CreatedAt Timestamp, PRIMARY KEY (Key)) WITH (TTL = 1 On CreatedAt); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:25: Error: Literal of Interval type is expected for TTL\n" - "<main>:4:25: Error: Invalid TTL settings\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:25: Error: Literal of Interval type is expected for TTL\n" + "<main>:4:25: Error: Invalid TTL settings\n"); +} - Y_UNIT_TEST(InvalidTtlUnit) { - auto req = R"( +Y_UNIT_TEST(InvalidTtlUnit) { + auto req = R"( USE plato; CREATE TABLE tableName (Key Uint32, CreatedAt Uint32, PRIMARY KEY (Key)) WITH (TTL = Interval("P1D") On CreatedAt AS PICOSECONDS); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_STRING_CONTAINS(Err2Str(res), "<main>:4:56: Error: Unexpected token 'PICOSECONDS'"); + UNIT_ASSERT_STRING_CONTAINS(Err2Str(res), "<main>:4:56: Error: Unexpected token 'PICOSECONDS'"); #else - UNIT_ASSERT_STRING_CONTAINS(Err2Str(res), "mismatched input 'PICOSECONDS' expecting {MICROSECONDS, MILLISECONDS, NANOSECONDS, SECONDS}"); + UNIT_ASSERT_STRING_CONTAINS(Err2Str(res), "mismatched input 'PICOSECONDS' expecting {MICROSECONDS, MILLISECONDS, NANOSECONDS, SECONDS}"); #endif - } +} - Y_UNIT_TEST(InvalidChangefeedSink) { - auto req = R"( +Y_UNIT_TEST(InvalidChangefeedSink) { + auto req = R"( USE plato; CREATE TABLE tableName ( Key Uint32, PRIMARY KEY (Key), CHANGEFEED feedName WITH (SINK_TYPE = "S3", MODE = "KEYS_ONLY", FORMAT = "json") ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:55: Error: Unknown changefeed sink type: S3\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:55: Error: Unknown changefeed sink type: S3\n"); +} - Y_UNIT_TEST(InvalidChangefeedSettings) { - auto req = R"( +Y_UNIT_TEST(InvalidChangefeedSettings) { + auto req = R"( USE plato; CREATE TABLE tableName ( Key Uint32, PRIMARY KEY (Key), CHANGEFEED feedName WITH (SINK_TYPE = "local", FOO = "bar") ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:64: Error: Unknown changefeed setting: FOO\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:64: Error: Unknown changefeed setting: FOO\n"); +} - Y_UNIT_TEST(InvalidChangefeedInitialScan) { - auto req = R"( +Y_UNIT_TEST(InvalidChangefeedInitialScan) { + auto req = R"( USE plato; CREATE TABLE tableName ( Key Uint32, PRIMARY KEY (Key), CHANGEFEED feedName WITH (MODE = "KEYS_ONLY", FORMAT = "json", INITIAL_SCAN = "foo") ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:95: Error: Literal of Bool type is expected for INITIAL_SCAN\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:95: Error: Literal of Bool type is expected for INITIAL_SCAN\n"); +} - Y_UNIT_TEST(InvalidChangefeedVirtualTimestamps) { - auto req = R"( +Y_UNIT_TEST(InvalidChangefeedVirtualTimestamps) { + auto req = R"( USE plato; CREATE TABLE tableName ( Key Uint32, PRIMARY KEY (Key), CHANGEFEED feedName WITH (MODE = "KEYS_ONLY", FORMAT = "json", VIRTUAL_TIMESTAMPS = "foo") ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:101: Error: Literal of Bool type is expected for VIRTUAL_TIMESTAMPS\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:101: Error: Literal of Bool type is expected for VIRTUAL_TIMESTAMPS\n"); +} - Y_UNIT_TEST(InvalidChangefeedResolvedTimestamps) { - auto req = R"( +Y_UNIT_TEST(InvalidChangefeedResolvedTimestamps) { + auto req = R"( USE plato; CREATE TABLE tableName ( Key Uint32, PRIMARY KEY (Key), CHANGEFEED feedName WITH (MODE = "KEYS_ONLY", FORMAT = "json", BARRIERS_INTERVAL = "foo") ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:100: Error: Literal of Interval type is expected for BARRIERS_INTERVAL\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:100: Error: Literal of Interval type is expected for BARRIERS_INTERVAL\n"); +} - Y_UNIT_TEST(InvalidChangefeedSchemaChanges) { - auto req = R"( +Y_UNIT_TEST(InvalidChangefeedSchemaChanges) { + auto req = R"( USE plato; CREATE TABLE tableName ( Key Uint32, PRIMARY KEY (Key), CHANGEFEED feedName WITH (MODE = "KEYS_ONLY", FORMAT = "json", SCHEMA_CHANGES = "foo") ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:97: Error: Literal of Bool type is expected for SCHEMA_CHANGES\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:97: Error: Literal of Bool type is expected for SCHEMA_CHANGES\n"); +} - Y_UNIT_TEST(InvalidChangefeedRetentionPeriod) { - auto req = R"( +Y_UNIT_TEST(InvalidChangefeedRetentionPeriod) { + auto req = R"( USE plato; CREATE TABLE tableName ( Key Uint32, PRIMARY KEY (Key), CHANGEFEED feedName WITH (MODE = "KEYS_ONLY", FORMAT = "json", RETENTION_PERIOD = "foo") ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:99: Error: Literal of Interval type is expected for RETENTION_PERIOD\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:99: Error: Literal of Interval type is expected for RETENTION_PERIOD\n"); +} - Y_UNIT_TEST(InvalidChangefeedTopicPartitions) { - auto req = R"( +Y_UNIT_TEST(InvalidChangefeedTopicPartitions) { + auto req = R"( USE plato; CREATE TABLE tableName ( Key Uint32, PRIMARY KEY (Key), CHANGEFEED feedName WITH (MODE = "KEYS_ONLY", FORMAT = "json", TOPIC_MIN_ACTIVE_PARTITIONS = "foo") ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:110: Error: Literal of integer type is expected for TOPIC_MIN_ACTIVE_PARTITIONS\n"); - } + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:110: Error: Literal of integer type is expected for TOPIC_MIN_ACTIVE_PARTITIONS\n"); +} - Y_UNIT_TEST(InvalidChangefeedAwsRegion) { - auto req = R"( +Y_UNIT_TEST(InvalidChangefeedAwsRegion) { + auto req = R"( USE plato; CREATE TABLE tableName ( Key Uint32, PRIMARY KEY (Key), CHANGEFEED feedName WITH (MODE = "KEYS_ONLY", FORMAT = "json", AWS_REGION = true) ); )"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:93: Error: Literal of String type is expected for AWS_REGION\n"); - } - - Y_UNIT_TEST(ErrJoinWithGroupingSetsWithoutCorrelationName) { - auto req = "USE plato;\n" - "\n" - "SELECT k1, k2, subkey\n" - "FROM T1 AS a JOIN T2 AS b USING (key)\n" - "GROUP BY GROUPING SETS(\n" - " (a.key as k1, b.subkey as k2),\n" - " (k1),\n" - " (subkey)\n" - ");"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:8:4: Error: Columns in grouping sets should have correlation name, error in key: subkey\n"); - } - - Y_UNIT_TEST(ErrJoinWithGroupByWithoutCorrelationName) { - auto req = "USE plato;\n" - "\n" - "SELECT k1, k2,\n" - " value\n" - "FROM T1 AS a JOIN T2 AS b USING (key)\n" - "GROUP BY a.key as k1, b.subkey as k2,\n" - " value;"; - ExpectFailWithError(req, - "<main>:7:5: Error: Columns in GROUP BY should have correlation name, error in key: value\n"); - } - - Y_UNIT_TEST(ErrWithMissingFrom) { - auto req = "select 1 as key where 1 > 1;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:25: Error: Filtering is not allowed without FROM\n"); + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:5:93: Error: Literal of String type is expected for AWS_REGION\n"); +} - req = "select 1 + count(*);"; - res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Aggregation is not allowed without FROM\n"); +Y_UNIT_TEST(ErrJoinWithGroupingSetsWithoutCorrelationName) { + auto req = "USE plato;\n" + "\n" + "SELECT k1, k2, subkey\n" + "FROM T1 AS a JOIN T2 AS b USING (key)\n" + "GROUP BY GROUPING SETS(\n" + " (a.key as k1, b.subkey as k2),\n" + " (k1),\n" + " (subkey)\n" + ");"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:8:4: Error: Columns in grouping sets should have correlation name, error in key: subkey\n"); +} - req = "select 1 as key, subkey + value;"; - res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Column references are not allowed without FROM\n" - "<main>:1:18: Error: Column reference 'subkey'\n" - "<main>:1:1: Error: Column references are not allowed without FROM\n" - "<main>:1:27: Error: Column reference 'value'\n"); +Y_UNIT_TEST(ErrJoinWithGroupByWithoutCorrelationName) { + auto req = "USE plato;\n" + "\n" + "SELECT k1, k2,\n" + " value\n" + "FROM T1 AS a JOIN T2 AS b USING (key)\n" + "GROUP BY a.key as k1, b.subkey as k2,\n" + " value;"; + ExpectFailWithError(req, + "<main>:7:5: Error: Columns in GROUP BY should have correlation name, error in key: value\n"); +} - req = "select count(1) group by key;"; - res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Column references are not allowed without FROM\n" - "<main>:1:26: Error: Column reference 'key'\n"); - } +Y_UNIT_TEST(ErrWithMissingFrom) { + auto req = "select 1 as key where 1 > 1;"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:25: Error: Filtering is not allowed without FROM\n"); + + req = "select 1 + count(*);"; + res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:12: Error: Aggregation is not allowed without FROM\n"); + + req = "select 1 as key, subkey + value;"; + res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Column references are not allowed without FROM\n" + "<main>:1:18: Error: Column reference 'subkey'\n" + "<main>:1:1: Error: Column references are not allowed without FROM\n" + "<main>:1:27: Error: Column reference 'value'\n"); + + req = "select count(1) group by key;"; + res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:1: Error: Column references are not allowed without FROM\n" + "<main>:1:26: Error: Column reference 'key'\n"); +} - Y_UNIT_TEST(ErrWithMissingFromForWindow) { - auto req = "$c = () -> (1 + count(1) over w);\n" - "select $c();"; - ExpectFailWithError(req, - "<main>:1:9: Error: Window and aggregation functions are not allowed in this context\n" - "<main>:1:17: Error: Failed to use aggregation function Count without window specification or in wrong place\n"); - - req = "$c = () -> (1 + lead(1) over w);\n" - "select $c();"; - ExpectFailWithError(req, - "<main>:1:17: Error: Window functions are not allowed in this context\n" - "<main>:1:17: Error: Failed to use window function Lead without window specification or in wrong place\n"); - - req = "select 1 + count(1) over w window w as ();"; - ExpectFailWithError(req, - "<main>:1:1: Error: Window and aggregation functions are not allowed without FROM\n" - "<main>:1:12: Error: Failed to use aggregation function Count without window specification or in wrong place\n"); - - req = "select 1 + lead(1) over w window w as ();"; - ExpectFailWithError(req, - "<main>:1:12: Error: Window functions are not allowed without FROM\n" - "<main>:1:12: Error: Failed to use window function Lead without window specification or in wrong place\n"); - } +Y_UNIT_TEST(ErrWithMissingFromForWindow) { + auto req = "$c = () -> (1 + count(1) over w);\n" + "select $c();"; + ExpectFailWithError(req, + "<main>:1:9: Error: Window and aggregation functions are not allowed in this context\n" + "<main>:1:17: Error: Failed to use aggregation function Count without window specification or in wrong place\n"); + + req = "$c = () -> (1 + lead(1) over w);\n" + "select $c();"; + ExpectFailWithError(req, + "<main>:1:17: Error: Window functions are not allowed in this context\n" + "<main>:1:17: Error: Failed to use window function Lead without window specification or in wrong place\n"); + + req = "select 1 + count(1) over w window w as ();"; + ExpectFailWithError(req, + "<main>:1:1: Error: Window and aggregation functions are not allowed without FROM\n" + "<main>:1:12: Error: Failed to use aggregation function Count without window specification or in wrong place\n"); + + req = "select 1 + lead(1) over w window w as ();"; + ExpectFailWithError(req, + "<main>:1:12: Error: Window functions are not allowed without FROM\n" + "<main>:1:12: Error: Failed to use window function Lead without window specification or in wrong place\n"); +} - Y_UNIT_TEST(ErrWithMissingFromForInplaceWindow) { - auto req = "$c = () -> (1 + count(1) over ());\n" - "select $c();"; - ExpectFailWithError(req, - "<main>:1:26: Error: Window and aggregation functions are not allowed in this context\n"); - - req = "$c = () -> (1 + lead(1) over (rows between unbounded preceding and current row));\n" - "select $c();"; - ExpectFailWithError(req, - "<main>:1:25: Error: Window and aggregation functions are not allowed in this context\n"); - - req = "select 1 + count(1) over ();"; - ExpectFailWithError(req, - "<main>:1:1: Error: Window and aggregation functions are not allowed without FROM\n" - "<main>:1:12: Error: Failed to use aggregation function Count without window specification or in wrong place\n"); - - req = "select 1 + lead(1) over (rows between current row and unbounded following);"; - ExpectFailWithError(req, - "<main>:1:12: Error: Window functions are not allowed without FROM\n" - "<main>:1:12: Error: Failed to use window function Lead without window specification or in wrong place\n"); - } +Y_UNIT_TEST(ErrWithMissingFromForInplaceWindow) { + auto req = "$c = () -> (1 + count(1) over ());\n" + "select $c();"; + ExpectFailWithError(req, + "<main>:1:26: Error: Window and aggregation functions are not allowed in this context\n"); + + req = "$c = () -> (1 + lead(1) over (rows between unbounded preceding and current row));\n" + "select $c();"; + ExpectFailWithError(req, + "<main>:1:25: Error: Window and aggregation functions are not allowed in this context\n"); + + req = "select 1 + count(1) over ();"; + ExpectFailWithError(req, + "<main>:1:1: Error: Window and aggregation functions are not allowed without FROM\n" + "<main>:1:12: Error: Failed to use aggregation function Count without window specification or in wrong place\n"); + + req = "select 1 + lead(1) over (rows between current row and unbounded following);"; + ExpectFailWithError(req, + "<main>:1:12: Error: Window functions are not allowed without FROM\n" + "<main>:1:12: Error: Failed to use window function Lead without window specification or in wrong place\n"); +} - Y_UNIT_TEST(ErrDistinctInWrongPlace) { - auto req = "select Some::Udf(distinct key) from plato.Input;"; - ExpectFailWithError(req, - "<main>:1:18: Error: DISTINCT can only be used in aggregation functions\n"); - req = "select sum(key)(distinct foo) from plato.Input;"; - ExpectFailWithError(req, - "<main>:1:17: Error: DISTINCT can only be used in aggregation functions\n"); - - req = "select len(distinct foo) from plato.Input;"; - ExpectFailWithError(req, - "<main>:1:8: Error: DISTINCT can only be used in aggregation functions\n"); - - req = "$foo = ($x) -> ($x); select $foo(distinct key) from plato.Input;"; - ExpectFailWithError(req, - "<main>:1:34: Error: DISTINCT can only be used in aggregation functions\n"); - } +Y_UNIT_TEST(ErrDistinctInWrongPlace) { + auto req = "select Some::Udf(distinct key) from plato.Input;"; + ExpectFailWithError(req, + "<main>:1:18: Error: DISTINCT can only be used in aggregation functions\n"); + req = "select sum(key)(distinct foo) from plato.Input;"; + ExpectFailWithError(req, + "<main>:1:17: Error: DISTINCT can only be used in aggregation functions\n"); + + req = "select len(distinct foo) from plato.Input;"; + ExpectFailWithError(req, + "<main>:1:8: Error: DISTINCT can only be used in aggregation functions\n"); + + req = "$foo = ($x) -> ($x); select $foo(distinct key) from plato.Input;"; + ExpectFailWithError(req, + "<main>:1:34: Error: DISTINCT can only be used in aggregation functions\n"); +} - Y_UNIT_TEST(ErrForNotSingleChildInInlineAST) { - ExpectFailWithError("select YQL::\"\"", - "<main>:1:8: Error: Failed to parse YQL: expecting AST root node with single child, but got 0\n"); - ExpectFailWithError("select YQL::@@ \t@@", - "<main>:1:8: Error: Failed to parse YQL: expecting AST root node with single child, but got 0\n"); - auto req = "$lambda = YQL::@@(lambda '(x)(+ x x)) (lambda '(y)(+ y y))@@;\n" - "select ListMap([1, 2, 3], $lambda);"; - ExpectFailWithError(req, - "<main>:1:11: Error: Failed to parse YQL: expecting AST root node with single child, but got 2\n"); - } +Y_UNIT_TEST(ErrForNotSingleChildInInlineAST) { + ExpectFailWithError("select YQL::\"\"", + "<main>:1:8: Error: Failed to parse YQL: expecting AST root node with single child, but got 0\n"); + ExpectFailWithError("select YQL::@@ \t@@", + "<main>:1:8: Error: Failed to parse YQL: expecting AST root node with single child, but got 0\n"); + auto req = "$lambda = YQL::@@(lambda '(x)(+ x x)) (lambda '(y)(+ y y))@@;\n" + "select ListMap([1, 2, 3], $lambda);"; + ExpectFailWithError(req, + "<main>:1:11: Error: Failed to parse YQL: expecting AST root node with single child, but got 2\n"); +} - Y_UNIT_TEST(ErrEmptyColumnName) { - ExpectFailWithError("select * without \"\" from plato.Input", - "<main>:1:18: Error: String literal can not be used here\n"); +Y_UNIT_TEST(ErrEmptyColumnName) { + ExpectFailWithError("select * without \"\" from plato.Input", + "<main>:1:18: Error: String literal can not be used here\n"); - ExpectFailWithError("select * without `` from plato.Input;", - "<main>:1:18: Error: Empty column name is not allowed\n"); + ExpectFailWithError("select * without `` from plato.Input;", + "<main>:1:18: Error: Empty column name is not allowed\n"); - ExpectFailWithErrorForAnsiLexer("select * without \"\" from plato.Input", - "<main>:1:18: Error: Empty column name is not allowed\n"); + ExpectFailWithErrorForAnsiLexer("select * without \"\" from plato.Input", + "<main>:1:18: Error: Empty column name is not allowed\n"); - ExpectFailWithErrorForAnsiLexer("select * without `` from plato.Input;", - "<main>:1:18: Error: Empty column name is not allowed\n"); - } + ExpectFailWithErrorForAnsiLexer("select * without `` from plato.Input;", + "<main>:1:18: Error: Empty column name is not allowed\n"); +} - Y_UNIT_TEST(ErrOnNonZeroArgumentsForTableRows) { - ExpectFailWithError("$udf=\"\";process plato.Input using $udf(TableRows(k))", - "<main>:1:40: Error: TableRows requires exactly 0 arguments\n"); - } +Y_UNIT_TEST(ErrOnNonZeroArgumentsForTableRows) { + ExpectFailWithError("$udf=\"\";process plato.Input using $udf(TableRows(k))", + "<main>:1:40: Error: TableRows requires exactly 0 arguments\n"); +} - Y_UNIT_TEST(ErrGroupByWithAggregationFunctionAndDistinctExpr) { - ExpectFailWithError("select * from plato.Input group by count(distinct key|key)", - "<main>:1:36: Error: Unable to GROUP BY aggregated values\n"); - } +Y_UNIT_TEST(ErrGroupByWithAggregationFunctionAndDistinctExpr) { + ExpectFailWithError("select * from plato.Input group by count(distinct key|key)", + "<main>:1:36: Error: Unable to GROUP BY aggregated values\n"); +} - // FIXME: check if we can get old behaviour +// FIXME: check if we can get old behaviour #if 0 Y_UNIT_TEST(ErrWithSchemaWithColumnsWithoutType) { ExpectFailWithError("select * from plato.Input with COLUMNs", @@ -6466,83 +6415,83 @@ select FormatType($f()); } #endif - Y_UNIT_TEST(ErrCollectPreaggregatedInListLiteralWithoutFrom) { - ExpectFailWithError("SELECT([VARIANCE(DISTINCT[])])", - "<main>:1:1: Error: Column references are not allowed without FROM\n" - "<main>:1:9: Error: Column reference '_yql_preagg_Variance0'\n"); - } +Y_UNIT_TEST(ErrCollectPreaggregatedInListLiteralWithoutFrom) { + ExpectFailWithError("SELECT([VARIANCE(DISTINCT[])])", + "<main>:1:1: Error: Column references are not allowed without FROM\n" + "<main>:1:9: Error: Column reference '_yql_preagg_Variance0'\n"); +} - Y_UNIT_TEST(ErrGroupBySmartParenAsTuple) { - ExpectFailWithError("SELECT * FROM plato.Input GROUP BY (k, v,)", - "<main>:1:41: Error: Unexpected trailing comma in grouping elements list\n"); - } +Y_UNIT_TEST(ErrGroupBySmartParenAsTuple) { + ExpectFailWithError("SELECT * FROM plato.Input GROUP BY (k, v,)", + "<main>:1:41: Error: Unexpected trailing comma in grouping elements list\n"); +} - Y_UNIT_TEST(HandleNestedSmartParensInGroupBy) { - ExpectFailWithError("SELECT * FROM plato.Input GROUP BY (+() as k)", - "<main>:1:37: Error: Unable to GROUP BY constant expression\n"); - } +Y_UNIT_TEST(HandleNestedSmartParensInGroupBy) { + ExpectFailWithError("SELECT * FROM plato.Input GROUP BY (+() as k)", + "<main>:1:37: Error: Unable to GROUP BY constant expression\n"); +} - Y_UNIT_TEST(ErrRenameWithAddColumn) { - ExpectFailWithError("USE plato; ALTER TABLE table RENAME TO moved, ADD COLUMN addc uint64", - "<main>:1:40: Error: RENAME TO can not be used together with another table action\n"); - } +Y_UNIT_TEST(ErrRenameWithAddColumn) { + ExpectFailWithError("USE plato; ALTER TABLE table RENAME TO moved, ADD COLUMN addc uint64", + "<main>:1:40: Error: RENAME TO can not be used together with another table action\n"); +} - Y_UNIT_TEST(ErrAddColumnAndRename) { - // FIXME: fix positions in ALTER TABLE - ExpectFailWithError("USE plato; ALTER TABLE table ADD COLUMN addc uint64, RENAME TO moved", - "<main>:1:46: Error: RENAME TO can not be used together with another table action\n"); - } +Y_UNIT_TEST(ErrAddColumnAndRename) { + // FIXME: fix positions in ALTER TABLE + ExpectFailWithError("USE plato; ALTER TABLE table ADD COLUMN addc uint64, RENAME TO moved", + "<main>:1:46: Error: RENAME TO can not be used together with another table action\n"); +} - Y_UNIT_TEST(InvalidUuidValue) { - ExpectFailWithError("SELECT Uuid('123e4567ae89ba12d3aa456a426614174ab0')", - "<main>:1:8: Error: Invalid value \"123e4567ae89ba12d3aa456a426614174ab0\" for type Uuid\n"); - ExpectFailWithError("SELECT Uuid('123e4567ae89b-12d3-a456-426614174000')", - "<main>:1:8: Error: Invalid value \"123e4567ae89b-12d3-a456-426614174000\" for type Uuid\n"); - } +Y_UNIT_TEST(InvalidUuidValue) { + ExpectFailWithError("SELECT Uuid('123e4567ae89ba12d3aa456a426614174ab0')", + "<main>:1:8: Error: Invalid value \"123e4567ae89ba12d3aa456a426614174ab0\" for type Uuid\n"); + ExpectFailWithError("SELECT Uuid('123e4567ae89b-12d3-a456-426614174000')", + "<main>:1:8: Error: Invalid value \"123e4567ae89b-12d3-a456-426614174000\" for type Uuid\n"); +} - Y_UNIT_TEST(WindowFunctionWithoutOver) { - ExpectFailWithError("SELECT LAST_VALUE(foo) FROM plato.Input", - "<main>:1:8: Error: Can't use window function LastValue without window specification (OVER keyword is missing)\n"); - ExpectFailWithError("SELECT LAST_VALUE(foo) FROM plato.Input GROUP BY key", - "<main>:1:8: Error: Can't use window function LastValue without window specification (OVER keyword is missing)\n"); - } +Y_UNIT_TEST(WindowFunctionWithoutOver) { + ExpectFailWithError("SELECT LAST_VALUE(foo) FROM plato.Input", + "<main>:1:8: Error: Can't use window function LastValue without window specification (OVER keyword is missing)\n"); + ExpectFailWithError("SELECT LAST_VALUE(foo) FROM plato.Input GROUP BY key", + "<main>:1:8: Error: Can't use window function LastValue without window specification (OVER keyword is missing)\n"); +} - Y_UNIT_TEST(CreateAlterUserWithoutCluster) { - ExpectFailWithError("\n CREATE USER user ENCRYPTED PASSWORD 'foobar';", "<main>:2:2: Error: USE statement is missing - no default cluster is selected\n"); - ExpectFailWithError("ALTER USER CURRENT_USER RENAME TO $foo;", "<main>:1:1: Error: USE statement is missing - no default cluster is selected\n"); - } +Y_UNIT_TEST(CreateAlterUserWithoutCluster) { + ExpectFailWithError("\n CREATE USER user ENCRYPTED PASSWORD 'foobar';", "<main>:2:2: Error: USE statement is missing - no default cluster is selected\n"); + ExpectFailWithError("ALTER USER CURRENT_USER RENAME TO $foo;", "<main>:1:1: Error: USE statement is missing - no default cluster is selected\n"); +} - Y_UNIT_TEST(ModifyPermissionsWithoutCluster) { - ExpectFailWithError("\n GRANT CONNECT ON `/Root` TO user;", "<main>:2:2: Error: USE statement is missing - no default cluster is selected\n"); - ExpectFailWithError("\n REVOKE MANAGE ON `/Root` FROM user;", "<main>:2:2: Error: USE statement is missing - no default cluster is selected\n"); - } +Y_UNIT_TEST(ModifyPermissionsWithoutCluster) { + ExpectFailWithError("\n GRANT CONNECT ON `/Root` TO user;", "<main>:2:2: Error: USE statement is missing - no default cluster is selected\n"); + ExpectFailWithError("\n REVOKE MANAGE ON `/Root` FROM user;", "<main>:2:2: Error: USE statement is missing - no default cluster is selected\n"); +} - Y_UNIT_TEST(ReservedRoleNames) { - ExpectFailWithError("USE plato; CREATE USER current_User;", "<main>:1:24: Error: System role CURRENT_USER can not be used here\n"); - ExpectFailWithError("USE plato; ALTER USER current_User RENAME TO Current_role", "<main>:1:46: Error: System role CURRENT_ROLE can not be used here\n"); - UNIT_ASSERT(SqlToYql("USE plato; DROP GROUP IF EXISTS a, b, c, current_User;").IsOk()); - } +Y_UNIT_TEST(ReservedRoleNames) { + ExpectFailWithError("USE plato; CREATE USER current_User;", "<main>:1:24: Error: System role CURRENT_USER can not be used here\n"); + ExpectFailWithError("USE plato; ALTER USER current_User RENAME TO Current_role", "<main>:1:46: Error: System role CURRENT_ROLE can not be used here\n"); + UNIT_ASSERT(SqlToYql("USE plato; DROP GROUP IF EXISTS a, b, c, current_User;").IsOk()); +} - Y_UNIT_TEST(DisableClassicDivisionWithError) { - ExpectFailWithError("pragma ClassicDivision = 'false'; select $foo / 30;", "<main>:1:42: Error: Unknown name: $foo\n"); - } +Y_UNIT_TEST(DisableClassicDivisionWithError) { + ExpectFailWithError("pragma ClassicDivision = 'false'; select $foo / 30;", "<main>:1:42: Error: Unknown name: $foo\n"); +} - Y_UNIT_TEST(AggregationOfAgrregatedDistinctExpr) { - ExpectFailWithError("select sum(sum(distinct x + 1)) from plato.Input", "<main>:1:12: Error: Aggregation of aggregated values is forbidden\n"); - } +Y_UNIT_TEST(AggregationOfAgrregatedDistinctExpr) { + ExpectFailWithError("select sum(sum(distinct x + 1)) from plato.Input", "<main>:1:12: Error: Aggregation of aggregated values is forbidden\n"); +} - Y_UNIT_TEST(WarnForUnusedSqlHint) { - NYql::TAstParseResult res = SqlToYql("select * from plato.Input1 as a join /*+ merge() */ plato.Input2 as b using(key);\n" - "select --+ foo(bar)\n" - " 1;"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:23: Warning: Hint foo will not be used, code: 4534\n"); - } +Y_UNIT_TEST(WarnForUnusedSqlHint) { + NYql::TAstParseResult res = SqlToYql("select * from plato.Input1 as a join /*+ merge() */ plato.Input2 as b using(key);\n" + "select --+ foo(bar)\n" + " 1;"); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:23: Warning: Hint foo will not be used, code: 4534\n"); +} - Y_UNIT_TEST(WarnForUnusedSqlHintAsError) { - NSQLTranslation::TTranslationSettings settings; +Y_UNIT_TEST(WarnForUnusedSqlHintAsError) { + NSQLTranslation::TTranslationSettings settings; - TString query = R"sql( + TString query = R"sql( pragma warning("error", "*"); select * from plato.Input1 as a @@ -6551,49 +6500,49 @@ select FormatType($f()); 1; )sql"; - NYql::TAstParseResult res = SqlToYqlWithSettings(query, settings); - UNIT_ASSERT_C(!res.IsOk(), res.Issues.ToString()); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:6:35: Error: Hint foo will not be used, code: 4534\n"); - } + NYql::TAstParseResult res = SqlToYqlWithSettings(query, settings); + UNIT_ASSERT_C(!res.IsOk(), res.Issues.ToString()); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:6:35: Error: Hint foo will not be used, code: 4534\n"); +} - Y_UNIT_TEST(WarnForDeprecatedSchema) { - NSQLTranslation::TTranslationSettings settings; - settings.ClusterMapping["s3bucket"] = NYql::S3ProviderName; - NYql::TAstParseResult res = SqlToYqlWithSettings("select * from s3bucket.`foo` with schema (col1 Int32, String as col2, Int64 as col3);", settings); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "Warning: Deprecated syntax for positional schema: please use 'column type' instead of 'type AS column', code: 4535\n"); - } +Y_UNIT_TEST(WarnForDeprecatedSchema) { + NSQLTranslation::TTranslationSettings settings; + settings.ClusterMapping["s3bucket"] = NYql::S3ProviderName; + NYql::TAstParseResult res = SqlToYqlWithSettings("select * from s3bucket.`foo` with schema (col1 Int32, String as col2, Int64 as col3);", settings); + UNIT_ASSERT(res.Root); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "Warning: Deprecated syntax for positional schema: please use 'column type' instead of 'type AS column', code: 4535\n"); +} - Y_UNIT_TEST(ErrorOnColumnNameInMaxByLimit) { - ExpectFailWithError( - "SELECT AGGREGATE_BY(AsTuple(value, key), AggregationFactory(\"MAX_BY\", subkey)) FROM plato.Input;", - "<main>:1:42: Error: Source does not allow column references\n" - "<main>:1:71: Error: Column reference 'subkey'\n"); - } +Y_UNIT_TEST(ErrorOnColumnNameInMaxByLimit) { + ExpectFailWithError( + "SELECT AGGREGATE_BY(AsTuple(value, key), AggregationFactory(\"MAX_BY\", subkey)) FROM plato.Input;", + "<main>:1:42: Error: Source does not allow column references\n" + "<main>:1:71: Error: Column reference 'subkey'\n"); +} - Y_UNIT_TEST(ErrorInLibraryWithTopLevelNamedSubquery) { - TString withUnusedSubq = "$unused = select max(key) from plato.Input;\n" - "\n" - "define subquery $foo() as\n" - " $count = select count(*) from plato.Input;\n" - " select * from plato.Input limit $count / 2;\n" - "end define;\n" - "export $foo;\n"; - UNIT_ASSERT(SqlToYqlWithMode(withUnusedSubq, NSQLTranslation::ESqlMode::LIBRARY).IsOk()); - - TString withTopLevelSubq = "$count = select count(*) from plato.Input;\n" - "\n" - "define subquery $foo() as\n" - " select * from plato.Input limit $count / 2;\n" - "end define;\n" - "export $foo;\n"; - auto res = SqlToYqlWithMode(withTopLevelSubq, NSQLTranslation::ESqlMode::LIBRARY); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:17: Error: Named subquery can not be used as a top level statement in libraries\n"); - } +Y_UNIT_TEST(ErrorInLibraryWithTopLevelNamedSubquery) { + TString withUnusedSubq = "$unused = select max(key) from plato.Input;\n" + "\n" + "define subquery $foo() as\n" + " $count = select count(*) from plato.Input;\n" + " select * from plato.Input limit $count / 2;\n" + "end define;\n" + "export $foo;\n"; + UNIT_ASSERT(SqlToYqlWithMode(withUnusedSubq, NSQLTranslation::ESqlMode::LIBRARY).IsOk()); + + TString withTopLevelSubq = "$count = select count(*) from plato.Input;\n" + "\n" + "define subquery $foo() as\n" + " select * from plato.Input limit $count / 2;\n" + "end define;\n" + "export $foo;\n"; + auto res = SqlToYqlWithMode(withTopLevelSubq, NSQLTranslation::ESqlMode::LIBRARY); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:17: Error: Named subquery can not be used as a top level statement in libraries\n"); +} - Y_UNIT_TEST(SessionStartAndSessionStateShouldSurviveSessionWindowArgsError){ - TString query = R"( +Y_UNIT_TEST(SessionStartAndSessionStateShouldSurviveSessionWindowArgsError) { + TString query = R"( $init = ($_row) -> (min(1, 2)); -- error: aggregation func min() can not be used here $calculate = ($_row, $_state) -> (1); $update = ($_row, $_state) -> (2); @@ -6605,48 +6554,48 @@ select FormatType($f()); PARTITION BY user, SessionWindow(ts + 1, $init, $update, $calculate) ) )"; - ExpectFailWithError(query, "<main>:2:33: Error: Aggregation function Min requires exactly 1 argument(s), given: 2\n"); - } + ExpectFailWithError(query, "<main>:2:33: Error: Aggregation function Min requires exactly 1 argument(s), given: 2\n"); +} - Y_UNIT_TEST(ScalarContextUsage1) { - TString query = R"( +Y_UNIT_TEST(ScalarContextUsage1) { + TString query = R"( $a = (select 1 as x, 2 as y); select 1 + $a; )"; - ExpectFailWithError(query, "<main>:2:39: Error: Source used in expression should contain one concrete column\n" - "<main>:3:24: Error: Source is used here\n"); - } + ExpectFailWithError(query, "<main>:2:39: Error: Source used in expression should contain one concrete column\n" + "<main>:3:24: Error: Source is used here\n"); +} - Y_UNIT_TEST(ScalarContextUsage2) { - TString query = R"( +Y_UNIT_TEST(ScalarContextUsage2) { + TString query = R"( use plato; $a = (select 1 as x, 2 as y); select * from concat($a); )"; - ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" - "<main>:4:34: Error: Source is used here\n"); - } + ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" + "<main>:4:34: Error: Source is used here\n"); +} - Y_UNIT_TEST(ScalarContextUsage3) { - TString query = R"( +Y_UNIT_TEST(ScalarContextUsage3) { + TString query = R"( use plato; $a = (select 1 as x, 2 as y); select * from range($a); )"; - ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" - "<main>:4:33: Error: Source is used here\n"); - } + ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" + "<main>:4:33: Error: Source is used here\n"); +} - Y_UNIT_TEST(ScalarContextUsage4) { - TString query = R"( +Y_UNIT_TEST(ScalarContextUsage4) { + TString query = R"( use plato; $a = (select 1 as x, 2 as y); insert into $a select 1; )"; - ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" - "<main>:4:25: Error: Source is used here\n"); - } + ExpectFailWithError(query, "<main>:3:39: Error: Source used in expression should contain one concrete column\n" + "<main>:4:25: Error: Source is used here\n"); } +} // Y_UNIT_TEST_SUITE(SqlToYQLErrors) void CheckUnused(const TString& req, const TString& symbol, unsigned row, unsigned col) { auto res = SqlToYql(req); @@ -6656,565 +6605,556 @@ void CheckUnused(const TString& req, const TString& symbol, unsigned row, unsign } Y_UNIT_TEST_SUITE(WarnUnused) { - Y_UNIT_TEST(ActionOrSubquery) { - TString req = " $a()\n" - "as select 1;\n" - "end define;\n" - "\n" - "select 1;"; - CheckUnused("define action\n" + req, "$a", 2, 3); - CheckUnused("define subquery\n" + req, "$a", 2, 3); - } +Y_UNIT_TEST(ActionOrSubquery) { + TString req = " $a()\n" + "as select 1;\n" + "end define;\n" + "\n" + "select 1;"; + CheckUnused("define action\n" + req, "$a", 2, 3); + CheckUnused("define subquery\n" + req, "$a", 2, 3); +} - Y_UNIT_TEST(Import) { - TString req = "import lib1 symbols\n" - " $sqr;\n" - "select 1;"; - CheckUnused(req, "$sqr", 2, 3); - - req = "import lib1 symbols\n" - " $sqr as\n" - " $sq;\n" - "select 1;"; - CheckUnused(req, "$sq", 3, 5); - } +Y_UNIT_TEST(Import) { + TString req = "import lib1 symbols\n" + " $sqr;\n" + "select 1;"; + CheckUnused(req, "$sqr", 2, 3); + + req = "import lib1 symbols\n" + " $sqr as\n" + " $sq;\n" + "select 1;"; + CheckUnused(req, "$sq", 3, 5); +} - Y_UNIT_TEST(NamedNodeStatement) { - TString req = " $a, $a = AsTuple(1, 2);\n" - "select $a;"; - CheckUnused(req, "$a", 1, 2); - req = "$a, $b = AsTuple(1, 2);\n" - "select $a;"; - CheckUnused(req, "$b", 1, 6); - CheckUnused(" $a = 1; $a = 2; select $a;", "$a", 1, 2); - } +Y_UNIT_TEST(NamedNodeStatement) { + TString req = " $a, $a = AsTuple(1, 2);\n" + "select $a;"; + CheckUnused(req, "$a", 1, 2); + req = "$a, $b = AsTuple(1, 2);\n" + "select $a;"; + CheckUnused(req, "$b", 1, 6); + CheckUnused(" $a = 1; $a = 2; select $a;", "$a", 1, 2); +} - Y_UNIT_TEST(Declare) { - CheckUnused("declare $a as String;select 1;", "$a", 1, 9); - } +Y_UNIT_TEST(Declare) { + CheckUnused("declare $a as String;select 1;", "$a", 1, 9); +} - Y_UNIT_TEST(ActionParams) { - TString req = "define action $a($x, $y) as\n" - " select $x;\n" - "end define;\n" - "\n" - "do $a(1,2);"; - CheckUnused(req, "$y", 1, 22); - } +Y_UNIT_TEST(ActionParams) { + TString req = "define action $a($x, $y) as\n" + " select $x;\n" + "end define;\n" + "\n" + "do $a(1,2);"; + CheckUnused(req, "$y", 1, 22); +} - Y_UNIT_TEST(SubqueryParams) { - TString req = "use plato;\n" - "define subquery $q($name, $x) as\n" - " select * from $name;\n" - "end define;\n" - "\n" - "select * from $q(\"Input\", 1);"; - CheckUnused(req, "$x", 2, 27); - } +Y_UNIT_TEST(SubqueryParams) { + TString req = "use plato;\n" + "define subquery $q($name, $x) as\n" + " select * from $name;\n" + "end define;\n" + "\n" + "select * from $q(\"Input\", 1);"; + CheckUnused(req, "$x", 2, 27); +} - Y_UNIT_TEST(For) { - TString req = "define action $a() as\n" - " select 1;\n" - "end define;\n" - "\n" - "for $i in ListFromRange(1, 10)\n" - "do $a();"; - CheckUnused(req, "$i", 5, 5); - } +Y_UNIT_TEST(For) { + TString req = "define action $a() as\n" + " select 1;\n" + "end define;\n" + "\n" + "for $i in ListFromRange(1, 10)\n" + "do $a();"; + CheckUnused(req, "$i", 5, 5); +} - Y_UNIT_TEST(LambdaParams) { - TString req = "$lambda = ($x, $y) -> ($x);\n" - "select $lambda(1, 2);"; - CheckUnused(req, "$y", 1, 16); - } +Y_UNIT_TEST(LambdaParams) { + TString req = "$lambda = ($x, $y) -> ($x);\n" + "select $lambda(1, 2);"; + CheckUnused(req, "$y", 1, 16); +} - Y_UNIT_TEST(InsideLambdaBody) { - TString req = "$lambda = () -> {\n" - " $x = 1; return 1;\n" - "};\n" - "select $lambda();"; - CheckUnused(req, "$x", 2, 3); - req = "$lambda = () -> {\n" - " $x = 1; $x = 2; return $x;\n" - "};\n" - "select $lambda();"; - CheckUnused(req, "$x", 2, 3); - } +Y_UNIT_TEST(InsideLambdaBody) { + TString req = "$lambda = () -> {\n" + " $x = 1; return 1;\n" + "};\n" + "select $lambda();"; + CheckUnused(req, "$x", 2, 3); + req = "$lambda = () -> {\n" + " $x = 1; $x = 2; return $x;\n" + "};\n" + "select $lambda();"; + CheckUnused(req, "$x", 2, 3); +} - Y_UNIT_TEST(InsideAction) { - TString req = "define action $a() as\n" - " $x = 1; select 1;\n" - "end define;\n" - "\n" - "do $a();"; - CheckUnused(req, "$x", 2, 3); - req = "define action $a() as\n" - " $x = 1; $x = 2; select $x;\n" - "end define;\n" - "\n" - "do $a();"; - CheckUnused(req, "$x", 2, 3); - } +Y_UNIT_TEST(InsideAction) { + TString req = "define action $a() as\n" + " $x = 1; select 1;\n" + "end define;\n" + "\n" + "do $a();"; + CheckUnused(req, "$x", 2, 3); + req = "define action $a() as\n" + " $x = 1; $x = 2; select $x;\n" + "end define;\n" + "\n" + "do $a();"; + CheckUnused(req, "$x", 2, 3); +} - Y_UNIT_TEST(NoWarnOnNestedActions) { - auto req = "pragma warning(\"error\", \"4527\");\n" - "define action $action($b) as\n" - " define action $aaa() as\n" - " select $b;\n" - " end define;\n" - " do $aaa();\n" - "end define;\n" - "\n" - "do $action(1);"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(NoWarnOnNestedActions) { + auto req = "pragma warning(\"error\", \"4527\");\n" + "define action $action($b) as\n" + " define action $aaa() as\n" + " select $b;\n" + " end define;\n" + " do $aaa();\n" + "end define;\n" + "\n" + "do $action(1);"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(NoWarnForUsageAfterSubquery) { - auto req = "use plato;\n" - "pragma warning(\"error\", \"4527\");\n" - "\n" - "$a = 1;\n" - "\n" - "define subquery $q($table) as\n" - " select * from $table;\n" - "end define;\n" - "\n" - "select * from $q(\"Input\");\n" - "select $a;"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(NoWarnForUsageAfterSubquery) { + auto req = "use plato;\n" + "pragma warning(\"error\", \"4527\");\n" + "\n" + "$a = 1;\n" + "\n" + "define subquery $q($table) as\n" + " select * from $table;\n" + "end define;\n" + "\n" + "select * from $q(\"Input\");\n" + "select $a;"; + UNIT_ASSERT(SqlToYql(req).IsOk()); } +} // Y_UNIT_TEST_SUITE(WarnUnused) Y_UNIT_TEST_SUITE(AnonymousNames) { - Y_UNIT_TEST(ReferenceAnonymousVariableIsForbidden) { - auto req = "$_ = 1; select $_;"; +Y_UNIT_TEST(ReferenceAnonymousVariableIsForbidden) { + auto req = "$_ = 1; select $_;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:16: Error: Unable to reference anonymous name $_\n"); + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:16: Error: Unable to reference anonymous name $_\n"); - req = "$`_` = 1; select $`_`;"; - res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:18: Error: Unable to reference anonymous name $_\n"); - } + req = "$`_` = 1; select $`_`;"; + res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:18: Error: Unable to reference anonymous name $_\n"); +} - Y_UNIT_TEST(Declare) { - auto req = "declare $_ as String;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:9: Error: Can not use anonymous name '$_' in DECLARE statement\n"); - } +Y_UNIT_TEST(Declare) { + auto req = "declare $_ as String;"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:9: Error: Can not use anonymous name '$_' in DECLARE statement\n"); +} - Y_UNIT_TEST(ActionSubquery) { - auto req = "define action $_() as select 1; end define;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:15: Error: Can not use anonymous name '$_' as ACTION name\n"); +Y_UNIT_TEST(ActionSubquery) { + auto req = "define action $_() as select 1; end define;"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:15: Error: Can not use anonymous name '$_' as ACTION name\n"); - req = "define subquery $_() as select 1; end define;"; - res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:17: Error: Can not use anonymous name '$_' as SUBQUERY name\n"); - } + req = "define subquery $_() as select 1; end define;"; + res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:17: Error: Can not use anonymous name '$_' as SUBQUERY name\n"); +} - Y_UNIT_TEST(Import) { - auto req = "import lib symbols $sqr as $_;"; - auto res = SqlToYql(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:28: Error: Can not import anonymous name $_\n"); - } +Y_UNIT_TEST(Import) { + auto req = "import lib symbols $sqr as $_;"; + auto res = SqlToYql(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:28: Error: Can not import anonymous name $_\n"); +} - Y_UNIT_TEST(Export) { - auto req = "export $_;"; - auto res = SqlToYqlWithMode(req, NSQLTranslation::ESqlMode::LIBRARY); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Can not export anonymous name $_\n"); - } +Y_UNIT_TEST(Export) { + auto req = "export $_;"; + auto res = SqlToYqlWithMode(req, NSQLTranslation::ESqlMode::LIBRARY); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:8: Error: Can not export anonymous name $_\n"); +} - Y_UNIT_TEST(AnonymousInActionArgs) { - auto req = "pragma warning(\"error\", \"4527\");\n" - "define action $a($_, $y, $_) as\n" - " select $y;\n" - "end define;\n" - "\n" - "do $a(1,2,3);"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(AnonymousInActionArgs) { + auto req = "pragma warning(\"error\", \"4527\");\n" + "define action $a($_, $y, $_) as\n" + " select $y;\n" + "end define;\n" + "\n" + "do $a(1,2,3);"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(AnonymousInSubqueryArgs) { - auto req = "use plato;\n" - "pragma warning(\"error\", \"4527\");\n" - "define subquery $q($_, $y, $_) as\n" - " select * from $y;\n" - "end define;\n" - "\n" - "select * from $q(1,\"Input\",3);"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(AnonymousInSubqueryArgs) { + auto req = "use plato;\n" + "pragma warning(\"error\", \"4527\");\n" + "define subquery $q($_, $y, $_) as\n" + " select * from $y;\n" + "end define;\n" + "\n" + "select * from $q(1,\"Input\",3);"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(AnonymousInLambdaArgs) { - auto req = "pragma warning(\"error\", \"4527\");\n" - "$lambda = ($_, $x, $_) -> ($x);\n" - "select $lambda(1,2,3);"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(AnonymousInLambdaArgs) { + auto req = "pragma warning(\"error\", \"4527\");\n" + "$lambda = ($_, $x, $_) -> ($x);\n" + "select $lambda(1,2,3);"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(AnonymousInFor) { - auto req = "pragma warning(\"error\", \"4527\");\n" - "evaluate for $_ in ListFromRange(1, 10) do begin select 1; end do;"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(AnonymousInFor) { + auto req = "pragma warning(\"error\", \"4527\");\n" + "evaluate for $_ in ListFromRange(1, 10) do begin select 1; end do;"; + UNIT_ASSERT(SqlToYql(req).IsOk()); +} - Y_UNIT_TEST(Assignment) { - auto req = "pragma warning(\"error\", \"4527\");\n" - "$_ = 1;\n" - "$_, $x, $_ = AsTuple(1,2,3);\n" - "select $x;"; - UNIT_ASSERT(SqlToYql(req).IsOk()); - } +Y_UNIT_TEST(Assignment) { + auto req = "pragma warning(\"error\", \"4527\");\n" + "$_ = 1;\n" + "$_, $x, $_ = AsTuple(1,2,3);\n" + "select $x;"; + UNIT_ASSERT(SqlToYql(req).IsOk()); } +} // Y_UNIT_TEST_SUITE(AnonymousNames) Y_UNIT_TEST_SUITE(JsonValue) { - Y_UNIT_TEST(JsonValueArgumentCount) { - NYql::TAstParseResult res = SqlToYql("select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json));"); +Y_UNIT_TEST(JsonValueArgumentCount) { + NYql::TAstParseResult res = SqlToYql("select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json));"); - UNIT_ASSERT(!res.Root); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:49: Error: Unexpected token ')' : syntax error...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:49: Error: Unexpected token ')' : syntax error...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:49: Error: mismatched input ')' expecting ','\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:49: Error: mismatched input ')' expecting ','\n"); #endif - } +} - Y_UNIT_TEST(JsonValueJsonPathMustBeLiteralString) { - NYql::TAstParseResult res = SqlToYql("$jsonPath = \"strict $.key\"; select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), $jsonPath);"); +Y_UNIT_TEST(JsonValueJsonPathMustBeLiteralString) { + NYql::TAstParseResult res = SqlToYql("$jsonPath = \"strict $.key\"; select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), $jsonPath);"); - UNIT_ASSERT(!res.Root); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:79: Error: Unexpected token absence : Missing STRING_VALUE \n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:79: Error: Unexpected token absence : Missing STRING_VALUE \n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:79: Error: mismatched input '$' expecting STRING_VALUE\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:79: Error: mismatched input '$' expecting STRING_VALUE\n"); #endif - } +} + +Y_UNIT_TEST(JsonValueTranslation) { + NYql::TAstParseResult res = SqlToYql("select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\");"); + + UNIT_ASSERT(res.Root); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'\"strict $.key\"")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("SafeCast")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("DataType 'Json")); + }; + + TWordCountHive elementStat({"JsonValue"}); + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["JsonValue"]); +} - Y_UNIT_TEST(JsonValueTranslation) { - NYql::TAstParseResult res = SqlToYql("select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\");"); +Y_UNIT_TEST(JsonValueReturningSection) { + for (const auto& typeName : {"Bool", "Int64", "Double", "String"}) { + NYql::TAstParseResult res = SqlToYql( + TStringBuilder() << "select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\" RETURNING " << typeName << ");"); UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { Y_UNUSED(word); UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'\"strict $.key\"")); UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("SafeCast")); UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("DataType 'Json")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(TStringBuilder() << "DataType '" << typeName)); }; - TWordCountHive elementStat({"JsonValue"}); + TWordCountHive elementStat({typeName}); VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["JsonValue"]); + UNIT_ASSERT(elementStat[typeName] > 0); } +} - Y_UNIT_TEST(JsonValueReturningSection) { - for (const auto& typeName : {"Bool", "Int64", "Double", "String"}) { - NYql::TAstParseResult res = SqlToYql( - TStringBuilder() << "select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\" RETURNING " << typeName << ");" - ); +Y_UNIT_TEST(JsonValueInvalidReturningType) { + NYql::TAstParseResult res = SqlToYql("select JSON_VALUE(CAST(@@{'key': 1238}@@ as Json), 'strict $.key' RETURNING invalid);"); + + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:77: Error: Unknown simple type 'invalid'\n"); +} + +Y_UNIT_TEST(JsonValueAndReturningInExpressions) { + NYql::TAstParseResult res = SqlToYql( + "USE plato\n;" + "$json_value = \"some string\";\n" + "SELECT $json_value;\n" + "SELECT 1 as json_value;\n" + "SELECT $json_value as json_value;\n" + "$returning = \"another string\";\n" + "SELECT $returning;\n" + "SELECT 1 as returning;\n" + "SELECT $returning as returning;\n"); + + UNIT_ASSERT(res.Root); +} + +Y_UNIT_TEST(JsonValueValidCaseHandlers) { + const TVector<std::pair<TString, TString>> testCases = { + {"", "'DefaultValue (Null)"}, + {"NULL", "'DefaultValue (Null)"}, + {"ERROR", "'Error (Null)"}, + {"DEFAULT 123", "'DefaultValue (Int32 '\"123\")"}, + }; + + for (const auto& onEmpty : testCases) { + for (const auto& onError : testCases) { + TStringBuilder query; + query << "$json = CAST(@@{\"key\": 1238}@@ as Json);\n" + << "SELECT JSON_VALUE($json, \"strict $.key\""; + if (!onEmpty.first.empty()) { + query << " " << onEmpty.first << " ON EMPTY"; + } + if (!onError.first.empty()) { + query << " " << onError.first << " ON ERROR"; + } + query << ");\n"; + + NYql::TAstParseResult res = SqlToYql(query); UNIT_ASSERT(res.Root); TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'\"strict $.key\"")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("SafeCast")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("DataType 'Json")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(TStringBuilder() << "DataType '" << typeName)); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(onEmpty.second + " " + onError.second)); }; - TWordCountHive elementStat({typeName}); + TWordCountHive elementStat({"JsonValue"}); VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat[typeName] > 0); + UNIT_ASSERT(elementStat["JsonValue"] > 0); } } +} - Y_UNIT_TEST(JsonValueInvalidReturningType) { - NYql::TAstParseResult res = SqlToYql("select JSON_VALUE(CAST(@@{'key': 1238}@@ as Json), 'strict $.key' RETURNING invalid);"); - - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:77: Error: Unknown simple type 'invalid'\n"); - } - - Y_UNIT_TEST(JsonValueAndReturningInExpressions) { - NYql::TAstParseResult res = SqlToYql( - "USE plato\n;" - "$json_value = \"some string\";\n" - "SELECT $json_value;\n" - "SELECT 1 as json_value;\n" - "SELECT $json_value as json_value;\n" - "$returning = \"another string\";\n" - "SELECT $returning;\n" - "SELECT 1 as returning;\n" - "SELECT $returning as returning;\n" - ); - - UNIT_ASSERT(res.Root); - } +Y_UNIT_TEST(JsonValueTooManyCaseHandlers) { + NYql::TAstParseResult res = SqlToYql( + "select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\" NULL ON EMPTY NULL ON ERROR NULL ON EMPTY);\n"); - Y_UNIT_TEST(JsonValueValidCaseHandlers) { - const TVector<std::pair<TString, TString>> testCases = { - {"", "'DefaultValue (Null)"}, - {"NULL", "'DefaultValue (Null)"}, - {"ERROR", "'Error (Null)"}, - {"DEFAULT 123", "'DefaultValue (Int32 '\"123\")"}, - }; + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF( + Err2Str(res), + "<main>:1:52: Error: Only 1 ON EMPTY and/or 1 ON ERROR clause is expected\n"); +} - for (const auto& onEmpty : testCases) { - for (const auto& onError : testCases) { - TStringBuilder query; - query << "$json = CAST(@@{\"key\": 1238}@@ as Json);\n" - << "SELECT JSON_VALUE($json, \"strict $.key\""; - if (!onEmpty.first.empty()) { - query << " " << onEmpty.first << " ON EMPTY"; - } - if (!onError.first.empty()) { - query << " " << onError.first << " ON ERROR"; - } - query << ");\n"; +Y_UNIT_TEST(JsonValueTooManyOnEmpty) { + NYql::TAstParseResult res = SqlToYql( + "select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\" NULL ON EMPTY NULL ON EMPTY);\n"); - NYql::TAstParseResult res = SqlToYql(query); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF( + Err2Str(res), + "<main>:1:52: Error: Only 1 ON EMPTY clause is expected\n"); +} - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(JsonValueTooManyOnError) { + NYql::TAstParseResult res = SqlToYql( + "select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\" NULL ON ERROR NULL ON ERROR);\n"); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(onEmpty.second + " " + onError.second)); - }; + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF( + Err2Str(res), + "<main>:1:52: Error: Only 1 ON ERROR clause is expected\n"); +} - TWordCountHive elementStat({"JsonValue"}); - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat["JsonValue"] > 0); - } - } - } +Y_UNIT_TEST(JsonValueOnEmptyAfterOnError) { + NYql::TAstParseResult res = SqlToYql( + "select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\" NULL ON ERROR NULL ON EMPTY);\n"); - Y_UNIT_TEST(JsonValueTooManyCaseHandlers) { - NYql::TAstParseResult res = SqlToYql( - "select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\" NULL ON EMPTY NULL ON ERROR NULL ON EMPTY);\n" - ); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF( + Err2Str(res), + "<main>:1:52: Error: ON EMPTY clause must be before ON ERROR clause\n"); +} - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF( - Err2Str(res), - "<main>:1:52: Error: Only 1 ON EMPTY and/or 1 ON ERROR clause is expected\n" - ); - } +Y_UNIT_TEST(JsonValueNullInput) { + NYql::TAstParseResult res = SqlToYql(R"(SELECT JSON_VALUE(NULL, "strict $.key");)"); - Y_UNIT_TEST(JsonValueTooManyOnEmpty) { - NYql::TAstParseResult res = SqlToYql( - "select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\" NULL ON EMPTY NULL ON EMPTY);\n" - ); + UNIT_ASSERT(res.Root); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF( - Err2Str(res), - "<main>:1:52: Error: Only 1 ON EMPTY clause is expected\n" - ); - } + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Nothing (OptionalType (DataType 'Json)))")); + }; - Y_UNIT_TEST(JsonValueTooManyOnError) { - NYql::TAstParseResult res = SqlToYql( - "select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\" NULL ON ERROR NULL ON ERROR);\n" - ); + TWordCountHive elementStat({"JsonValue"}); + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT(elementStat["JsonValue"] > 0); +} +} // Y_UNIT_TEST_SUITE(JsonValue) - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF( - Err2Str(res), - "<main>:1:52: Error: Only 1 ON ERROR clause is expected\n" - ); - } +Y_UNIT_TEST_SUITE(JsonExists) { +Y_UNIT_TEST(JsonExistsValidHandlers) { + const TVector<std::pair<TString, TString>> testCases = { + {"", "(Just (Bool '\"false\"))"}, + {"TRUE ON ERROR", "(Just (Bool '\"true\"))"}, + {"FALSE ON ERROR", "(Just (Bool '\"false\"))"}, + {"UNKNOWN ON ERROR", "(Nothing (OptionalType (DataType 'Bool)))"}, + // NOTE: in this case we expect arguments of JsonExists callable to end immediately + // after variables. This parenthesis at the end of the expression is left on purpose + {"ERROR ON ERROR", "(Utf8 '\"strict $.key\") (JsonVariables))"}, + }; - Y_UNIT_TEST(JsonValueOnEmptyAfterOnError) { + for (const auto& item : testCases) { NYql::TAstParseResult res = SqlToYql( - "select JSON_VALUE(CAST(@@{\"key\": 1238}@@ as Json), \"strict $.key\" NULL ON ERROR NULL ON EMPTY);\n" - ); - - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF( - Err2Str(res), - "<main>:1:52: Error: ON EMPTY clause must be before ON ERROR clause\n" - ); - } - - Y_UNIT_TEST(JsonValueNullInput) { - NYql::TAstParseResult res = SqlToYql(R"(SELECT JSON_VALUE(NULL, "strict $.key");)"); + TStringBuilder() << R"( + $json = CAST(@@{"key": 1238}@@ as Json); + SELECT JSON_EXISTS($json, "strict $.key" )" + << item.first << ");\n"); UNIT_ASSERT(res.Root); TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Nothing (OptionalType (DataType 'Json)))")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(item.second)); }; - TWordCountHive elementStat({"JsonValue"}); + TWordCountHive elementStat({"JsonExists"}); VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat["JsonValue"] > 0); + UNIT_ASSERT(elementStat["JsonExists"] > 0); } } -Y_UNIT_TEST_SUITE(JsonExists) { - Y_UNIT_TEST(JsonExistsValidHandlers) { - const TVector<std::pair<TString, TString>> testCases = { - {"", "(Just (Bool '\"false\"))"}, - {"TRUE ON ERROR", "(Just (Bool '\"true\"))"}, - {"FALSE ON ERROR", "(Just (Bool '\"false\"))"}, - {"UNKNOWN ON ERROR", "(Nothing (OptionalType (DataType 'Bool)))"}, - // NOTE: in this case we expect arguments of JsonExists callable to end immediately - // after variables. This parenthesis at the end of the expression is left on purpose - {"ERROR ON ERROR", "(Utf8 '\"strict $.key\") (JsonVariables))"}, - }; - - for (const auto& item : testCases) { - NYql::TAstParseResult res = SqlToYql( - TStringBuilder() << R"( - $json = CAST(@@{"key": 1238}@@ as Json); - SELECT JSON_EXISTS($json, "strict $.key" )" << item.first << ");\n" - ); - - UNIT_ASSERT(res.Root); - - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(item.second)); - }; - - TWordCountHive elementStat({"JsonExists"}); - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat["JsonExists"] > 0); - } - } - - Y_UNIT_TEST(JsonExistsInvalidHandler) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(JsonExistsInvalidHandler) { + NYql::TAstParseResult res = SqlToYql(R"( $json = CAST(@@{"key": 1238}@@ as Json); $default = false; SELECT JSON_EXISTS($json, "strict $.key" $default ON ERROR); )"); - UNIT_ASSERT(!res.Root); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:53: Error: Unexpected token absence : Missing RPAREN \n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:53: Error: Unexpected token absence : Missing RPAREN \n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:53: Error: mismatched input '$' expecting {')', ERROR, FALSE, TRUE, UNKNOWN}\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:53: Error: mismatched input '$' expecting {')', ERROR, FALSE, TRUE, UNKNOWN}\n"); #endif - } +} - Y_UNIT_TEST(JsonExistsNullInput) { - NYql::TAstParseResult res = SqlToYql(R"(SELECT JSON_EXISTS(NULL, "strict $.key");)"); +Y_UNIT_TEST(JsonExistsNullInput) { + NYql::TAstParseResult res = SqlToYql(R"(SELECT JSON_EXISTS(NULL, "strict $.key");)"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Nothing (OptionalType (DataType 'Json)))")); - }; + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Nothing (OptionalType (DataType 'Json)))")); + }; - TWordCountHive elementStat({"JsonExists"}); - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat["JsonExists"] > 0); - } + TWordCountHive elementStat({"JsonExists"}); + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT(elementStat["JsonExists"] > 0); } +} // Y_UNIT_TEST_SUITE(JsonExists) Y_UNIT_TEST_SUITE(JsonQuery) { - Y_UNIT_TEST(JsonQueryValidHandlers) { - using TTestSuite = const TVector<std::pair<TString, TString>>; - TTestSuite wrapCases = { - {"", "'NoWrap"}, - {"WITHOUT WRAPPER", "'NoWrap"}, - {"WITHOUT ARRAY WRAPPER", "'NoWrap"}, - {"WITH WRAPPER", "'Wrap"}, - {"WITH ARRAY WRAPPER", "'Wrap"}, - {"WITH UNCONDITIONAL WRAPPER", "'Wrap"}, - {"WITH UNCONDITIONAL ARRAY WRAPPER", "'Wrap"}, - {"WITH CONDITIONAL WRAPPER", "'ConditionalWrap"}, - {"WITH CONDITIONAL ARRAY WRAPPER", "'ConditionalWrap"}, - }; - TTestSuite handlerCases = { - {"", "'Null"}, - {"ERROR", "'Error"}, - {"NULL", "'Null"}, - {"EMPTY ARRAY", "'EmptyArray"}, - {"EMPTY OBJECT", "'EmptyObject"}, - }; +Y_UNIT_TEST(JsonQueryValidHandlers) { + using TTestSuite = const TVector<std::pair<TString, TString>>; + TTestSuite wrapCases = { + {"", "'NoWrap"}, + {"WITHOUT WRAPPER", "'NoWrap"}, + {"WITHOUT ARRAY WRAPPER", "'NoWrap"}, + {"WITH WRAPPER", "'Wrap"}, + {"WITH ARRAY WRAPPER", "'Wrap"}, + {"WITH UNCONDITIONAL WRAPPER", "'Wrap"}, + {"WITH UNCONDITIONAL ARRAY WRAPPER", "'Wrap"}, + {"WITH CONDITIONAL WRAPPER", "'ConditionalWrap"}, + {"WITH CONDITIONAL ARRAY WRAPPER", "'ConditionalWrap"}, + }; + TTestSuite handlerCases = { + {"", "'Null"}, + {"ERROR", "'Error"}, + {"NULL", "'Null"}, + {"EMPTY ARRAY", "'EmptyArray"}, + {"EMPTY OBJECT", "'EmptyObject"}, + }; - for (const auto& wrap : wrapCases) { - for (const auto& onError : handlerCases) { - for (const auto& onEmpty : handlerCases) { - TStringBuilder query; - query << R"($json = CAST(@@{"key": [123]}@@ as Json); - SELECT JSON_QUERY($json, "strict $.key" )" << wrap.first; - if (!onEmpty.first.empty()) { - if (wrap.first.StartsWith("WITH ")) { - continue; - } - query << " " << onEmpty.first << " ON EMPTY"; - } - if (!onError.first.empty()) { - query << " " << onError.first << " ON ERROR"; + for (const auto& wrap : wrapCases) { + for (const auto& onError : handlerCases) { + for (const auto& onEmpty : handlerCases) { + TStringBuilder query; + query << R"($json = CAST(@@{"key": [123]}@@ as Json); + SELECT JSON_QUERY($json, "strict $.key" )" + << wrap.first; + if (!onEmpty.first.empty()) { + if (wrap.first.StartsWith("WITH ")) { + continue; } - query << ");\n"; + query << " " << onEmpty.first << " ON EMPTY"; + } + if (!onError.first.empty()) { + query << " " << onError.first << " ON ERROR"; + } + query << ");\n"; - NYql::TAstParseResult res = SqlToYql(query); + NYql::TAstParseResult res = SqlToYql(query); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - Y_UNUSED(word); - const TString args = TStringBuilder() << wrap.second << " " << onEmpty.second << " " << onError.second; - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(args)); - }; + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + Y_UNUSED(word); + const TString args = TStringBuilder() << wrap.second << " " << onEmpty.second << " " << onError.second; + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(args)); + }; - Cout << wrap.first << " " << onEmpty.first << " " << onError.first << Endl; + Cout << wrap.first << " " << onEmpty.first << " " << onError.first << Endl; - TWordCountHive elementStat({"JsonQuery"}); - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat["JsonQuery"] > 0); - } + TWordCountHive elementStat({"JsonQuery"}); + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT(elementStat["JsonQuery"] > 0); } } } +} - Y_UNIT_TEST(JsonQueryOnEmptyWithWrapper) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(JsonQueryOnEmptyWithWrapper) { + NYql::TAstParseResult res = SqlToYql(R"( $json = CAST(@@{"key": 1238}@@ as Json); SELECT JSON_QUERY($json, "strict $" WITH ARRAY WRAPPER EMPTY ARRAY ON EMPTY); )"); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:38: Error: ON EMPTY is prohibited because WRAPPER clause is specified\n"); - } + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:38: Error: ON EMPTY is prohibited because WRAPPER clause is specified\n"); +} - Y_UNIT_TEST(JsonQueryNullInput) { - NYql::TAstParseResult res = SqlToYql(R"(SELECT JSON_QUERY(NULL, "strict $.key");)"); +Y_UNIT_TEST(JsonQueryNullInput) { + NYql::TAstParseResult res = SqlToYql(R"(SELECT JSON_QUERY(NULL, "strict $.key");)"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Nothing (OptionalType (DataType 'Json)))")); - }; + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("(Nothing (OptionalType (DataType 'Json)))")); + }; - TWordCountHive elementStat({"JsonQuery"}); - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat["JsonQuery"] > 0); - } + TWordCountHive elementStat({"JsonQuery"}); + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT(elementStat["JsonQuery"] > 0); } +} // Y_UNIT_TEST_SUITE(JsonQuery) Y_UNIT_TEST_SUITE(JsonPassing) { - Y_UNIT_TEST(SupportedVariableTypes) { - const TVector<TString> functions = {"JSON_EXISTS", "JSON_VALUE", "JSON_QUERY"}; +Y_UNIT_TEST(SupportedVariableTypes) { + const TVector<TString> functions = {"JSON_EXISTS", "JSON_VALUE", "JSON_QUERY"}; - for (const auto& function : functions) { - const auto query = Sprintf(R"( + for (const auto& function : functions) { + const auto query = Sprintf(R"( pragma CompactNamedExprs; $json = CAST(@@{"key": 1238}@@ as Json); SELECT %s( @@ -7227,32 +7167,31 @@ Y_UNIT_TEST_SUITE(JsonPassing) { true as var4, $json as var5 ))", - function.data() - ); - NYql::TAstParseResult res = SqlToYql(query); + function.data()); + NYql::TAstParseResult res = SqlToYql(query); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var1" (String '"string")))"), "Cannot find `var1`"); - UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var2" (Double '"1.234")))"), "Cannot find `var2`"); - UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var3" (SafeCast (Int32 '"1") (DataType 'Int64))))"), "Cannot find `var3`"); - UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var4" (Bool '"true")))"), "Cannot find `var4`"); - UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var5" namedexprnode0))"), "Cannot find `var5`"); - }; + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var1" (String '"string")))"), "Cannot find `var1`"); + UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var2" (Double '"1.234")))"), "Cannot find `var2`"); + UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var3" (SafeCast (Int32 '"1") (DataType 'Int64))))"), "Cannot find `var3`"); + UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var4" (Bool '"true")))"), "Cannot find `var4`"); + UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var5" namedexprnode0))"), "Cannot find `var5`"); + }; - TWordCountHive elementStat({"JsonVariables"}); - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat["JsonVariables"] > 0); - } + TWordCountHive elementStat({"JsonVariables"}); + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT(elementStat["JsonVariables"] > 0); } +} - Y_UNIT_TEST(ValidVariableNames) { - const TVector<TString> functions = {"JSON_EXISTS", "JSON_VALUE", "JSON_QUERY"}; +Y_UNIT_TEST(ValidVariableNames) { + const TVector<TString> functions = {"JSON_EXISTS", "JSON_VALUE", "JSON_QUERY"}; - for (const auto& function : functions) { - const auto query = Sprintf(R"( + for (const auto& function : functions) { + const auto query = Sprintf(R"( $json = CAST(@@{"key": 1238}@@ as Json); SELECT %s( $json, @@ -7263,299 +7202,297 @@ Y_UNIT_TEST_SUITE(JsonPassing) { "three" as `var3`, "four" as VaR4 ))", - function.data() - ); - NYql::TAstParseResult res = SqlToYql(query); + function.data()); + NYql::TAstParseResult res = SqlToYql(query); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var1" (String '"one")))"), "Cannot find `var1`"); - UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"VaR2" (String '"two")))"), "Cannot find `VaR2`"); - UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var3" (String '"three")))"), "Cannot find `var3`"); - UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"VaR4" (String '"four")))"), "Cannot find `VaR4`"); - }; + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var1" (String '"one")))"), "Cannot find `var1`"); + UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"VaR2" (String '"two")))"), "Cannot find `VaR2`"); + UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"var3" (String '"three")))"), "Cannot find `var3`"); + UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos, line.find(R"('('"VaR4" (String '"four")))"), "Cannot find `VaR4`"); + }; - TWordCountHive elementStat({"JsonVariables"}); - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat["JsonVariables"] > 0); - } + TWordCountHive elementStat({"JsonVariables"}); + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT(elementStat["JsonVariables"] > 0); } } +} // Y_UNIT_TEST_SUITE(JsonPassing) Y_UNIT_TEST_SUITE(MigrationToJsonApi) { - Y_UNIT_TEST(WarningOnDeprecatedJsonUdf) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(WarningOnDeprecatedJsonUdf) { + NYql::TAstParseResult res = SqlToYql(R"( $json = CAST(@@{"key": 1234}@@ as Json); SELECT Json::Parse($json); )"); - UNIT_ASSERT(res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:26: Warning: Json UDF is deprecated. Please use JSON API instead, code: 4506\n"); - } + UNIT_ASSERT(res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:26: Warning: Json UDF is deprecated. Please use JSON API instead, code: 4506\n"); } +} // Y_UNIT_TEST_SUITE(MigrationToJsonApi) Y_UNIT_TEST_SUITE(AnsiIdentsNegative) { - Y_UNIT_TEST(EnableAnsiLexerFromRequestSpecialComments) { - auto req = "\n" - "\t --!ansi_lexer \n" - "-- Some comment\n" - "-- another comment\n" - "pragma SimpleColumns;\n" - "\n" - "select 1, '''' as empty;"; +Y_UNIT_TEST(EnableAnsiLexerFromRequestSpecialComments) { + auto req = "\n" + "\t --!ansi_lexer \n" + "-- Some comment\n" + "-- another comment\n" + "pragma SimpleColumns;\n" + "\n" + "select 1, '''' as empty;"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); - } + auto res = SqlToYql(req); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); +} - Y_UNIT_TEST(AnsiLexerShouldNotBeEnabledHere) { - auto req = "$str = '\n" - "--!ansi_lexer\n" - "--!syntax_v1\n" - "';\n" - "\n" - "select 1, $str, \"\" as empty;"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); - } +Y_UNIT_TEST(AnsiLexerShouldNotBeEnabledHere) { + auto req = "$str = '\n" + "--!ansi_lexer\n" + "--!syntax_v1\n" + "';\n" + "\n" + "select 1, $str, \"\" as empty;"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); +} - Y_UNIT_TEST(DoubleQuotesInDictsTuplesOrLists) { - auto req = "$d = { 'a': 1, \"b\": 2, 'c': 3,};"; +Y_UNIT_TEST(DoubleQuotesInDictsTuplesOrLists) { + auto req = "$d = { 'a': 1, \"b\": 2, 'c': 3,};"; - auto res = SqlToYqlWithAnsiLexer(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:16: Error: Column reference \"b\" is not allowed in current scope\n"); + auto res = SqlToYqlWithAnsiLexer(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:16: Error: Column reference \"b\" is not allowed in current scope\n"); - req = "$t = (1, 2, \"a\");"; + req = "$t = (1, 2, \"a\");"; - res = SqlToYqlWithAnsiLexer(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:13: Error: Column reference \"a\" is not allowed in current scope\n"); + res = SqlToYqlWithAnsiLexer(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:13: Error: Column reference \"a\" is not allowed in current scope\n"); - req = "$l = ['a', 'b', \"c\"];"; + req = "$l = ['a', 'b', \"c\"];"; - res = SqlToYqlWithAnsiLexer(req); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:17: Error: Column reference \"c\" is not allowed in current scope\n"); - } + res = SqlToYqlWithAnsiLexer(req); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:17: Error: Column reference \"c\" is not allowed in current scope\n"); +} - Y_UNIT_TEST(MultilineComments) { - auto req = "/*/**/ select 1;"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - res = SqlToYqlWithAnsiLexer(req); +Y_UNIT_TEST(MultilineComments) { + auto req = "/*/**/ select 1;"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + res = SqlToYqlWithAnsiLexer(req); #if ANTLR_VER == 3 - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:16: Error: Unexpected character : syntax error...\n\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:16: Error: Unexpected character : syntax error...\n\n"); #else - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); #endif - req = "/*\n" - "--/*\n" - "*/ select 1;"; - res = SqlToYql(req); - UNIT_ASSERT(res.Root); - res = SqlToYqlWithAnsiLexer(req); + req = "/*\n" + "--/*\n" + "*/ select 1;"; + res = SqlToYql(req); + UNIT_ASSERT(res.Root); + res = SqlToYqlWithAnsiLexer(req); #if ANTLR_VER == 3 - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:12: Error: Unexpected character : syntax error...\n\n"); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:3:12: Error: Unexpected character : syntax error...\n\n"); #else - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); #endif - req = "/*\n" - "/*\n" - "--*/\n" - "*/ select 1;"; - res = SqlToYql(req); - UNIT_ASSERT(!res.Root); + req = "/*\n" + "/*\n" + "--*/\n" + "*/ select 1;"; + res = SqlToYql(req); + UNIT_ASSERT(!res.Root); #if ANTLR_VER == 3 - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:0: Error: Unexpected token '*' : cannot match to any predicted input...\n\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:0: Error: Unexpected token '*' : cannot match to any predicted input...\n\n"); #else - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:0: Error: mismatched input '*' expecting {';', '(', '$', ALTER, ANALYZE, BACKUP, BATCH, COMMIT, CREATE, DECLARE, DEFINE, DELETE, DISCARD, DO, DROP, EVALUATE, EXPLAIN, EXPORT, FOR, FROM, GRANT, IF, IMPORT, INSERT, PARALLEL, PRAGMA, PROCESS, REDUCE, REPLACE, RESTORE, REVOKE, ROLLBACK, SELECT, SHOW, UPDATE, UPSERT, USE, VALUES}\n"); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:4:0: Error: mismatched input '*' expecting {';', '(', '$', ALTER, ANALYZE, BACKUP, BATCH, COMMIT, CREATE, DECLARE, DEFINE, DELETE, DISCARD, DO, DROP, EVALUATE, EXPLAIN, EXPORT, FOR, FROM, GRANT, IF, IMPORT, INSERT, PARALLEL, PRAGMA, PROCESS, REDUCE, REPLACE, RESTORE, REVOKE, ROLLBACK, SELECT, SHOW, UPDATE, UPSERT, USE, VALUES}\n"); #endif - res = SqlToYqlWithAnsiLexer(req); - UNIT_ASSERT(res.Root); - } + res = SqlToYqlWithAnsiLexer(req); + UNIT_ASSERT(res.Root); } +} // Y_UNIT_TEST_SUITE(AnsiIdentsNegative) Y_UNIT_TEST_SUITE(AnsiOptionalAs) { - Y_UNIT_TEST(OptionalAsInProjection) { - UNIT_ASSERT(SqlToYql("PRAGMA AnsiOptionalAs; SELECT a b, c FROM plato.Input;").IsOk()); - ExpectFailWithError("PRAGMA DisableAnsiOptionalAs;\n" - "SELECT a b, c FROM plato.Input;", - "<main>:2:10: Error: Expecting mandatory AS here. Did you miss comma? Please add PRAGMA AnsiOptionalAs; for ANSI compatibility\n"); - } +Y_UNIT_TEST(OptionalAsInProjection) { + UNIT_ASSERT(SqlToYql("PRAGMA AnsiOptionalAs; SELECT a b, c FROM plato.Input;").IsOk()); + ExpectFailWithError("PRAGMA DisableAnsiOptionalAs;\n" + "SELECT a b, c FROM plato.Input;", + "<main>:2:10: Error: Expecting mandatory AS here. Did you miss comma? Please add PRAGMA AnsiOptionalAs; for ANSI compatibility\n"); +} - Y_UNIT_TEST(OptionalAsWithKeywords) { - UNIT_ASSERT(SqlToYql("PRAGMA AnsiOptionalAs; SELECT a type, b data, c source FROM plato.Input;").IsOk()); - } +Y_UNIT_TEST(OptionalAsWithKeywords) { + UNIT_ASSERT(SqlToYql("PRAGMA AnsiOptionalAs; SELECT a type, b data, c source FROM plato.Input;").IsOk()); } +} // Y_UNIT_TEST_SUITE(AnsiOptionalAs) Y_UNIT_TEST_SUITE(SessionWindowNegative) { - Y_UNIT_TEST(SessionWindowWithoutSource) { - ExpectFailWithError("SELECT 1 + SessionWindow(ts, 32);", - "<main>:1:12: Error: SessionWindow requires data source\n"); - } +Y_UNIT_TEST(SessionWindowWithoutSource) { + ExpectFailWithError("SELECT 1 + SessionWindow(ts, 32);", + "<main>:1:12: Error: SessionWindow requires data source\n"); +} - Y_UNIT_TEST(SessionWindowInProjection) { - ExpectFailWithError("SELECT 1 + SessionWindow(ts, 32) from plato.Input;", - "<main>:1:12: Error: SessionWindow can only be used as a top-level GROUP BY / PARTITION BY expression\n"); - } +Y_UNIT_TEST(SessionWindowInProjection) { + ExpectFailWithError("SELECT 1 + SessionWindow(ts, 32) from plato.Input;", + "<main>:1:12: Error: SessionWindow can only be used as a top-level GROUP BY / PARTITION BY expression\n"); +} - Y_UNIT_TEST(SessionWindowWithNonConstSecondArg) { - ExpectFailWithError( - "SELECT key, session_start FROM plato.Input\n" - "GROUP BY SessionWindow(ts, 32 + subkey) as session_start, key;", +Y_UNIT_TEST(SessionWindowWithNonConstSecondArg) { + ExpectFailWithError( + "SELECT key, session_start FROM plato.Input\n" + "GROUP BY SessionWindow(ts, 32 + subkey) as session_start, key;", - "<main>:2:10: Error: Source does not allow column references\n" - "<main>:2:33: Error: Column reference 'subkey'\n"); - } + "<main>:2:10: Error: Source does not allow column references\n" + "<main>:2:33: Error: Column reference 'subkey'\n"); +} - Y_UNIT_TEST(SessionWindowWithWrongNumberOfArgs) { - ExpectFailWithError("SELECT * FROM plato.Input GROUP BY SessionWindow()", - "<main>:1:36: Error: SessionWindow requires either two or four arguments\n"); - ExpectFailWithError("SELECT * FROM plato.Input GROUP BY SessionWindow(key, subkey, 100)", - "<main>:1:36: Error: SessionWindow requires either two or four arguments\n"); - } +Y_UNIT_TEST(SessionWindowWithWrongNumberOfArgs) { + ExpectFailWithError("SELECT * FROM plato.Input GROUP BY SessionWindow()", + "<main>:1:36: Error: SessionWindow requires either two or four arguments\n"); + ExpectFailWithError("SELECT * FROM plato.Input GROUP BY SessionWindow(key, subkey, 100)", + "<main>:1:36: Error: SessionWindow requires either two or four arguments\n"); +} - Y_UNIT_TEST(DuplicateSessionWindow) { - ExpectFailWithError( - "SELECT\n" - " *\n" - "FROM plato.Input\n" - "GROUP BY\n" - " SessionWindow(ts, 10),\n" - " user,\n" - " SessionWindow(ts, 20)\n" - ";", - - "<main>:7:5: Error: Duplicate session window specification:\n" - "<main>:5:5: Error: Previous session window is declared here\n"); - - ExpectFailWithError( - "SELECT\n" - " MIN(key) over w\n" - "FROM plato.Input\n" - "WINDOW w AS (\n" - " PARTITION BY SessionWindow(ts, 10), user,\n" - " SessionWindow(ts, 20)\n" - ");", - - "<main>:6:5: Error: Duplicate session window specification:\n" - "<main>:5:18: Error: Previous session window is declared here\n"); - } +Y_UNIT_TEST(DuplicateSessionWindow) { + ExpectFailWithError( + "SELECT\n" + " *\n" + "FROM plato.Input\n" + "GROUP BY\n" + " SessionWindow(ts, 10),\n" + " user,\n" + " SessionWindow(ts, 20)\n" + ";", + + "<main>:7:5: Error: Duplicate session window specification:\n" + "<main>:5:5: Error: Previous session window is declared here\n"); + + ExpectFailWithError( + "SELECT\n" + " MIN(key) over w\n" + "FROM plato.Input\n" + "WINDOW w AS (\n" + " PARTITION BY SessionWindow(ts, 10), user,\n" + " SessionWindow(ts, 20)\n" + ");", + + "<main>:6:5: Error: Duplicate session window specification:\n" + "<main>:5:18: Error: Previous session window is declared here\n"); +} - Y_UNIT_TEST(SessionStartStateWithoutSource) { - ExpectFailWithError("SELECT 1 + SessionStart();", - "<main>:1:12: Error: SessionStart requires data source\n"); - ExpectFailWithError("SELECT 1 + SessionState();", - "<main>:1:12: Error: SessionState requires data source\n"); - } +Y_UNIT_TEST(SessionStartStateWithoutSource) { + ExpectFailWithError("SELECT 1 + SessionStart();", + "<main>:1:12: Error: SessionStart requires data source\n"); + ExpectFailWithError("SELECT 1 + SessionState();", + "<main>:1:12: Error: SessionState requires data source\n"); +} - Y_UNIT_TEST(SessionStartStateWithoutGroupByOrWindow) { - ExpectFailWithError("SELECT 1 + SessionStart() from plato.Input;", - "<main>:1:12: Error: SessionStart can not be used without aggregation by SessionWindow\n"); - ExpectFailWithError("SELECT 1 + SessionState() from plato.Input;", - "<main>:1:12: Error: SessionState can not be used without aggregation by SessionWindow\n"); - } +Y_UNIT_TEST(SessionStartStateWithoutGroupByOrWindow) { + ExpectFailWithError("SELECT 1 + SessionStart() from plato.Input;", + "<main>:1:12: Error: SessionStart can not be used without aggregation by SessionWindow\n"); + ExpectFailWithError("SELECT 1 + SessionState() from plato.Input;", + "<main>:1:12: Error: SessionState can not be used without aggregation by SessionWindow\n"); +} - Y_UNIT_TEST(SessionStartStateWithGroupByWithoutSession) { - ExpectFailWithError("SELECT 1 + SessionStart() from plato.Input group by user;", - "<main>:1:12: Error: SessionStart can not be used here: SessionWindow specification is missing in GROUP BY\n"); - ExpectFailWithError("SELECT 1 + SessionState() from plato.Input group by user;", - "<main>:1:12: Error: SessionState can not be used here: SessionWindow specification is missing in GROUP BY\n"); - } +Y_UNIT_TEST(SessionStartStateWithGroupByWithoutSession) { + ExpectFailWithError("SELECT 1 + SessionStart() from plato.Input group by user;", + "<main>:1:12: Error: SessionStart can not be used here: SessionWindow specification is missing in GROUP BY\n"); + ExpectFailWithError("SELECT 1 + SessionState() from plato.Input group by user;", + "<main>:1:12: Error: SessionState can not be used here: SessionWindow specification is missing in GROUP BY\n"); +} - Y_UNIT_TEST(SessionStartStateWithoutOverWithWindowWithoutSession) { - ExpectFailWithError("SELECT 1 + SessionStart(), MIN(key) over w from plato.Input window w as ()", - "<main>:1:12: Error: SessionStart can not be used without aggregation by SessionWindow. Maybe you forgot to add OVER `window_name`?\n"); - ExpectFailWithError("SELECT 1 + SessionState(), MIN(key) over w from plato.Input window w as ()", - "<main>:1:12: Error: SessionState can not be used without aggregation by SessionWindow. Maybe you forgot to add OVER `window_name`?\n"); - } +Y_UNIT_TEST(SessionStartStateWithoutOverWithWindowWithoutSession) { + ExpectFailWithError("SELECT 1 + SessionStart(), MIN(key) over w from plato.Input window w as ()", + "<main>:1:12: Error: SessionStart can not be used without aggregation by SessionWindow. Maybe you forgot to add OVER `window_name`?\n"); + ExpectFailWithError("SELECT 1 + SessionState(), MIN(key) over w from plato.Input window w as ()", + "<main>:1:12: Error: SessionState can not be used without aggregation by SessionWindow. Maybe you forgot to add OVER `window_name`?\n"); +} - Y_UNIT_TEST(SessionStartStateWithWindowWithoutSession) { - ExpectFailWithError("SELECT 1 + SessionStart() over w, MIN(key) over w from plato.Input window w as ()", - "<main>:1:12: Error: SessionStart can not be used with window w: SessionWindow specification is missing in PARTITION BY\n"); - ExpectFailWithError("SELECT 1 + SessionState() over w, MIN(key) over w from plato.Input window w as ()", - "<main>:1:12: Error: SessionState can not be used with window w: SessionWindow specification is missing in PARTITION BY\n"); - } +Y_UNIT_TEST(SessionStartStateWithWindowWithoutSession) { + ExpectFailWithError("SELECT 1 + SessionStart() over w, MIN(key) over w from plato.Input window w as ()", + "<main>:1:12: Error: SessionStart can not be used with window w: SessionWindow specification is missing in PARTITION BY\n"); + ExpectFailWithError("SELECT 1 + SessionState() over w, MIN(key) over w from plato.Input window w as ()", + "<main>:1:12: Error: SessionState can not be used with window w: SessionWindow specification is missing in PARTITION BY\n"); +} - Y_UNIT_TEST(SessionStartStateWithSessionedWindow) { - ExpectFailWithError("SELECT 1 + SessionStart(), MIN(key) over w from plato.Input group by key window w as (partition by SessionWindow(ts, 1)) ", - "<main>:1:12: Error: SessionStart can not be used here: SessionWindow specification is missing in GROUP BY. Maybe you forgot to add OVER `window_name`?\n"); - ExpectFailWithError("SELECT 1 + SessionState(), MIN(key) over w from plato.Input group by key window w as (partition by SessionWindow(ts, 1)) ", - "<main>:1:12: Error: SessionState can not be used here: SessionWindow specification is missing in GROUP BY. Maybe you forgot to add OVER `window_name`?\n"); - } +Y_UNIT_TEST(SessionStartStateWithSessionedWindow) { + ExpectFailWithError("SELECT 1 + SessionStart(), MIN(key) over w from plato.Input group by key window w as (partition by SessionWindow(ts, 1)) ", + "<main>:1:12: Error: SessionStart can not be used here: SessionWindow specification is missing in GROUP BY. Maybe you forgot to add OVER `window_name`?\n"); + ExpectFailWithError("SELECT 1 + SessionState(), MIN(key) over w from plato.Input group by key window w as (partition by SessionWindow(ts, 1)) ", + "<main>:1:12: Error: SessionState can not be used here: SessionWindow specification is missing in GROUP BY. Maybe you forgot to add OVER `window_name`?\n"); +} - Y_UNIT_TEST(AggregationBySessionStateIsNotSupportedYet) { - ExpectFailWithError("SELECT SOME(1 + SessionState()), key from plato.Input group by key, SessionWindow(ts, 1);", - "<main>:1:17: Error: SessionState with GROUP BY is not supported yet\n"); - } +Y_UNIT_TEST(AggregationBySessionStateIsNotSupportedYet) { + ExpectFailWithError("SELECT SOME(1 + SessionState()), key from plato.Input group by key, SessionWindow(ts, 1);", + "<main>:1:17: Error: SessionState with GROUP BY is not supported yet\n"); +} - Y_UNIT_TEST(SessionWindowInRtmr) { - NYql::TAstParseResult res = SqlToYql( - "SELECT * FROM plato.Input GROUP BY SessionWindow(ts, 10);", - 10, TString(NYql::RtmrProviderName)); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:54: Error: Streaming group by query must have a hopping window specification.\n"); +Y_UNIT_TEST(SessionWindowInRtmr) { + NYql::TAstParseResult res = SqlToYql( + "SELECT * FROM plato.Input GROUP BY SessionWindow(ts, 10);", + 10, TString(NYql::RtmrProviderName)); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:1:54: Error: Streaming group by query must have a hopping window specification.\n"); - res = SqlToYql(R"( + res = SqlToYql(R"( SELECT key, SUM(value) AS value FROM plato.Input GROUP BY key, HOP(subkey, "PT10S", "PT30S", "PT20S"), SessionWindow(ts, 10); )", 10, TString(NYql::RtmrProviderName)); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:13: Error: SessionWindow is unsupported for streaming sources\n"); - } + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), "<main>:2:13: Error: SessionWindow is unsupported for streaming sources\n"); } +} // Y_UNIT_TEST_SUITE(SessionWindowNegative) Y_UNIT_TEST_SUITE(LibraSqlSugar) { - auto makeResult = [](TStringBuf settings) { - return SqlToYql( - TStringBuilder() - << settings - << "\n$udf1 = MyLibra::MakeLibraPreprocessor($settings);" - << "\n$udf2 = CustomLibra::MakeLibraPreprocessor($settings);" - << "\nPROCESS plato.Input USING $udf1(TableRow())" - << "\nUNION ALL" - << "\nPROCESS plato.Input USING $udf2(TableRow());" - ); - }; - - Y_UNIT_TEST(EmptySettings) { - auto res = makeResult(R"( +auto makeResult = [](TStringBuf settings) { + return SqlToYql( + TStringBuilder() + << settings + << "\n$udf1 = MyLibra::MakeLibraPreprocessor($settings);" + << "\n$udf2 = CustomLibra::MakeLibraPreprocessor($settings);" + << "\nPROCESS plato.Input USING $udf1(TableRow())" + << "\nUNION ALL" + << "\nPROCESS plato.Input USING $udf2(TableRow());"); +}; + +Y_UNIT_TEST(EmptySettings) { + auto res = makeResult(R"( $settings = AsStruct(); )"); - UNIT_ASSERT(res.IsOk()); - } + UNIT_ASSERT(res.IsOk()); +} - Y_UNIT_TEST(OnlyEntities) { - auto res = makeResult(R"( +Y_UNIT_TEST(OnlyEntities) { + auto res = makeResult(R"( $settings = AsStruct( AsList("A", "B", "C") AS Entities ); )"); - UNIT_ASSERT(res.IsOk()); - } + UNIT_ASSERT(res.IsOk()); +} - Y_UNIT_TEST(EntitiesWithStrategy) { - auto res = makeResult(R"( +Y_UNIT_TEST(EntitiesWithStrategy) { + auto res = makeResult(R"( $settings = AsStruct( AsList("A", "B", "C") AS Entities, "blacklist" AS EntitiesStrategy ); )"); - UNIT_ASSERT(res.IsOk()); - } + UNIT_ASSERT(res.IsOk()); +} - Y_UNIT_TEST(AllSettings) { - auto res = makeResult(R"( +Y_UNIT_TEST(AllSettings) { + auto res = makeResult(R"( $settings = AsStruct( AsList("A", "B", "C") AS Entities, "whitelist" AS EntitiesStrategy, @@ -7564,153 +7501,152 @@ Y_UNIT_TEST_SUITE(LibraSqlSugar) { "map" AS Mode ); )"); - UNIT_ASSERT(res.IsOk()); - } + UNIT_ASSERT(res.IsOk()); +} - Y_UNIT_TEST(BadStrategy) { - auto res = makeResult(R"( +Y_UNIT_TEST(BadStrategy) { + auto res = makeResult(R"( $settings = AsStruct("bad" AS EntitiesStrategy); )"); - UNIT_ASSERT_STRING_CONTAINS( - Err2Str(res), - "Error: MakeLibraPreprocessor got invalid entities strategy: expected 'whitelist' or 'blacklist'" - ); - } + UNIT_ASSERT_STRING_CONTAINS( + Err2Str(res), + "Error: MakeLibraPreprocessor got invalid entities strategy: expected 'whitelist' or 'blacklist'"); +} - Y_UNIT_TEST(BadEntities) { - auto res = makeResult(R"( +Y_UNIT_TEST(BadEntities) { + auto res = makeResult(R"( $settings = AsStruct(AsList("A", 1) AS Entities); )"); - UNIT_ASSERT_STRING_CONTAINS(Err2Str(res), "Error: MakeLibraPreprocessor entity must be string literal"); - } + UNIT_ASSERT_STRING_CONTAINS(Err2Str(res), "Error: MakeLibraPreprocessor entity must be string literal"); } +} // Y_UNIT_TEST_SUITE(LibraSqlSugar) Y_UNIT_TEST_SUITE(TrailingQuestionsNegative) { - Y_UNIT_TEST(Basic) { - ExpectFailWithError("SELECT 1?;", "<main>:1:9: Error: Unexpected token '?' at the end of expression\n"); +Y_UNIT_TEST(Basic) { + ExpectFailWithError("SELECT 1?;", "<main>:1:9: Error: Unexpected token '?' at the end of expression\n"); #if ANTLR_VER == 3 - ExpectFailWithError("SELECT 1? + 1;", "<main>:1:10: Error: Unexpected token '+' : cannot match to any predicted input...\n\n"); + ExpectFailWithError("SELECT 1? + 1;", "<main>:1:10: Error: Unexpected token '+' : cannot match to any predicted input...\n\n"); #else - ExpectFailWithError("SELECT 1? + 1;", "<main>:1:10: Error: mismatched input '+' expecting {<EOF>, ';'}\n"); + ExpectFailWithError("SELECT 1? + 1;", "<main>:1:10: Error: mismatched input '+' expecting {<EOF>, ';'}\n"); #endif - ExpectFailWithError("SELECT 1 + 1??? < 2", "<main>:1:13: Error: Unexpected token '?' at the end of expression\n"); - ExpectFailWithError("SELECT 1? > 2? > 3?", - "<main>:1:11: Error: Unexpected token '?' at the end of expression\n" - "<main>:1:16: Error: Unexpected token '?' at the end of expression\n" - "<main>:1:21: Error: Unexpected token '?' at the end of expression\n"); - } + ExpectFailWithError("SELECT 1 + 1??? < 2", "<main>:1:13: Error: Unexpected token '?' at the end of expression\n"); + ExpectFailWithError("SELECT 1? > 2? > 3?", + "<main>:1:11: Error: Unexpected token '?' at the end of expression\n" + "<main>:1:16: Error: Unexpected token '?' at the end of expression\n" + "<main>:1:21: Error: Unexpected token '?' at the end of expression\n"); +} - Y_UNIT_TEST(SmartParen) { - ExpectFailWithError("$x = 1; SELECT (Int32?, $x?)", "<main>:1:27: Error: Unexpected token '?' at the end of expression\n"); - ExpectFailWithError("SELECT (Int32, foo?)", "<main>:1:19: Error: Unexpected token '?' at the end of expression\n"); - } +Y_UNIT_TEST(SmartParen) { + ExpectFailWithError("$x = 1; SELECT (Int32?, $x?)", "<main>:1:27: Error: Unexpected token '?' at the end of expression\n"); + ExpectFailWithError("SELECT (Int32, foo?)", "<main>:1:19: Error: Unexpected token '?' at the end of expression\n"); +} - Y_UNIT_TEST(LambdaOptArgs) { - ExpectFailWithError("$l = ($x, $y?, $z??, $t?) -> ($x);", "<main>:1:18: Error: Expecting at most one '?' token here (for optional lambda parameters), but got 2\n"); - } +Y_UNIT_TEST(LambdaOptArgs) { + ExpectFailWithError("$l = ($x, $y?, $z??, $t?) -> ($x);", "<main>:1:18: Error: Expecting at most one '?' token here (for optional lambda parameters), but got 2\n"); } +} // Y_UNIT_TEST_SUITE(TrailingQuestionsNegative) Y_UNIT_TEST_SUITE(FlexibleTypes) { - Y_UNIT_TEST(AssumeOrderByType) { - UNIT_ASSERT(SqlToYql("PRAGMA FlexibleTypes; SELECT 1 AS int32 ASSUME ORDER BY int32").IsOk()); - } +Y_UNIT_TEST(AssumeOrderByType) { + UNIT_ASSERT(SqlToYql("PRAGMA FlexibleTypes; SELECT 1 AS int32 ASSUME ORDER BY int32").IsOk()); +} - Y_UNIT_TEST(GroupingSets) { - UNIT_ASSERT(SqlToYql("PRAGMA FlexibleTypes; SELECT COUNT(*) AS cnt, text, uuid FROM plato.Input GROUP BY GROUPING SETS((uuid), (uuid, text));").IsOk()); - } +Y_UNIT_TEST(GroupingSets) { + UNIT_ASSERT(SqlToYql("PRAGMA FlexibleTypes; SELECT COUNT(*) AS cnt, text, uuid FROM plato.Input GROUP BY GROUPING SETS((uuid), (uuid, text));").IsOk()); +} - Y_UNIT_TEST(WeakField) { - UNIT_ASSERT(SqlToYql("PRAGMA FlexibleTypes; SELECT WeakField(text, string) as text FROM plato.Input").IsOk()); - } +Y_UNIT_TEST(WeakField) { + UNIT_ASSERT(SqlToYql("PRAGMA FlexibleTypes; SELECT WeakField(text, string) as text FROM plato.Input").IsOk()); +} - Y_UNIT_TEST(Aggregation1) { - TString q = - "PRAGMA FlexibleTypes;\n" - "$foo = ($x, $const, $type) -> ($x || $const || FormatType($type));\n" - "SELECT $foo(SOME(x), 'aaa', String) FROM plato.Input GROUP BY y;"; - UNIT_ASSERT(SqlToYql(q).IsOk()); - } +Y_UNIT_TEST(Aggregation1) { + TString q = + "PRAGMA FlexibleTypes;\n" + "$foo = ($x, $const, $type) -> ($x || $const || FormatType($type));\n" + "SELECT $foo(SOME(x), 'aaa', String) FROM plato.Input GROUP BY y;"; + UNIT_ASSERT(SqlToYql(q).IsOk()); +} - Y_UNIT_TEST(Aggregation2) { - TString q = - "PRAGMA FlexibleTypes;\n" - "SELECT 1 + String + MAX(key) FROM plato.Input;"; - UNIT_ASSERT(SqlToYql(q).IsOk()); - } +Y_UNIT_TEST(Aggregation2) { + TString q = + "PRAGMA FlexibleTypes;\n" + "SELECT 1 + String + MAX(key) FROM plato.Input;"; + UNIT_ASSERT(SqlToYql(q).IsOk()); } +} // Y_UNIT_TEST_SUITE(FlexibleTypes) Y_UNIT_TEST_SUITE(ExternalDeclares) { - Y_UNIT_TEST(BasicUsage) { - NSQLTranslation::TTranslationSettings settings; - settings.DeclaredNamedExprs["foo"] = "String"; - auto res = SqlToYqlWithSettings("select $foo;", settings); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "declare") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"__((declare "$foo" (DataType 'String)))__")); - } - }; +Y_UNIT_TEST(BasicUsage) { + NSQLTranslation::TTranslationSettings settings; + settings.DeclaredNamedExprs["foo"] = "String"; + auto res = SqlToYqlWithSettings("select $foo;", settings); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "declare") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"__((declare "$foo" (DataType 'String)))__")); + } + }; - TWordCountHive elementStat = {{TString("declare"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("declare"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["declare"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["declare"]); +} - Y_UNIT_TEST(DeclareOverrides) { - NSQLTranslation::TTranslationSettings settings; - settings.DeclaredNamedExprs["foo"] = "String"; - auto res = SqlToYqlWithSettings("declare $foo as Int32; select $foo;", settings); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); +Y_UNIT_TEST(DeclareOverrides) { + NSQLTranslation::TTranslationSettings settings; + settings.DeclaredNamedExprs["foo"] = "String"; + auto res = SqlToYqlWithSettings("declare $foo as Int32; select $foo;", settings); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "declare") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"__((declare "$foo" (DataType 'Int32)))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "declare") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"__((declare "$foo" (DataType 'Int32)))__")); + } + }; - TWordCountHive elementStat = {{TString("declare"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("declare"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["declare"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["declare"]); +} - Y_UNIT_TEST(UnusedDeclareDoesNotProduceWarning) { - NSQLTranslation::TTranslationSettings settings; - settings.DeclaredNamedExprs["foo"] = "String"; - auto res = SqlToYqlWithSettings("select 1;", settings); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); +Y_UNIT_TEST(UnusedDeclareDoesNotProduceWarning) { + NSQLTranslation::TTranslationSettings settings; + settings.DeclaredNamedExprs["foo"] = "String"; + auto res = SqlToYqlWithSettings("select 1;", settings); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "declare") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"__((declare "$foo" (DataType 'String)))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "declare") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"__((declare "$foo" (DataType 'String)))__")); + } + }; - TWordCountHive elementStat = {{TString("declare"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("declare"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["declare"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["declare"]); +} - Y_UNIT_TEST(DeclaresWithInvalidTypesFails) { - NSQLTranslation::TTranslationSettings settings; - settings.DeclaredNamedExprs["foo"] = "List<BadType>"; - auto res = SqlToYqlWithSettings("select 1;", settings); - UNIT_ASSERT(!res.Root); - UNIT_ASSERT_NO_DIFF(Err2Str(res), - "<main>:0:5: Error: Unknown type: 'BadType'\n" - "<main>: Error: Failed to parse type for externally declared name 'foo'\n"); - } +Y_UNIT_TEST(DeclaresWithInvalidTypesFails) { + NSQLTranslation::TTranslationSettings settings; + settings.DeclaredNamedExprs["foo"] = "List<BadType>"; + auto res = SqlToYqlWithSettings("select 1;", settings); + UNIT_ASSERT(!res.Root); + UNIT_ASSERT_NO_DIFF(Err2Str(res), + "<main>:0:5: Error: Unknown type: 'BadType'\n" + "<main>: Error: Failed to parse type for externally declared name 'foo'\n"); } +} // Y_UNIT_TEST_SUITE(ExternalDeclares) Y_UNIT_TEST_SUITE(ExternalDataSource) { - Y_UNIT_TEST(CreateExternalDataSourceWithAuthNone) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalDataSourceWithAuthNone) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="ObjectStorage", @@ -7718,23 +7654,23 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AUTH_METHOD="NONE" ); )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"NONE") '('"location" '"my-bucket") '('"source_type" '"ObjectStorage"))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"NONE") '('"location" '"my-bucket") '('"source_type" '"ObjectStorage"))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalDataSourceWithAuthServiceAccount) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalDataSourceWithAuthServiceAccount) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="ObjectStorage", @@ -7744,23 +7680,23 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { SERVICE_ACCOUNT_SECRET_NAME="sa_secret_name" ); )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"SERVICE_ACCOUNT") '('"location" '"my-bucket") '('"service_account_id" '"sa") '('"service_account_secret_name" '"sa_secret_name") '('"source_type" '"ObjectStorage"))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"SERVICE_ACCOUNT") '('"location" '"my-bucket") '('"service_account_id" '"sa") '('"service_account_secret_name" '"sa_secret_name") '('"source_type" '"ObjectStorage"))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalDataSourceWithBasic) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalDataSourceWithBasic) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -7770,23 +7706,23 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { PASSWORD_SECRET_NAME="secret_name" ); )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"BASIC") '('"location" '"protocol://host:port/") '('"login" '"admin") '('"password_secret_name" '"secret_name") '('"source_type" '"PostgreSQL"))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"BASIC") '('"location" '"protocol://host:port/") '('"login" '"admin") '('"password_secret_name" '"secret_name") '('"source_type" '"PostgreSQL"))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalDataSourceWithMdbBasic) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalDataSourceWithMdbBasic) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -7798,23 +7734,23 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { PASSWORD_SECRET_NAME="secret_name" ); )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"MDB_BASIC") '('"location" '"protocol://host:port/") '('"login" '"admin") '('"password_secret_name" '"secret_name") '('"service_account_id" '"sa") '('"service_account_secret_name" '"sa_secret_name") '('"source_type" '"PostgreSQL"))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"MDB_BASIC") '('"location" '"protocol://host:port/") '('"login" '"admin") '('"password_secret_name" '"secret_name") '('"service_account_id" '"sa") '('"service_account_secret_name" '"sa_secret_name") '('"source_type" '"PostgreSQL"))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalDataSourceWithAws) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalDataSourceWithAws) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -7825,23 +7761,23 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AWS_REGION="ru-central-1" ); )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"AWS") '('"aws_access_key_id_secret_name" '"secred_id_name") '('"aws_region" '"ru-central-1") '('"aws_secret_access_key_secret_name" '"secret_key_name") '('"location" '"protocol://host:port/") '('"source_type" '"PostgreSQL"))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"AWS") '('"aws_access_key_id_secret_name" '"secred_id_name") '('"aws_region" '"ru-central-1") '('"aws_secret_access_key_secret_name" '"secret_key_name") '('"location" '"protocol://host:port/") '('"source_type" '"PostgreSQL"))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalDataSourceWithToken) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalDataSourceWithToken) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="YT", @@ -7850,23 +7786,23 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { TOKEN_SECRET_NAME="token_name" ); )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"TOKEN") '('"location" '"protocol://host:port/") '('"source_type" '"YT") '('"token_secret_name" '"token_name"))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"TOKEN") '('"location" '"protocol://host:port/") '('"source_type" '"YT") '('"token_secret_name" '"token_name"))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalDataSourceWithTablePrefix) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalDataSourceWithTablePrefix) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; pragma TablePathPrefix='/aba'; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( @@ -7875,23 +7811,23 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AUTH_METHOD="NONE" ); )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, "/aba/MyDataSource"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, "/aba/MyDataSource"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalDataSourceIfNotExists) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalDataSourceIfNotExists) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE IF NOT EXISTS MyDataSource WITH ( SOURCE_TYPE="ObjectStorage", @@ -7899,47 +7835,47 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AUTH_METHOD="NONE" ); )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"NONE") '('"location" '"my-bucket") '('"source_type" '"ObjectStorage"))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObjectIfNotExists")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"NONE") '('"location" '"my-bucket") '('"source_type" '"ObjectStorage"))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObjectIfNotExists")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(AlterExternalDataSource) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterExternalDataSource) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER EXTERNAL DATA SOURCE MyDataSource SET (SOURCE_TYPE = "ObjectStorage", Login = "Admin"), SET Location "bucket", RESET (Auth_Method, Service_Account_Id, Service_Account_Secret_Name); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alterObject))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('features '('('"location" '"bucket") '('"login" '"Admin") '('"source_type" '"ObjectStorage"))))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('resetFeatures '('"auth_method" '"service_account_id" '"service_account_secret_name")))#"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alterObject))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('features '('('"location" '"bucket") '('"login" '"Admin") '('"source_type" '"ObjectStorage"))))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('resetFeatures '('"auth_method" '"service_account_id" '"service_account_secret_name")))#"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalDataSourceOrReplace) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(CreateExternalDataSourceOrReplace) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; CREATE OR REPLACE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="ObjectStorage", @@ -7947,28 +7883,28 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AUTH_METHOD="NONE" ); )"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"NONE") '('"location" '"my-bucket") '('"source_type" '"ObjectStorage"))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObjectOrReplace")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"auth_method" '"NONE") '('"location" '"my-bucket") '('"source_type" '"ObjectStorage"))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObjectOrReplace")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateOrReplaceForUnsupportedTableTypesShouldFail) { - ExpectFailWithError(R"sql( +Y_UNIT_TEST(CreateOrReplaceForUnsupportedTableTypesShouldFail) { + ExpectFailWithError(R"sql( USE plato; CREATE OR REPLACE TABLE t (a int32 not null, primary key(a, a)); - )sql" , "<main>:3:23: Error: OR REPLACE feature is supported only for EXTERNAL DATA SOURCE and EXTERNAL TABLE\n"); + )sql", "<main>:3:23: Error: OR REPLACE feature is supported only for EXTERNAL DATA SOURCE and EXTERNAL TABLE\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE OR REPLACE TABLE t ( Key Uint64, @@ -7979,57 +7915,56 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { STORE = COLUMN, AUTO_PARTITIONING_MIN_PARTITIONS_COUNT = 10 ); - )sql" , "<main>:3:23: Error: OR REPLACE feature is supported only for EXTERNAL DATA SOURCE and EXTERNAL TABLE\n"); - } + )sql", "<main>:3:23: Error: OR REPLACE feature is supported only for EXTERNAL DATA SOURCE and EXTERNAL TABLE\n"); +} - Y_UNIT_TEST(CreateExternalDataSourceWithBadArguments) { +Y_UNIT_TEST(CreateExternalDataSourceWithBadArguments) { #if ANTLR_VER == 3 - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource; - )sql" , "<main>:3:52: Error: Unexpected token ';' : syntax error...\n\n"); + )sql", "<main>:3:52: Error: Unexpected token ';' : syntax error...\n\n"); #else - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource; - )sql" , "<main>:3:52: Error: mismatched input ';' expecting WITH\n"); + )sql", "<main>:3:52: Error: mismatched input ';' expecting WITH\n"); #endif - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( LOCATION="my-bucket", AUTH_METHOD="NONE" ); - )sql" , "<main>:5:33: Error: SOURCE_TYPE requires key\n"); + )sql", "<main>:5:33: Error: SOURCE_TYPE requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="ObjectStorage", LOCATION="my-bucket" ); - )sql" , "<main>:5:30: Error: AUTH_METHOD requires key\n"); + )sql", "<main>:5:30: Error: AUTH_METHOD requires key\n"); - - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="ObjectStorage", LOCATION="my-bucket", AUTH_METHOD="NONE1" ); - )sql" , "<main>:6:33: Error: Unknown AUTH_METHOD = NONE1\n"); + )sql", "<main>:6:33: Error: Unknown AUTH_METHOD = NONE1\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="ObjectStorage", LOCATION="my-bucket", AUTH_METHOD="SERVICE_ACCOUNT" ); - )sql" , "<main>:6:33: Error: SERVICE_ACCOUNT_ID requires key\n"); + )sql", "<main>:6:33: Error: SERVICE_ACCOUNT_ID requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="ObjectStorage", @@ -8037,9 +7972,9 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AUTH_METHOD="SERVICE_ACCOUNT", SERVICE_ACCOUNT_ID="s1" ); - )sql" , "<main>:7:40: Error: SERVICE_ACCOUNT_SECRET_NAME requires key\n"); + )sql", "<main>:7:40: Error: SERVICE_ACCOUNT_SECRET_NAME requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="ObjectStorage", @@ -8047,9 +7982,9 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AUTH_METHOD="SERVICE_ACCOUNT", SERVICE_ACCOUNT_SECRET_NAME="s1" ); - )sql" , "<main>:7:49: Error: SERVICE_ACCOUNT_ID requires key\n"); + )sql", "<main>:7:49: Error: SERVICE_ACCOUNT_ID requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -8057,9 +7992,9 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AUTH_METHOD="BASIC", LOGIN="admin" ); - )sql" , "<main>:7:27: Error: PASSWORD_SECRET_NAME requires key\n"); + )sql", "<main>:7:27: Error: PASSWORD_SECRET_NAME requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -8067,9 +8002,9 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AUTH_METHOD="BASIC", PASSWORD_SECRET_NAME="secret_name" ); - )sql" , "<main>:7:42: Error: LOGIN requires key\n"); + )sql", "<main>:7:42: Error: LOGIN requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -8079,9 +8014,9 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { LOGIN="admin", PASSWORD_SECRET_NAME="secret_name" ); - )sql" , "<main>:9:42: Error: SERVICE_ACCOUNT_ID requires key\n"); + )sql", "<main>:9:42: Error: SERVICE_ACCOUNT_ID requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -8091,9 +8026,9 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { LOGIN="admin", PASSWORD_SECRET_NAME="secret_name" ); - )sql" , "<main>:9:42: Error: SERVICE_ACCOUNT_SECRET_NAME requires key\n"); + )sql", "<main>:9:42: Error: SERVICE_ACCOUNT_SECRET_NAME requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -8103,9 +8038,9 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { SERVICE_ACCOUNT_SECRET_NAME="sa_secret_name", PASSWORD_SECRET_NAME="secret_name" ); - )sql" , "<main>:9:42: Error: LOGIN requires key\n"); + )sql", "<main>:9:42: Error: LOGIN requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -8115,9 +8050,9 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { SERVICE_ACCOUNT_SECRET_NAME="sa_secret_name", LOGIN="admin" ); - )sql" , "<main>:9:27: Error: PASSWORD_SECRET_NAME requires key\n"); + )sql", "<main>:9:27: Error: PASSWORD_SECRET_NAME requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -8126,9 +8061,9 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AWS_SECRET_ACCESS_KEY_SECRET_NAME="secret_key_name", AWS_REGION="ru-central-1" ); - )sql" , "<main>:8:32: Error: AWS_ACCESS_KEY_ID_SECRET_NAME requires key\n"); + )sql", "<main>:8:32: Error: AWS_ACCESS_KEY_ID_SECRET_NAME requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -8137,9 +8072,9 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AWS_ACCESS_KEY_ID_SECRET_NAME="secred_id_name", AWS_REGION="ru-central-1" ); - )sql" , "<main>:8:32: Error: AWS_SECRET_ACCESS_KEY_SECRET_NAME requires key\n"); + )sql", "<main>:8:32: Error: AWS_SECRET_ACCESS_KEY_SECRET_NAME requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL DATA SOURCE MyDataSource WITH ( SOURCE_TYPE="PostgreSQL", @@ -8148,75 +8083,75 @@ Y_UNIT_TEST_SUITE(ExternalDataSource) { AWS_SECRET_ACCESS_KEY_SECRET_NAME="secret_key_name", AWS_ACCESS_KEY_ID_SECRET_NAME="secred_id_name" ); - )sql" , "<main>:8:51: Error: AWS_REGION requires key\n"); - } + )sql", "<main>:8:51: Error: AWS_REGION requires key\n"); +} - Y_UNIT_TEST(DropExternalDataSourceWithTablePrefix) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropExternalDataSourceWithTablePrefix) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP EXTERNAL DATA SOURCE MyDataSource; )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DropExternalDataSourceIfExists) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropExternalDataSourceIfExists) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP EXTERNAL DATA SOURCE IF EXISTS MyDataSource; )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, "MyDataSource"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObjectIfExists")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, "MyDataSource"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObjectIfExists")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DropExternalDataSource) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropExternalDataSource) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; pragma TablePathPrefix='/aba'; DROP EXTERNAL DATA SOURCE MyDataSource; )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, "/aba/MyDataSource"); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, "/aba/MyDataSource"); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); } +} // Y_UNIT_TEST_SUITE(ExternalDataSource) Y_UNIT_TEST_SUITE(ExternalTable) { - Y_UNIT_TEST(CreateExternalTable) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalTable) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE EXTERNAL TABLE mytable ( a int @@ -8225,23 +8160,23 @@ Y_UNIT_TEST_SUITE(ExternalTable) { LOCATION="/folder1/*" ); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('data_source_path (String '"/Root/mydatasource")) '('location (String '"/folder1/*")))) '('tableType 'externalTable)))))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tablescheme")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('data_source_path (String '"/Root/mydatasource")) '('location (String '"/folder1/*")))) '('tableType 'externalTable)))))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tablescheme")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalTableWithTablePrefix) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalTableWithTablePrefix) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; pragma TablePathPrefix='/aba'; CREATE EXTERNAL TABLE mytable ( @@ -8251,24 +8186,24 @@ Y_UNIT_TEST_SUITE(ExternalTable) { LOCATION="/folder1/*" ); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, "/aba/mydatasource"); - UNIT_ASSERT_STRING_CONTAINS(line, "/aba/mytable"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tablescheme")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, "/aba/mydatasource"); + UNIT_ASSERT_STRING_CONTAINS(line, "/aba/mytable"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("tablescheme")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalTableObjectStorage) { - auto res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalTableObjectStorage) { + auto res = SqlToYql(R"sql( USE plato; CREATE EXTERNAL TABLE mytable ( a int, @@ -8291,11 +8226,11 @@ Y_UNIT_TEST_SUITE(ExternalTable) { PARTITONED_BY = "[year, month]" ); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); +} - Y_UNIT_TEST(CreateExternalTableIfNotExists) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateExternalTableIfNotExists) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE EXTERNAL TABLE IF NOT EXISTS mytable ( a int @@ -8304,23 +8239,23 @@ Y_UNIT_TEST_SUITE(ExternalTable) { LOCATION="/folder1/*" ); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('data_source_path (String '"/Root/mydatasource")) '('location (String '"/folder1/*")))) '('tableType 'externalTable)))))#"); - UNIT_ASSERT_STRING_CONTAINS(line, "create_if_not_exists"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('data_source_path (String '"/Root/mydatasource")) '('location (String '"/folder1/*")))) '('tableType 'externalTable)))))#"); + UNIT_ASSERT_STRING_CONTAINS(line, "create_if_not_exists"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalTableOrReplace) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(CreateExternalTableOrReplace) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; CREATE OR REPLACE EXTERNAL TABLE mytable ( a int @@ -8329,109 +8264,109 @@ Y_UNIT_TEST_SUITE(ExternalTable) { LOCATION="/folder1/*" ); )"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('data_source_path (String '"/Root/mydatasource")) '('location (String '"/folder1/*")))) '('tableType 'externalTable)))))#"); - UNIT_ASSERT_STRING_CONTAINS(line, "create_or_replace"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('data_source_path (String '"/Root/mydatasource")) '('location (String '"/folder1/*")))) '('tableType 'externalTable)))))#"); + UNIT_ASSERT_STRING_CONTAINS(line, "create_or_replace"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(AlterExternalTableAddColumn) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterExternalTableAddColumn) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER EXTERNAL TABLE mytable ADD COLUMN my_column int32, RESET (LOCATION); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('actions '('('addColumns '('('"my_column" (AsOptionalType (DataType 'Int32))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('setTableSettings '('('location)))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('tableType 'externalTable))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alter))#"); - } - }; + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('actions '('('addColumns '('('"my_column" (AsOptionalType (DataType 'Int32))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('setTableSettings '('('location)))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('tableType 'externalTable))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alter))#"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(AlterExternalTableDropColumn) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterExternalTableDropColumn) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER EXTERNAL TABLE mytable DROP COLUMN my_column, SET (Location = "abc", Other_Prop = "42"), SET x 'y'; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('actions '('('dropColumns '('"my_column")#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('setTableSettings '('('location (String '"abc")) '('Other_Prop (String '"42")) '('x (String '"y")))))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('tableType 'externalTable))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alter))#"); - } - }; + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('actions '('('dropColumns '('"my_column")#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('setTableSettings '('('location (String '"abc")) '('Other_Prop (String '"42")) '('x (String '"y")))))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('tableType 'externalTable))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alter))#"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateExternalTableWithBadArguments) { +Y_UNIT_TEST(CreateExternalTableWithBadArguments) { #if ANTLR_VER == 3 - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL TABLE mytable; - )sql" , "<main>:3:41: Error: Unexpected token ';' : syntax error...\n\n"); + )sql", "<main>:3:41: Error: Unexpected token ';' : syntax error...\n\n"); #else - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL TABLE mytable; - )sql" , "<main>:3:45: Error: mismatched input ';' expecting '('\n"); + )sql", "<main>:3:45: Error: mismatched input ';' expecting '('\n"); #endif - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL TABLE mytable ( a int ); - )sql" , "<main>:4:23: Error: DATA_SOURCE requires key\n"); + )sql", "<main>:4:23: Error: DATA_SOURCE requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL TABLE mytable ( a int ) WITH ( DATA_SOURCE="/Root/mydatasource" ); - )sql" , "<main>:6:33: Error: LOCATION requires key\n"); + )sql", "<main>:6:33: Error: LOCATION requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL TABLE mytable ( a int ) WITH ( LOCATION="/folder1/*" ); - )sql" , "<main>:6:30: Error: DATA_SOURCE requires key\n"); + )sql", "<main>:6:30: Error: DATA_SOURCE requires key\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE EXTERNAL TABLE mytable ( a int, @@ -8440,130 +8375,133 @@ Y_UNIT_TEST_SUITE(ExternalTable) { DATA_SOURCE="/Root/mydatasource", LOCATION="/folder1/*" ); - )sql" , "<main>:8:30: Error: PRIMARY KEY is not supported for external table\n"); - } + )sql", "<main>:8:30: Error: PRIMARY KEY is not supported for external table\n"); +} - Y_UNIT_TEST(DropExternalTable) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropExternalTable) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP EXTERNAL TABLE MyExternalTable; )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("tablescheme")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("tablescheme")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DropExternalTableWithTablePrefix) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropExternalTableWithTablePrefix) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; pragma TablePathPrefix='/aba'; DROP EXTERNAL TABLE MyExternalTable; )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, "/aba/MyExternalTable"); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'tablescheme")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, "/aba/MyExternalTable"); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'tablescheme")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DropExternalTableIfExists) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropExternalTableIfExists) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP EXTERNAL TABLE IF EXISTS MyExternalTable; )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("tablescheme")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("drop_if_exists")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("tablescheme")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("drop_if_exists")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); } +} // Y_UNIT_TEST_SUITE(ExternalTable) Y_UNIT_TEST_SUITE(TopicsDDL) { - void TestQuery(const TString& query, bool expectOk = true, const TVector<TString> issueSubstrings = {}) { - TStringBuilder finalQuery; - - finalQuery << "use plato;" << Endl << query; - auto res = SqlToYql(finalQuery, 10, "kikimr"); - if (expectOk) { - UNIT_ASSERT_C(res.IsOk(), "Query: " << query << "\n" << "Issues: " << res.Issues.ToString()); - } else { - UNIT_ASSERT_C(!res.IsOk(), "Query: " << query << "\n" << "Issues: " << res.Issues.ToString()); - for (const auto& issue : issueSubstrings) { - UNIT_ASSERT_STRING_CONTAINS_C(res.Issues.ToOneLineString(), issue, "Query: " << query << "\n" << "Issues: " << res.Issues.ToString()); - } +void TestQuery(const TString& query, bool expectOk = true, const TVector<TString> issueSubstrings = {}) { + TStringBuilder finalQuery; + + finalQuery << "use plato;" << Endl << query; + auto res = SqlToYql(finalQuery, 10, "kikimr"); + if (expectOk) { + UNIT_ASSERT_C(res.IsOk(), "Query: " << query << "\n" + << "Issues: " << res.Issues.ToString()); + } else { + UNIT_ASSERT_C(!res.IsOk(), "Query: " << query << "\n" + << "Issues: " << res.Issues.ToString()); + for (const auto& issue : issueSubstrings) { + UNIT_ASSERT_STRING_CONTAINS_C(res.Issues.ToOneLineString(), issue, "Query: " << query << "\n" + << "Issues: " << res.Issues.ToString()); } } +} - Y_UNIT_TEST(CreateTopicSimple) { - TestQuery(R"( +Y_UNIT_TEST(CreateTopicSimple) { + TestQuery(R"( CREATE TOPIC topic1; )"); - TestQuery(R"( + TestQuery(R"( CREATE TOPIC `cluster1.topic1`; )"); - TestQuery(R"( + TestQuery(R"( CREATE TOPIC topic1 WITH (metering_mode = "str_value", partition_count_limit = 123, retention_period = Interval('PT1H')); )"); - } +} - Y_UNIT_TEST(CreateTopicConsumer) { - TestQuery(R"( +Y_UNIT_TEST(CreateTopicConsumer) { + TestQuery(R"( CREATE TOPIC topic1 (CONSUMER cons1); )"); - TestQuery(R"( + TestQuery(R"( CREATE TOPIC topic1 (CONSUMER cons1, CONSUMER cons2 WITH (important = false)); )"); - TestQuery(R"( + TestQuery(R"( CREATE TOPIC topic1 (CONSUMER cons1, CONSUMER cons2 WITH (important = false)) WITH (supported_codecs = "1,2,3"); )"); - TestQuery(R"( + TestQuery(R"( CREATE TOPIC topic1 (CONSUMER cons1, CONSUMER cons2 WITH (important = false, availability_period = Interval('PT9H'))) WITH (supported_codecs = "1,2,3"); )"); - } +} - Y_UNIT_TEST(AlterTopicSimple) { - TestQuery(R"( +Y_UNIT_TEST(AlterTopicSimple) { + TestQuery(R"( ALTER TOPIC topic1 SET (retention_period = Interval('PT1H')); )"); - TestQuery(R"( + TestQuery(R"( ALTER TOPIC topic1 SET (retention_storage_mb = 3, partition_count_limit = 50); )"); - TestQuery(R"( + TestQuery(R"( ALTER TOPIC topic1 RESET (supported_codecs, retention_period); )"); - TestQuery(R"( + TestQuery(R"( ALTER TOPIC topic1 RESET (partition_write_speed_bytes_per_second), SET (partition_write_burst_bytes = 11111, min_active_partitions = 1); )"); - } - Y_UNIT_TEST(AlterTopicConsumer) { - TestQuery(R"( +} +Y_UNIT_TEST(AlterTopicConsumer) { + TestQuery(R"( ALTER TOPIC topic1 ADD CONSUMER consumer1, ADD CONSUMER consumer2 WITH (important = false, supported_codecs = "RAW"), ALTER CONSUMER consumer3 SET (important = false, read_from = 1), @@ -8574,346 +8512,343 @@ Y_UNIT_TEST_SUITE(TopicsDDL) { SET (partition_count_limit = 11, retention_period = Interval('PT1H')), RESET(metering_mode) )"); - } - Y_UNIT_TEST(DropTopic) { - TestQuery(R"( +} +Y_UNIT_TEST(DropTopic) { + TestQuery(R"( DROP TOPIC topic1; )"); - } +} - Y_UNIT_TEST(TopicBadRequests) { - TestQuery(R"( +Y_UNIT_TEST(TopicBadRequests) { + TestQuery(R"( CREATE TOPIC topic1(); )", false); - TestQuery(R"( + TestQuery(R"( CREATE TOPIC topic1 SET setting1 = value1; )", false); - TestQuery(R"( + TestQuery(R"( ALTER TOPIC topic1 SET setting1 value1; )", false); - TestQuery(R"( + TestQuery(R"( ALTER TOPIC topic1 RESET setting1; )", false); - TestQuery(R"( + TestQuery(R"( ALTER TOPIC topic1 DROP CONSUMER consumer4 WITH (k1 = v1); )", false); - TestQuery(R"( + TestQuery(R"( CREATE TOPIC topic1 WITH (retention_period = 123); - )", false, {"3:58: Error: Literal of Interval type is expected for retention"}); - TestQuery(R"( + )", false, + {"3:58: Error: Literal of Interval type is expected for retention"}); + TestQuery(R"( CREATE TOPIC topic1 (CONSUMER cons1, CONSUMER cons1 WITH (important = false)); - )", false, {"3:59: Error: Consumer cons1 defined more than once"}); - TestQuery(R"( + )", false, + {"3:59: Error: Consumer cons1 defined more than once"}); + TestQuery(R"( CREATE TOPIC topic1 (CONSUMER cons1 WITH (bad_option = false)); - )", false, {"3:68: Error: BAD_OPTION: unknown option for consumer"}); - TestQuery(R"( + )", false, + {"3:68: Error: BAD_OPTION: unknown option for consumer"}); + TestQuery(R"( CREATE TOPIC topic1 (CONSUMER cons1 WITH (important = false, important = true)); - )", false, {"3:86: Error: IMPORTANT specified multiple times in CONSUMER statement for single consumer"}); - TestQuery(R"( + )", false, + {"3:86: Error: IMPORTANT specified multiple times in CONSUMER statement for single consumer"}); + TestQuery(R"( ALTER TOPIC topic1 ADD CONSUMER cons1, ALTER CONSUMER cons1 RESET (important); - )", false, {"3:80: Error: IMPORTANT reset is not supported"}); - TestQuery(R"( + )", false, + {"3:80: Error: IMPORTANT reset is not supported"}); + TestQuery(R"( ALTER TOPIC topic1 ADD CONSUMER consumer1, ALTER CONSUMER consumer3 SET (supported_codecs = "RAW", read_from = 1), ALTER CONSUMER consumer3 RESET (supported_codecs); - )", false, {"5:49: Error: SUPPORTED_CODECS specified multiple times in ALTER CONSUMER statement for single consumer"}); - TestQuery(R"( + )", false, + {"5:49: Error: SUPPORTED_CODECS specified multiple times in ALTER CONSUMER statement for single consumer"}); + TestQuery(R"( ALTER TOPIC topic1 ADD CONSUMER consumer1, ALTER CONSUMER consumer3 SET (supported_codecs = "RAW", read_from = 1), ALTER CONSUMER consumer3 SET (read_from = 2); - )", false, {"5:59: Error: READ_FROM specified multiple times in CONSUMER statement for single consumer"}); - TestQuery(R"( + )", false, + {"5:59: Error: READ_FROM specified multiple times in CONSUMER statement for single consumer"}); + TestQuery(R"( CREATE TOPIC topic1 (CONSUMER cons1 WITH (availability_period = 3600)); - )", false, {"3:77: Error: Literal of Interval type is expected for AVAILABILITY_PERIOD setting"}); - TestQuery(R"( + )", false, + {"3:77: Error: Literal of Interval type is expected for AVAILABILITY_PERIOD setting"}); + TestQuery(R"( ALTER TOPIC topic1 ALTER CONSUMER consumer3 SET (availability_period = false); - )", false, {"4:69: Error: Literal of Interval type is expected for AVAILABILITY_PERIOD setting"}); - } + )", false, + {"4:69: Error: Literal of Interval type is expected for AVAILABILITY_PERIOD setting"}); +} - Y_UNIT_TEST(TopicWithPrefix) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(TopicWithPrefix) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; PRAGMA TablePathPrefix = '/database/path/to/tables'; ALTER TOPIC `my_table/my_feed` ADD CONSUMER `my_consumer`; )"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("/database/path/to/tables/my_table/my_feed"), 0}, {"topic", 0}}; - VerifyProgram(res, elementStat); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["topic"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["/database/path/to/tables/my_table/my_feed"]); - } + TWordCountHive elementStat = {{TString("/database/path/to/tables/my_table/my_feed"), 0}, {"topic", 0}}; + VerifyProgram(res, elementStat); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["topic"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["/database/path/to/tables/my_table/my_feed"]); } +} // Y_UNIT_TEST_SUITE(TopicsDDL) Y_UNIT_TEST_SUITE(BlockEnginePragma) { - Y_UNIT_TEST(Basic) { - const TVector<TString> values = {"auto", "force", "disable"}; - for (const auto& value : values) { - const auto query = TStringBuilder() << "pragma Blockengine='" << value << "'; select 1;"; - NYql::TAstParseResult res = SqlToYql(query); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(Basic) { + const TVector<TString> values = {"auto", "force", "disable"}; + for (const auto& value : values) { + const auto query = TStringBuilder() << "pragma Blockengine='" << value << "'; select 1;"; + NYql::TAstParseResult res = SqlToYql(query); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - Y_UNUSED(word); - UNIT_ASSERT_STRING_CONTAINS(line, TStringBuilder() << R"(Configure! world (DataSource '"config") '"BlockEngine" '")" << value << "\""); - }; + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + Y_UNUSED(word); + UNIT_ASSERT_STRING_CONTAINS(line, TStringBuilder() << R"(Configure! world (DataSource '"config") '"BlockEngine" '")" << value << "\""); + }; - TWordCountHive elementStat({"BlockEngine"}); - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT(elementStat["BlockEngine"] == ((value == "disable") ? 0 : 1)); - } + TWordCountHive elementStat({"BlockEngine"}); + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT(elementStat["BlockEngine"] == ((value == "disable") ? 0 : 1)); } +} - Y_UNIT_TEST(UnknownSetting) { - ExpectFailWithError("use plato; pragma BlockEngine='foo';", - "<main>:1:31: Error: Expected `disable|auto|force' argument for: BlockEngine\n"); - } +Y_UNIT_TEST(UnknownSetting) { + ExpectFailWithError("use plato; pragma BlockEngine='foo';", + "<main>:1:31: Error: Expected `disable|auto|force' argument for: BlockEngine\n"); } +} // Y_UNIT_TEST_SUITE(BlockEnginePragma) Y_UNIT_TEST_SUITE(TViewSyntaxTest) { - Y_UNIT_TEST(CreateViewSimple) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(CreateViewSimple) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; CREATE VIEW TheView WITH (security_invoker = TRUE) AS SELECT 1; - )" - ); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - } + )"); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); +} - Y_UNIT_TEST(CreateViewWithUdfs) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(CreateViewWithUdfs) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; CREATE VIEW TheView WITH (security_invoker = TRUE) AS SELECT "bbb" LIKE Unwrap("aaa"); - )" - ); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - } + )"); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); +} - Y_UNIT_TEST(CreateViewIfNotExists) { - constexpr const char* name = "TheView"; - NYql::TAstParseResult res = SqlToYql(std::format(R"( +Y_UNIT_TEST(CreateViewIfNotExists) { + constexpr const char* name = "TheView"; + NYql::TAstParseResult res = SqlToYql(std::format(R"( USE plato; CREATE VIEW IF NOT EXISTS {} AS SELECT 1; - )", name - )); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + )", name)); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_STRING_CONTAINS(line, name); - UNIT_ASSERT_STRING_CONTAINS(line, "createObjectIfNotExists"); - } - }; + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_STRING_CONTAINS(line, name); + UNIT_ASSERT_STRING_CONTAINS(line, "createObjectIfNotExists"); + } + }; - TWordCountHive elementStat = { {"Write!"} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{"Write!"}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); +} - Y_UNIT_TEST(CreateViewFromTable) { - constexpr const char* path = "/PathPrefix/TheView"; - constexpr const char* query = R"( +Y_UNIT_TEST(CreateViewFromTable) { + constexpr const char* path = "/PathPrefix/TheView"; + constexpr const char* query = R"( SELECT * FROM SomeTable )"; - NYql::TAstParseResult res = SqlToYql(std::format(R"( + NYql::TAstParseResult res = SqlToYql(std::format(R"( USE plato; CREATE VIEW `{}` WITH (security_invoker = TRUE) AS {}; )", - path, - query - ) - ); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_STRING_CONTAINS(line, path); - UNIT_ASSERT_STRING_CONTAINS(line, "createObject"); - } - }; - TWordCountHive elementStat = { {"Write!"} }; - VerifyProgram(res, elementStat, verifyLine); + path, + query)); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_STRING_CONTAINS(line, path); + UNIT_ASSERT_STRING_CONTAINS(line, "createObject"); + } + }; + TWordCountHive elementStat = {{"Write!"}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); +} - Y_UNIT_TEST(CheckReconstructedQuery) { - constexpr const char* path = "/PathPrefix/TheView"; - constexpr const char* query = R"( +Y_UNIT_TEST(CheckReconstructedQuery) { + constexpr const char* path = "/PathPrefix/TheView"; + constexpr const char* query = R"( SELECT * FROM FirstTable JOIN SecondTable ON FirstTable.key == SecondTable.key )"; - NYql::TAstParseResult res = SqlToYql(std::format(R"( + NYql::TAstParseResult res = SqlToYql(std::format(R"( USE plato; CREATE VIEW `{}` WITH (security_invoker = TRUE) AS {}; )", - path, - query - ) - ); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - - TString reconstructedQuery = ToString(Tokenize(query)); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - if (word == "query_text") { - UNIT_ASSERT_STRING_CONTAINS(line, reconstructedQuery); - } - }; - TWordCountHive elementStat = { {"Write!"} }; - VerifyProgram(res, elementStat, verifyLine); + path, + query)); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + + TString reconstructedQuery = ToString(Tokenize(query)); + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + if (word == "query_text") { + UNIT_ASSERT_STRING_CONTAINS(line, reconstructedQuery); + } + }; + TWordCountHive elementStat = {{"Write!"}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); +} - Y_UNIT_TEST(DropView) { - constexpr const char* path = "/PathPrefix/TheView"; - NYql::TAstParseResult res = SqlToYql(std::format(R"( +Y_UNIT_TEST(DropView) { + constexpr const char* path = "/PathPrefix/TheView"; + NYql::TAstParseResult res = SqlToYql(std::format(R"( USE plato; DROP VIEW `{}`; )", - path - ) - ); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + path)); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_STRING_CONTAINS(line, path); - UNIT_ASSERT_STRING_CONTAINS(line, "dropObject"); - } - }; - TWordCountHive elementStat = { {"Write!"} }; - VerifyProgram(res, elementStat, verifyLine); + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_STRING_CONTAINS(line, path); + UNIT_ASSERT_STRING_CONTAINS(line, "dropObject"); + } + }; + TWordCountHive elementStat = {{"Write!"}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); +} - Y_UNIT_TEST(DropViewIfExists) { - constexpr const char* name = "TheView"; - NYql::TAstParseResult res = SqlToYql(std::format(R"( +Y_UNIT_TEST(DropViewIfExists) { + constexpr const char* name = "TheView"; + NYql::TAstParseResult res = SqlToYql(std::format(R"( USE plato; DROP VIEW IF EXISTS {}; - )", name - )); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + )", name)); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_STRING_CONTAINS(line, name); - UNIT_ASSERT_STRING_CONTAINS(line, "dropObjectIfExists"); - } - }; + TVerifyLineFunc verifyLine = [&](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_STRING_CONTAINS(line, name); + UNIT_ASSERT_STRING_CONTAINS(line, "dropObjectIfExists"); + } + }; - TWordCountHive elementStat = { {"Write!"} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{"Write!"}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); +} - Y_UNIT_TEST(CreateViewWithTablePrefix) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(CreateViewWithTablePrefix) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; PRAGMA TablePathPrefix='/PathPrefix'; CREATE VIEW TheView WITH (security_invoker = TRUE) AS SELECT 1; - )" - ); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + )"); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write!") { - UNIT_ASSERT_STRING_CONTAINS(line, "/PathPrefix/TheView"); - UNIT_ASSERT_STRING_CONTAINS(line, "createObject"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write!") { + UNIT_ASSERT_STRING_CONTAINS(line, "/PathPrefix/TheView"); + UNIT_ASSERT_STRING_CONTAINS(line, "createObject"); + } + }; - TWordCountHive elementStat = { {"Write!"} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{"Write!"}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); +} - Y_UNIT_TEST(DropViewWithTablePrefix) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(DropViewWithTablePrefix) { + NYql::TAstParseResult res = SqlToYql(R"( USE plato; PRAGMA TablePathPrefix='/PathPrefix'; DROP VIEW TheView; - )" - ); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + )"); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, "/PathPrefix/TheView"); - UNIT_ASSERT_STRING_CONTAINS(line, "dropObject"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, "/PathPrefix/TheView"); + UNIT_ASSERT_STRING_CONTAINS(line, "dropObject"); + } + }; - TWordCountHive elementStat = { {"Write!"} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{"Write!"}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); - } + UNIT_ASSERT_VALUES_EQUAL(elementStat["Write!"], 1); +} - Y_UNIT_TEST(YtAlternativeSchemaSyntax) { - NYql::TAstParseResult res = SqlToYql(R"( +Y_UNIT_TEST(YtAlternativeSchemaSyntax) { + NYql::TAstParseResult res = SqlToYql(R"( SELECT * FROM plato.Input WITH schema(y Int32, x String not null); )"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "userschema") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, - line.find(R"__('('('"userschema" (StructType '('"y" (AsOptionalType (DataType 'Int32))) '('"x" (DataType 'String))))))__")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "userschema") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, + line.find(R"__('('('"userschema" (StructType '('"y" (AsOptionalType (DataType 'Int32))) '('"x" (DataType 'String))))))__")); + } + }; - TWordCountHive elementStat = {{TString("userschema"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("userschema"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["userschema"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["userschema"]); +} - Y_UNIT_TEST(UseViewAndFullColumnId) { - NYql::TAstParseResult res = SqlToYql("USE plato; SELECT Input.x FROM Input VIEW uitzicht;"); - UNIT_ASSERT(res.Root); +Y_UNIT_TEST(UseViewAndFullColumnId) { + NYql::TAstParseResult res = SqlToYql("USE plato; SELECT Input.x FROM Input VIEW uitzicht;"); + UNIT_ASSERT(res.Root); - TWordCountHive elementStat = {{TString("SqlAccess"), 0}, {"SqlProjectItem", 0}, {"Read!", 0}}; - VerifyProgram(res, elementStat); - UNIT_ASSERT_VALUES_EQUAL(0, elementStat["SqlAccess"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectItem"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Read!"]); - } + TWordCountHive elementStat = {{TString("SqlAccess"), 0}, {"SqlProjectItem", 0}, {"Read!", 0}}; + VerifyProgram(res, elementStat); + UNIT_ASSERT_VALUES_EQUAL(0, elementStat["SqlAccess"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SqlProjectItem"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Read!"]); } +} // Y_UNIT_TEST_SUITE(TViewSyntaxTest) Y_UNIT_TEST_SUITE(CompactNamedExprs) { - Y_UNIT_TEST(SourceCallablesInWrongContext) { - TString query = R"( +Y_UNIT_TEST(SourceCallablesInWrongContext) { + TString query = R"( pragma CompactNamedExprs; $foo = %s(); select $foo from plato.Input; )"; - THashMap<TString, TString> errs = { - {"TableRow", "<main>:3:20: Error: TableRow requires data source\n"}, - {"JoinTableRow", "<main>:3:20: Error: JoinTableRow requires data source\n"}, - {"TableRecordIndex", "<main>:3:20: Error: Unable to use function: TableRecord without source\n"}, - {"TablePath", "<main>:3:20: Error: Unable to use function: TablePath without source\n"}, - {"SystemMetadata", "<main>:3:20: Error: Unable to use function: SystemMetadata without source\n"}, - }; + THashMap<TString, TString> errs = { + {"TableRow", "<main>:3:20: Error: TableRow requires data source\n"}, + {"JoinTableRow", "<main>:3:20: Error: JoinTableRow requires data source\n"}, + {"TableRecordIndex", "<main>:3:20: Error: Unable to use function: TableRecord without source\n"}, + {"TablePath", "<main>:3:20: Error: Unable to use function: TablePath without source\n"}, + {"SystemMetadata", "<main>:3:20: Error: Unable to use function: SystemMetadata without source\n"}, + }; - for (TString callable : { "TableRow", "JoinTableRow", "TableRecordIndex", "TablePath", "SystemMetadata"}) { - auto req = Sprintf(query.c_str(), callable.c_str()); - ExpectFailWithError(req, errs[callable]); - } + for (TString callable : {"TableRow", "JoinTableRow", "TableRecordIndex", "TablePath", "SystemMetadata"}) { + auto req = Sprintf(query.c_str(), callable.c_str()); + ExpectFailWithError(req, errs[callable]); } +} - Y_UNIT_TEST(ValidateUnusedExprs) { - TString query = R"( +Y_UNIT_TEST(ValidateUnusedExprs) { + TString query = R"( pragma warning("disable", "4527"); pragma CompactNamedExprs; pragma ValidateUnusedExprs; @@ -8921,8 +8856,8 @@ Y_UNIT_TEST_SUITE(CompactNamedExprs) { $foo = count(1); select 1; )"; - ExpectFailWithError(query, "<main>:6:20: Error: Aggregation is not allowed in this context\n"); - query = R"( + ExpectFailWithError(query, "<main>:6:20: Error: Aggregation is not allowed in this context\n"); + query = R"( pragma warning("disable", "4527"); pragma CompactNamedExprs; pragma ValidateUnusedExprs; @@ -8932,11 +8867,11 @@ Y_UNIT_TEST_SUITE(CompactNamedExprs) { end define; select 1; )"; - ExpectFailWithError(query, "<main>:7:24: Error: Aggregation function Count requires exactly 1 argument(s), given: 2\n"); - } + ExpectFailWithError(query, "<main>:7:24: Error: Aggregation function Count requires exactly 1 argument(s), given: 2\n"); +} - Y_UNIT_TEST(DisableValidateUnusedExprs) { - TString query = R"( +Y_UNIT_TEST(DisableValidateUnusedExprs) { + TString query = R"( pragma warning("disable", "4527"); pragma CompactNamedExprs; pragma DisableValidateUnusedExprs; @@ -8944,8 +8879,8 @@ Y_UNIT_TEST_SUITE(CompactNamedExprs) { $foo = count(1); select 1; )"; - SqlToYql(query).IsOk(); - query = R"( + SqlToYql(query).IsOk(); + query = R"( pragma warning("disable", "4527"); pragma CompactNamedExprs; pragma DisableValidateUnusedExprs; @@ -8955,13 +8890,13 @@ Y_UNIT_TEST_SUITE(CompactNamedExprs) { end define; select 1; )"; - SqlToYql(query).IsOk(); - } + SqlToYql(query).IsOk(); } +} // Y_UNIT_TEST_SUITE(CompactNamedExprs) Y_UNIT_TEST_SUITE(ResourcePool) { - Y_UNIT_TEST(CreateResourcePool) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateResourcePool) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE RESOURCE POOL MyResourcePool WITH ( CONCURRENT_QUERY_LIMIT=20, @@ -8969,142 +8904,142 @@ Y_UNIT_TEST_SUITE(ResourcePool) { QUEUE_TYPE="FIFO" ); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"concurrent_query_limit" (Int32 '"20")) '('"query_cancel_after_seconds" (Int32 '"86400")) '('"queue_type" '"FIFO"))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"concurrent_query_limit" (Int32 '"20")) '('"query_cancel_after_seconds" (Int32 '"86400")) '('"queue_type" '"FIFO"))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateResourcePoolWithBadArguments) { +Y_UNIT_TEST(CreateResourcePoolWithBadArguments) { #if ANTLR_VER == 3 - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE RESOURCE POOL MyResourcePool; - )sql" , "<main>:3:47: Error: Unexpected token ';' : syntax error...\n\n"); + )sql", "<main>:3:47: Error: Unexpected token ';' : syntax error...\n\n"); #else - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE RESOURCE POOL MyResourcePool; - )sql" , "<main>:3:47: Error: mismatched input ';' expecting WITH\n"); + )sql", "<main>:3:47: Error: mismatched input ';' expecting WITH\n"); #endif - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE RESOURCE POOL MyResourcePool WITH ( DUPLICATE_SETTING="first_value", DUPLICATE_SETTING="second_value" ); - )sql" , "<main>:5:21: Error: DUPLICATE_SETTING duplicate keys\n"); - } + )sql", "<main>:5:21: Error: DUPLICATE_SETTING duplicate keys\n"); +} - Y_UNIT_TEST(AlterResourcePool) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterResourcePool) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER RESOURCE POOL MyResourcePool SET (CONCURRENT_QUERY_LIMIT = 30, Weight = 5, QUEUE_TYPE = "UNORDERED"), RESET (Query_Cancel_After_Seconds, Query_Count_Limit); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alterObject))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('features '('('"concurrent_query_limit" (Int32 '"30")) '('"queue_type" '"UNORDERED") '('"weight" (Int32 '"5")))))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('resetFeatures '('"query_cancel_after_seconds" '"query_count_limit")))#"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alterObject))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('features '('('"concurrent_query_limit" (Int32 '"30")) '('"queue_type" '"UNORDERED") '('"weight" (Int32 '"5")))))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('resetFeatures '('"query_cancel_after_seconds" '"query_count_limit")))#"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DropResourcePool) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropResourcePool) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP RESOURCE POOL MyResourcePool; )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); } +} // Y_UNIT_TEST_SUITE(ResourcePool) Y_UNIT_TEST_SUITE(BackupCollection) { - Y_UNIT_TEST(CreateBackupCollection) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateBackupCollection) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE BACKUP COLLECTION TestCollection WITH ( STORAGE="local", TAG="test" -- for testing purposes, not a real thing ); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"storage" (String '"local")))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"tag" (String '"test"))))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('entries '()))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'create")); - } - }; + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"storage" (String '"local")))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"tag" (String '"test"))))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('entries '()))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'create")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateBackupCollectionWithDatabase) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateBackupCollectionWithDatabase) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE BACKUP COLLECTION TestCollection DATABASE WITH ( STORAGE="local", TAG="test" -- for testing purposes, not a real thing ); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"storage" (String '"local")))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"tag" (String '"test"))))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('entries '('('('type 'database)))))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'create")); - } - }; + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"storage" (String '"local")))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"tag" (String '"test"))))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('entries '('('('type 'database)))))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'create")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateBackupCollectionWithTables) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateBackupCollectionWithTables) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE BACKUP COLLECTION TestCollection ( TABLE someTable, @@ -9114,148 +9049,148 @@ Y_UNIT_TEST_SUITE(BackupCollection) { TAG="test" -- for testing purposes, not a real thing ); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"storage" (String '"local")))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"tag" (String '"test"))))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('entries '('('('type 'table) '('path '"someTable")) '('('type 'table) '('path '"prefix/anotherTable")))))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'create")); - } - }; + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"storage" (String '"local")))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"tag" (String '"test"))))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('entries '('('('type 'table) '('path '"someTable")) '('('type 'table) '('path '"prefix/anotherTable")))))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'create")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateBackupCollectionWithBadArguments) { +Y_UNIT_TEST(CreateBackupCollectionWithBadArguments) { #if ANTLR_VER == 3 - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE BACKUP COLLECTION TestCollection; - )sql" , "<main>:3:51: Error: Unexpected token ';' : syntax error...\n\n"); + )sql", "<main>:3:51: Error: Unexpected token ';' : syntax error...\n\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE BACKUP COLLECTION TABLE TestCollection; - )sql" , "<main>:3:43: Error: Unexpected token 'TestCollection' : syntax error...\n\n"); + )sql", "<main>:3:43: Error: Unexpected token 'TestCollection' : syntax error...\n\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE BACKUP COLLECTION DATABASE `test` TestCollection; - )sql" , "<main>:3:46: Error: Unexpected token '`test`' : syntax error...\n\n"); + )sql", "<main>:3:46: Error: Unexpected token '`test`' : syntax error...\n\n"); #else - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE BACKUP COLLECTION TestCollection; - )sql" , "<main>:3:55: Error: mismatched input ';' expecting {'(', DATABASE, WITH}\n"); + )sql", "<main>:3:55: Error: mismatched input ';' expecting {'(', DATABASE, WITH}\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE BACKUP COLLECTION TABLE TestCollection; - )sql" , "<main>:3:47: Error: mismatched input 'TestCollection' expecting {'(', DATABASE, WITH}\n"); + )sql", "<main>:3:47: Error: mismatched input 'TestCollection' expecting {'(', DATABASE, WITH}\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE BACKUP COLLECTION DATABASE `test` TestCollection; - )sql" , "<main>:3:50: Error: mismatched input '`test`' expecting {'(', DATABASE, WITH}\n"); + )sql", "<main>:3:50: Error: mismatched input '`test`' expecting {'(', DATABASE, WITH}\n"); #endif - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE BACKUP COLLECTION TestCollection WITH ( DUPLICATE_SETTING="first_value", DUPLICATE_SETTING="second_value" ); - )sql" , "<main>:5:21: Error: DUPLICATE_SETTING duplicate keys\n"); + )sql", "<main>:5:21: Error: DUPLICATE_SETTING duplicate keys\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE BACKUP COLLECTION TestCollection WITH ( INT_SETTING=1 ); - )sql" , "<main>:4:21: Error: INT_SETTING value should be a string literal\n"); - } + )sql", "<main>:4:21: Error: INT_SETTING value should be a string literal\n"); +} - Y_UNIT_TEST(AlterBackupCollection) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterBackupCollection) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER BACKUP COLLECTION TestCollection SET (STORAGE="remote"), -- also just for test SET (TAG1 = "123"), RESET (TAG2, TAG3); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alter))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"storage" (String '"remote")))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"tag1" (String '"123"))))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('resetSettings '('"tag2" '"tag3")))#"); - } - }; + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alter))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"storage" (String '"remote")))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('"tag1" (String '"123"))))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('resetSettings '('"tag2" '"tag3")))#"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(AlterBackupCollectionEntries) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterBackupCollectionEntries) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER BACKUP COLLECTION TestCollection DROP TABLE `test`, ADD DATABASE; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alter))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('alterEntries)#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('type 'table) '('path '"test") '('action 'drop)))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('type 'database) '('action 'add)))#"); - } - }; + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alter))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('alterEntries)#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('type 'table) '('path '"test") '('action 'drop)))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('type 'database) '('action 'add)))#"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DropBackupCollection) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropBackupCollection) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP BACKUP COLLECTION TestCollection; )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("drop")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("drop")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); } +} // Y_UNIT_TEST_SUITE(BackupCollection) Y_UNIT_TEST_SUITE(ResourcePoolClassifier) { - Y_UNIT_TEST(CreateResourcePoolClassifier) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateResourcePoolClassifier) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE RESOURCE POOL CLASSIFIER MyResourcePoolClassifier WITH ( RANK=20, @@ -9263,200 +9198,200 @@ Y_UNIT_TEST_SUITE(ResourcePoolClassifier) { MEMBER_NAME='yandex_query@abc' ); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"member_name" '"yandex_query@abc") '('"rank" (Int32 '"20")) '('"resource_pool" '"wgUserQueries"))#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"member_name" '"yandex_query@abc") '('"rank" (Int32 '"20")) '('"resource_pool" '"wgUserQueries"))#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(CreateResourcePoolClassifierWithBadArguments) { +Y_UNIT_TEST(CreateResourcePoolClassifierWithBadArguments) { #if ANTLR_VER == 3 - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE RESOURCE POOL CLASSIFIER MyResourcePoolClassifier; - )sql" , "<main>:3:68: Error: Unexpected token ';' : syntax error...\n\n"); + )sql", "<main>:3:68: Error: Unexpected token ';' : syntax error...\n\n"); #else - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE RESOURCE POOL CLASSIFIER MyResourcePoolClassifier; - )sql" , "<main>:3:72: Error: mismatched input ';' expecting WITH\n"); + )sql", "<main>:3:72: Error: mismatched input ';' expecting WITH\n"); #endif - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE RESOURCE POOL CLASSIFIER MyResourcePoolClassifier WITH ( DUPLICATE_SETTING="first_value", DUPLICATE_SETTING="second_value" ); - )sql" , "<main>:5:21: Error: DUPLICATE_SETTING duplicate keys\n"); - } + )sql", "<main>:5:21: Error: DUPLICATE_SETTING duplicate keys\n"); +} - Y_UNIT_TEST(AlterResourcePoolClassifier) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterResourcePoolClassifier) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER RESOURCE POOL CLASSIFIER MyResourcePoolClassifier SET (RANK = 30, Weight = 5, MEMBER_NAME = "test@user"), RESET (Resource_Pool); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alterObject))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('features '('('"member_name" '"test@user") '('"rank" (Int32 '"30")) '('"weight" (Int32 '"5")))))#"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('resetFeatures '('"resource_pool")))#"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#(('mode 'alterObject))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('features '('('"member_name" '"test@user") '('"rank" (Int32 '"30")) '('"weight" (Int32 '"5")))))#"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('resetFeatures '('"resource_pool")))#"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DropResourcePoolClassifier) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropResourcePoolClassifier) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP RESOURCE POOL CLASSIFIER MyResourcePoolClassifier; )sql"); - UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.Root); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0}}; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(BacktickMatching) { - auto req = "select\n" - " 1 as `Schema has \\`RealCost\\``\n" - " -- foo`bar"; - auto res = SqlToYql(req); - UNIT_ASSERT(res.Root); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); - res = SqlToYqlWithAnsiLexer(req); - UNIT_ASSERT(res.Root); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); +Y_UNIT_TEST(BacktickMatching) { + auto req = "select\n" + " 1 as `Schema has \\`RealCost\\``\n" + " -- foo`bar"; + auto res = SqlToYql(req); + UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); + res = SqlToYqlWithAnsiLexer(req); + UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); - req = "select 1 as `a``b`, 2 as ````, 3 as `\\x60a\\x60`, 4 as ```b```, 5 as `\\`c\\``"; - res = SqlToYql(req); - UNIT_ASSERT(res.Root); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); - res = SqlToYqlWithAnsiLexer(req); - UNIT_ASSERT(res.Root); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); - } + req = "select 1 as `a``b`, 2 as ````, 3 as `\\x60a\\x60`, 4 as ```b```, 5 as `\\`c\\``"; + res = SqlToYql(req); + UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); + res = SqlToYqlWithAnsiLexer(req); + UNIT_ASSERT(res.Root); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); } +} // Y_UNIT_TEST_SUITE(ResourcePoolClassifier) Y_UNIT_TEST_SUITE(Backup) { - Y_UNIT_TEST(Simple) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(Simple) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; BACKUP TestCollection; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'Incremental")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'backup")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'Incremental")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'backup")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(Incremental) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(Incremental) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; BACKUP TestCollection INCREMENTAL; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'backupIncremental")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'backupIncremental")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); } +} // Y_UNIT_TEST_SUITE(Backup) Y_UNIT_TEST_SUITE(Restore) { - Y_UNIT_TEST(Simple) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(Simple) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; RESTORE TestCollection; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'restore")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'restore")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(AtPoint) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AtPoint) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; RESTORE TestCollection AT '2024-06-16_20-14-02'; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('at '"2024-06-16_20-14-02")#"); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'restore")); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find(R"#('"TestCollection")#")); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('at '"2024-06-16_20-14-02")#"); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'restore")); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); } +} // Y_UNIT_TEST_SUITE(Restore) Y_UNIT_TEST_SUITE(ColumnFamily) { - Y_UNIT_TEST(CompressionLevelCorrectUsage) { - NYql::TAstParseResult res = SqlToYql(R"( use plato; +Y_UNIT_TEST(CompressionLevelCorrectUsage) { + NYql::TAstParseResult res = SqlToYql(R"( use plato; CREATE TABLE tableName ( Key Uint32 FAMILY default, Value String FAMILY family1, @@ -9473,24 +9408,24 @@ Y_UNIT_TEST_SUITE(ColumnFamily) { ) ); )"); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("compression_level")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("5")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("3")); - } - }; + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("compression_level")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("5")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("3")); + } + }; - TWordCountHive elementStat = { { TString("Write"), 0 }, { TString("compression_level"), 0 } }; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["compression_level"]); - } + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("compression_level"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["compression_level"]); +} - Y_UNIT_TEST(FieldDataIsNotString) { - NYql::TAstParseResult res = SqlToYql(R"( use plato; +Y_UNIT_TEST(FieldDataIsNotString) { + NYql::TAstParseResult res = SqlToYql(R"( use plato; CREATE TABLE tableName ( Key Uint32 FAMILY default, PRIMARY KEY (Key), @@ -9501,13 +9436,13 @@ Y_UNIT_TEST_SUITE(ColumnFamily) { ) ); )"); - UNIT_ASSERT(!res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 1); - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "DATA value should be a string literal"); - } + UNIT_ASSERT(!res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 1); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "DATA value should be a string literal"); +} - Y_UNIT_TEST(FieldCompressionIsNotString) { - NYql::TAstParseResult res = SqlToYql(R"( use plato; +Y_UNIT_TEST(FieldCompressionIsNotString) { + NYql::TAstParseResult res = SqlToYql(R"( use plato; CREATE TABLE tableName ( Key Uint32 FAMILY default, PRIMARY KEY (Key), @@ -9518,13 +9453,13 @@ Y_UNIT_TEST_SUITE(ColumnFamily) { ), ); )"); - UNIT_ASSERT(!res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 1); - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "COMPRESSION value should be a string literal"); - } + UNIT_ASSERT(!res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 1); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "COMPRESSION value should be a string literal"); +} - Y_UNIT_TEST(FieldCompressionLevelIsNotInteger) { - NYql::TAstParseResult res = SqlToYql(R"( use plato; +Y_UNIT_TEST(FieldCompressionLevelIsNotInteger) { + NYql::TAstParseResult res = SqlToYql(R"( use plato; CREATE TABLE tableName ( Key Uint32 FAMILY default, PRIMARY KEY (Key), @@ -9535,13 +9470,13 @@ Y_UNIT_TEST_SUITE(ColumnFamily) { ) ); )"); - UNIT_ASSERT(!res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 1); - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "COMPRESSION_LEVEL value should be an integer"); - } + UNIT_ASSERT(!res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 1); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "COMPRESSION_LEVEL value should be an integer"); +} - Y_UNIT_TEST(FieldCacheModeCorrectUsage) { - NYql::TAstParseResult res = SqlToYql(R"sql( use plato; +Y_UNIT_TEST(FieldCacheModeCorrectUsage) { + NYql::TAstParseResult res = SqlToYql(R"sql( use plato; CREATE TABLE tableName ( Key Uint32 FAMILY default, Value String FAMILY family1, @@ -9556,24 +9491,24 @@ Y_UNIT_TEST_SUITE(ColumnFamily) { ) ); )sql"); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("cache_mode")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("regular")); - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("in_memory")); - } - }; + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("cache_mode")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("regular")); + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("in_memory")); + } + }; - TWordCountHive elementStat = { { TString("Write"), 0 }, { TString("cache_mode"), 0 } }; - VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - UNIT_ASSERT_VALUES_EQUAL(2, elementStat["cache_mode"]); - } + TWordCountHive elementStat = {{TString("Write"), 0}, {TString("cache_mode"), 0}}; + VerifyProgram(res, elementStat, verifyLine); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); + UNIT_ASSERT_VALUES_EQUAL(2, elementStat["cache_mode"]); +} - Y_UNIT_TEST(FieldCacheModeIsNotString) { - NYql::TAstParseResult res = SqlToYql(R"sql( use plato; +Y_UNIT_TEST(FieldCacheModeIsNotString) { + NYql::TAstParseResult res = SqlToYql(R"sql( use plato; CREATE TABLE tableName ( Key Uint32 FAMILY default, PRIMARY KEY (Key), @@ -9583,92 +9518,92 @@ Y_UNIT_TEST_SUITE(ColumnFamily) { ) ); )sql"); - UNIT_ASSERT(!res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 1); - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "CACHE_MODE value should be a string literal"); - } + UNIT_ASSERT(!res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 1); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "CACHE_MODE value should be a string literal"); +} - Y_UNIT_TEST(AlterCompressionCorrectUsage) { - NYql::TAstParseResult res = SqlToYql(R"( use plato; +Y_UNIT_TEST(AlterCompressionCorrectUsage) { + NYql::TAstParseResult res = SqlToYql(R"( use plato; ALTER TABLE tableName ALTER FAMILY default SET COMPRESSION "lz4"; )"); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); - } + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); +} - Y_UNIT_TEST(AlterCompressionFieldIsNotString) { - NYql::TAstParseResult res = SqlToYql(R"( use plato; +Y_UNIT_TEST(AlterCompressionFieldIsNotString) { + NYql::TAstParseResult res = SqlToYql(R"( use plato; ALTER TABLE tableName ALTER FAMILY default SET COMPRESSION lz4; )"); - UNIT_ASSERT(!res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 1); + UNIT_ASSERT(!res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 1); #if ANTLR_VER == 3 - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "Unexpected token 'lz4' : cannot match to any predicted input"); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "Unexpected token 'lz4' : cannot match to any predicted input"); #else - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "mismatched input 'lz4' expecting {STRING_VALUE, DIGITS, INTEGER_VALUE}"); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "mismatched input 'lz4' expecting {STRING_VALUE, DIGITS, INTEGER_VALUE}"); #endif - } +} - Y_UNIT_TEST(AlterCompressionLevelCorrectUsage) { - NYql::TAstParseResult res = SqlToYql(R"( use plato; +Y_UNIT_TEST(AlterCompressionLevelCorrectUsage) { + NYql::TAstParseResult res = SqlToYql(R"( use plato; ALTER TABLE tableName ALTER FAMILY default SET COMPRESSION_LEVEL 5; )"); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); - } + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); +} - Y_UNIT_TEST(AlterCompressionLevelFieldIsNotInteger) { - NYql::TAstParseResult res = SqlToYql(R"( use plato; +Y_UNIT_TEST(AlterCompressionLevelFieldIsNotInteger) { + NYql::TAstParseResult res = SqlToYql(R"( use plato; ALTER TABLE tableName ALTER FAMILY default SET COMPRESSION_LEVEL "5"; )"); - UNIT_ASSERT(!res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 1); - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "COMPRESSION_LEVEL value should be an integer"); - } + UNIT_ASSERT(!res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 1); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "COMPRESSION_LEVEL value should be an integer"); +} - Y_UNIT_TEST(AlterCompressionLevelFieldRedefinition) { - NYql::TAstParseResult res = SqlToYql(R"sql( use plato; +Y_UNIT_TEST(AlterCompressionLevelFieldRedefinition) { + NYql::TAstParseResult res = SqlToYql(R"sql( use plato; ALTER TABLE tableName ALTER FAMILY default SET COMPRESSION_LEVEL 3, ALTER FAMILY default SET COMPRESSION_LEVEL 5; )sql"); - UNIT_ASSERT(!res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 1); - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "Redefinition of COMPRESSION_LEVEL setting"); - } + UNIT_ASSERT(!res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 1); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "Redefinition of COMPRESSION_LEVEL setting"); +} - Y_UNIT_TEST(AlterCacheModeCorrectUsage) { - NYql::TAstParseResult res = SqlToYql(R"sql( use plato; +Y_UNIT_TEST(AlterCacheModeCorrectUsage) { + NYql::TAstParseResult res = SqlToYql(R"sql( use plato; ALTER TABLE tableName ALTER FAMILY default SET CACHE_MODE "in_memory"; )sql"); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 0); - } + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 0); +} - Y_UNIT_TEST(AlterCacheModeFieldIsNotInteger) { - NYql::TAstParseResult res = SqlToYql(R"sql( use plato; +Y_UNIT_TEST(AlterCacheModeFieldIsNotInteger) { + NYql::TAstParseResult res = SqlToYql(R"sql( use plato; ALTER TABLE tableName ALTER FAMILY default SET CACHE_MODE 42; )sql"); - UNIT_ASSERT(!res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 1); - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "CACHE_MODE value should be a string literal"); - } + UNIT_ASSERT(!res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 1); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "CACHE_MODE value should be a string literal"); +} - Y_UNIT_TEST(AlterCacheModeFieldRedefinition) { - NYql::TAstParseResult res = SqlToYql(R"sql( use plato; +Y_UNIT_TEST(AlterCacheModeFieldRedefinition) { + NYql::TAstParseResult res = SqlToYql(R"sql( use plato; ALTER TABLE tableName ALTER FAMILY default SET CACHE_MODE "in_memory", ALTER FAMILY default SET CACHE_MODE "regular"; )sql"); - UNIT_ASSERT(!res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 1); - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "Redefinition of CACHE_MODE setting"); - } + UNIT_ASSERT(!res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 1); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "Redefinition of CACHE_MODE setting"); } +} // Y_UNIT_TEST_SUITE(ColumnFamily) Y_UNIT_TEST_SUITE(Transfer) { - Y_UNIT_TEST(Lambda) { - NYql::TAstParseResult res = SqlToYql(R"( use plato; +Y_UNIT_TEST(Lambda) { + NYql::TAstParseResult res = SqlToYql(R"( use plato; -- Русский коммент, empty statement ; @@ -9690,13 +9625,13 @@ Y_UNIT_TEST_SUITE(Transfer) { ); )"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - UNIT_ASSERT_VALUES_EQUAL_C(res.Issues.Size(), 0, res.Issues.ToString()); + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); + UNIT_ASSERT_VALUES_EQUAL_C(res.Issues.Size(), 0, res.Issues.ToString()); - const auto programm = GetPrettyPrint(res); + const auto programm = GetPrettyPrint(res); - Cerr << ">>>>> Root " << programm << Endl; - auto expected = R"('transformLambda 'use plato; + Cerr << ">>>>> Root " << programm << Endl; + auto expected = R"('transformLambda 'use plato; -- befor comment $a = "А"; $b = ($x) -> { return $a || $x; }; @@ -9706,143 +9641,138 @@ $__ydb_transfer_lambda = ($x) -> { }; ))"; - UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, programm.find(expected)); - - } + UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, programm.find(expected)); } +} // Y_UNIT_TEST_SUITE(Transfer) Y_UNIT_TEST_SUITE(MatchRecognizeMeasuresAggregation) { - Y_UNIT_TEST(InsideSelect) { - ExpectFailWithError(R"sql( +Y_UNIT_TEST(InsideSelect) { + ExpectFailWithError(R"sql( SELECT FIRST(0), LAST(1); )sql", - "<main>:2:20: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" - "<main>:2:30: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" - ); - } + "<main>:2:20: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" + "<main>:2:30: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n"); +} - Y_UNIT_TEST(OutsideSelect) { - ExpectFailWithError(R"sql( +Y_UNIT_TEST(OutsideSelect) { + ExpectFailWithError(R"sql( $lambda = ($x) -> (FIRST($x) + LAST($x)); SELECT $lambda(x) FROM plato.Input; )sql", - "<main>:2:32: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" - "<main>:2:44: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" - ); - } + "<main>:2:32: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" + "<main>:2:44: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n"); +} - Y_UNIT_TEST(AsAggregateFunction) { - ExpectFailWithError(R"sql( +Y_UNIT_TEST(AsAggregateFunction) { + ExpectFailWithError(R"sql( SELECT FIRST(x), LAST(x) FROM plato.Input; )sql", - "<main>:2:20: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" - "<main>:2:30: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" - ); - } + "<main>:2:20: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" + "<main>:2:30: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n"); +} - Y_UNIT_TEST(AsWindowFunction) { - ExpectFailWithError(R"sql( +Y_UNIT_TEST(AsWindowFunction) { + ExpectFailWithError(R"sql( SELECT FIRST(x) OVER(), LAST(x) OVER() FROM plato.Input; )sql", - "<main>:2:20: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" - "<main>:2:37: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" - ); - } + "<main>:2:20: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n" + "<main>:2:37: Error: Cannot use FIRST and LAST outside the MATCH_RECOGNIZE context\n"); } +} // Y_UNIT_TEST_SUITE(MatchRecognizeMeasuresAggregation) Y_UNIT_TEST_SUITE(OlapPartitionCount) { - Y_UNIT_TEST(CorrectUsage) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CorrectUsage) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE TABLE `mytable` (id Uint32, PRIMARY KEY (id)) PARTITION BY HASH(id) WITH (STORE = COLUMN, PARTITION_COUNT = 8); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); +} - Y_UNIT_TEST(UseWithoutColumnStore) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(UseWithoutColumnStore) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE TABLE `mytable` (id Uint32, PRIMARY KEY (id)) WITH (PARTITION_COUNT = 8); )sql"); - UNIT_ASSERT(!res.IsOk()); - UNIT_ASSERT(res.Issues.Size() == 1); - UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "PARTITION_COUNT can be used only with STORE=COLUMN"); - } + UNIT_ASSERT(!res.IsOk()); + UNIT_ASSERT(res.Issues.Size() == 1); + UNIT_ASSERT_STRING_CONTAINS(res.Issues.ToString(), "PARTITION_COUNT can be used only with STORE=COLUMN"); } +} // Y_UNIT_TEST_SUITE(OlapPartitionCount) Y_UNIT_TEST_SUITE(Crashes) { - Y_UNIT_TEST(IncorrectCorrQuery) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(IncorrectCorrQuery) { + NYql::TAstParseResult res = SqlToYql(R"sql( use plato; SELECT COUNT(DISTINCT EXISTS (SELECT 1 FROM t1 AS t2)) FROM Input AS t1 )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); } +} // Y_UNIT_TEST_SUITE(Crashes) Y_UNIT_TEST_SUITE(Aggregation) { - Y_UNIT_TEST(DeduplicationDistinctSources) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DeduplicationDistinctSources) { + NYql::TAstParseResult res = SqlToYql(R"sql( SELECT Percentile(a.x, 0.50), Percentile(b.x, 0.75) FROM plato.Input1 AS a JOIN plato.Input1 AS b ON a.x == b.x; )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - TWordCountHive count = {{TString("percentile_traits_factory"), 0}}; - VerifyProgram(res, count); + TWordCountHive count = {{TString("percentile_traits_factory"), 0}}; + VerifyProgram(res, count); - UNIT_ASSERT_VALUES_EQUAL(2, count["percentile_traits_factory"]); - } + UNIT_ASSERT_VALUES_EQUAL(2, count["percentile_traits_factory"]); +} - Y_UNIT_TEST(DeduplicationSameSource) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DeduplicationSameSource) { + NYql::TAstParseResult res = SqlToYql(R"sql( SELECT Percentile(a.x, 0.50), Percentile(a.x, 0.75) FROM plato.Input1 AS a JOIN plato.Input1 AS b ON a.x == b.x; )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - TWordCountHive count = {{TString("percentile_traits_factory"), 0}}; - VerifyProgram(res, count); + TWordCountHive count = {{TString("percentile_traits_factory"), 0}}; + VerifyProgram(res, count); - UNIT_ASSERT_VALUES_EQUAL(1, count["percentile_traits_factory"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, count["percentile_traits_factory"]); } +} // Y_UNIT_TEST_SUITE(Aggregation) Y_UNIT_TEST_SUITE(AggregationPhases) { - Y_UNIT_TEST(TwoArg) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(TwoArg) { + NYql::TAstParseResult res = SqlToYql(R"sql( SELECT AvgIf(a, a % 2 == 0) FROM (SELECT 1 AS k, 2 AS a) GROUP BY k; SELECT AvgIf(a, a % 2 == 0) FROM (SELECT 1 AS k, 2 AS a) GROUP BY k WITH Combine; SELECT AvgIf(a, a % 2 == 0) FROM (SELECT 1 AS k, 2 AS a) GROUP BY k WITH Finalize; )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); +} - Y_UNIT_TEST(SingleArg) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(SingleArg) { + NYql::TAstParseResult res = SqlToYql(R"sql( SELECT AvgIf(a) FROM (SELECT 1 AS k, 2 AS a) GROUP BY k WITH CombineState; SELECT AvgIf(a) FROM (SELECT 1 AS k, 2 AS a) GROUP BY k WITH MergeState; )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); } +} // Y_UNIT_TEST_SUITE(AggregationPhases) Y_UNIT_TEST_SUITE(Watermarks) { - Y_UNIT_TEST(Insert) { - const auto stmt = R"sql( +Y_UNIT_TEST(Insert) { + const auto stmt = R"sql( USE plato; INSERT INTO Output @@ -9856,13 +9786,13 @@ WITH( WATERMARK AS (ts) ); )sql"; - const auto& res = SqlToYql(stmt); - Err2Str(res, EDebugOutput::ToCerr); - UNIT_ASSERT(res.IsOk()); - } + const auto& res = SqlToYql(stmt); + Err2Str(res, EDebugOutput::ToCerr); + UNIT_ASSERT(res.IsOk()); +} - Y_UNIT_TEST(Select) { - const auto stmt = R"sql( +Y_UNIT_TEST(Select) { + const auto stmt = R"sql( USE plato; SELECT @@ -9875,44 +9805,42 @@ WITH( WATERMARK AS (ts) ); )sql"; - const auto& res = SqlToYql(stmt); - Err2Str(res, EDebugOutput::ToCerr); - UNIT_ASSERT(res.IsOk()); - } + const auto& res = SqlToYql(stmt); + Err2Str(res, EDebugOutput::ToCerr); + UNIT_ASSERT(res.IsOk()); } +} // Y_UNIT_TEST_SUITE(Watermarks) Y_UNIT_TEST_SUITE(HoppingWindow) { - Y_UNIT_TEST(HoppingWindow) { - auto query = R"sql( +Y_UNIT_TEST(HoppingWindow) { + auto query = R"sql( SELECT * FROM plato.Input GROUP BY HoppingWindow(key, 39, 42); )sql"; - NYql::TAstParseResult res = SqlToYql(query); - UNIT_ASSERT_VALUES_UNEQUAL(nullptr, res.Root); - UNIT_ASSERT(res.IsOk()); - UNIT_ASSERT_VALUES_EQUAL(0, res.Issues.Size()); - } + NYql::TAstParseResult res = SqlToYql(query); + UNIT_ASSERT_VALUES_UNEQUAL(nullptr, res.Root); + UNIT_ASSERT(res.IsOk()); + UNIT_ASSERT_VALUES_EQUAL(0, res.Issues.Size()); +} - Y_UNIT_TEST(HoppingWindowWithoutSource) { - ExpectFailWithError( - R"sql(SELECT 1 + HoppingWindow(key, 39, 42);)sql", - "<main>:1:12: Error: HoppingWindow requires data source\n" - ); - } +Y_UNIT_TEST(HoppingWindowWithoutSource) { + ExpectFailWithError( + R"sql(SELECT 1 + HoppingWindow(key, 39, 42);)sql", + "<main>:1:12: Error: HoppingWindow requires data source\n"); +} - Y_UNIT_TEST(HoppingWindowInProjection) { - ExpectFailWithError( - R"sql(SELECT 1 + HoppingWindow(key, 39, 42) FROM plato.Input;)sql", - "<main>:1:12: Error: HoppingWindow can only be used as a top-level GROUP BY expression\n" - ); - } +Y_UNIT_TEST(HoppingWindowInProjection) { + ExpectFailWithError( + R"sql(SELECT 1 + HoppingWindow(key, 39, 42) FROM plato.Input;)sql", + "<main>:1:12: Error: HoppingWindow can only be used as a top-level GROUP BY expression\n"); +} - Y_UNIT_TEST(HoppingWindowWithNonConstIntervals) { - ExpectFailWithError( - R"sql( +Y_UNIT_TEST(HoppingWindowWithNonConstIntervals) { + ExpectFailWithError( + R"sql( SELECT key, hopping_start @@ -9922,12 +9850,11 @@ Y_UNIT_TEST_SUITE(HoppingWindow) { key; )sql", - "<main>:7:21: Error: Source does not allow column references\n" - "<main>:7:45: Error: Column reference 'subkey'\n" - ); + "<main>:7:21: Error: Source does not allow column references\n" + "<main>:7:45: Error: Column reference 'subkey'\n"); - ExpectFailWithError( - R"sql( + ExpectFailWithError( + R"sql( SELECT key, hopping_start @@ -9937,38 +9864,35 @@ Y_UNIT_TEST_SUITE(HoppingWindow) { key; )sql", - "<main>:7:21: Error: Source does not allow column references\n" - "<main>:7:45: Error: Column reference 'subkey'\n" - ); - } + "<main>:7:21: Error: Source does not allow column references\n" + "<main>:7:45: Error: Column reference 'subkey'\n"); +} - Y_UNIT_TEST(HoppingWindowWithWrongNumberOfArgs) { - ExpectFailWithError( - R"sql( +Y_UNIT_TEST(HoppingWindowWithWrongNumberOfArgs) { + ExpectFailWithError( + R"sql( SELECT * FROM plato.Input GROUP BY HoppingWindow(key, 39); )sql", - "<main>:5:26: Error: HoppingWindow requires three arguments\n" - ); + "<main>:5:26: Error: HoppingWindow requires three arguments\n"); - ExpectFailWithError( - R"sql( + ExpectFailWithError( + R"sql( SELECT * FROM plato.Input GROUP BY HoppingWindow(key, 39, 42, 63); )sql", - "<main>:5:26: Error: HoppingWindow requires three arguments\n" - ); - } + "<main>:5:26: Error: HoppingWindow requires three arguments\n"); +} - Y_UNIT_TEST(DuplicateHoppingWindow) { - ExpectFailWithError( - R"sql( +Y_UNIT_TEST(DuplicateHoppingWindow) { + ExpectFailWithError( + R"sql( SELECT * FROM plato.Input @@ -9978,63 +9902,56 @@ Y_UNIT_TEST_SUITE(HoppingWindow) { HoppingWindow(ts, 42, 39); )sql", - "<main>:8:21: Error: Duplicate hopping window specification:\n" - "<main>:6:21: Error: Previous hopping window is declared here\n" - ); - } + "<main>:8:21: Error: Duplicate hopping window specification:\n" + "<main>:6:21: Error: Previous hopping window is declared here\n"); +} - Y_UNIT_TEST(HopStartEndWithoutSource) { - ExpectFailWithError( - R"sql(SELECT 1 + HopStart();)sql", - "<main>:1:12: Error: HopStart requires data source\n" - ); +Y_UNIT_TEST(HopStartEndWithoutSource) { + ExpectFailWithError( + R"sql(SELECT 1 + HopStart();)sql", + "<main>:1:12: Error: HopStart requires data source\n"); - ExpectFailWithError( - R"sql(SELECT 1 + HopEnd();)sql", - "<main>:1:12: Error: HopEnd requires data source\n" - ); - } + ExpectFailWithError( + R"sql(SELECT 1 + HopEnd();)sql", + "<main>:1:12: Error: HopEnd requires data source\n"); +} - Y_UNIT_TEST(HopStartEndWithoutGroupByOrWindow) { - ExpectFailWithError( - R"sql(SELECT 1 + HopStart() FROM plato.Input;)sql", - "<main>:1:12: Error: HopStart can not be used without aggregation by HoppingWindow\n" - ); +Y_UNIT_TEST(HopStartEndWithoutGroupByOrWindow) { + ExpectFailWithError( + R"sql(SELECT 1 + HopStart() FROM plato.Input;)sql", + "<main>:1:12: Error: HopStart can not be used without aggregation by HoppingWindow\n"); - ExpectFailWithError( - R"sql(SELECT 1 + HopEnd() FROM plato.Input;)sql", - "<main>:1:12: Error: HopEnd can not be used without aggregation by HoppingWindow\n" - ); - } + ExpectFailWithError( + R"sql(SELECT 1 + HopEnd() FROM plato.Input;)sql", + "<main>:1:12: Error: HopEnd can not be used without aggregation by HoppingWindow\n"); +} - Y_UNIT_TEST(HopStartEndWithGroupByWithoutHopping) { - ExpectFailWithError( - R"sql( +Y_UNIT_TEST(HopStartEndWithGroupByWithoutHopping) { + ExpectFailWithError( + R"sql( SELECT 1 + HopStart() FROM plato.Input GROUP BY user; )sql", - "<main>:3:25: Error: HopStart can not be used here: HoppingWindow specification is missing in GROUP BY\n" - ); + "<main>:3:25: Error: HopStart can not be used here: HoppingWindow specification is missing in GROUP BY\n"); - ExpectFailWithError( - R"sql( + ExpectFailWithError( + R"sql( SELECT 1 + HopEnd() FROM plato.Input GROUP BY user; )sql", - "<main>:3:25: Error: HopEnd can not be used here: HoppingWindow specification is missing in GROUP BY\n" - ); - } + "<main>:3:25: Error: HopEnd can not be used here: HoppingWindow specification is missing in GROUP BY\n"); } +} // Y_UNIT_TEST_SUITE(HoppingWindow) Y_UNIT_TEST_SUITE(StreamingQuery) { - Y_UNIT_TEST(CreateStreamingQueryBasic) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateStreamingQueryBasic) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE TABLE test (Key Int32 NOT NULL, PRIMARY KEY (Key)); -- Some comment @@ -10047,32 +9964,32 @@ INSERT INTO Output2 SELECT * FROM $source;END DO; USE hahn; -- Other comment )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "createObject") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "createObject") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); + } - if (word == "__query_text") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '"\nPRAGMA DisableAnsiInForEmptyOrNullableItemsCollections;\nUSE plato;\n$source = SELECT * FROM Input;\nINSERT INTO Output1 SELECT * FROM $source;\nINSERT INTO Output2 SELECT * FROM $source;")))#"); - } - }; + if (word == "__query_text") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '"\nPRAGMA DisableAnsiInForEmptyOrNullableItemsCollections;\nUSE plato;\n$source = SELECT * FROM Input;\nINSERT INTO Output1 SELECT * FROM $source;\nINSERT INTO Output2 SELECT * FROM $source;")))#"); + } + }; - TWordCountHive elementStat = { - {TString("createObject"), 0}, - {TString("__query_text"), 0}, - {TString("(let world (World))"), 0}, - }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = { + {TString("createObject"), 0}, + {TString("__query_text"), 0}, + {TString("(let world (World))"), 0}, + }; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObject"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["(let world (World))"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObject"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["(let world (World))"]); +} - Y_UNIT_TEST(CreateStreamingQueryCrlfCheck) { - NYql::TAstParseResult res = SqlToYql(TStringBuilder() << R"sql( +Y_UNIT_TEST(CreateStreamingQueryCrlfCheck) { + NYql::TAstParseResult res = SqlToYql(TStringBuilder() << R"sql( USE plato; -- Some comment CREATE STREAMING QUERY MyQuery AS DO )sql" << "\r" << R"sql(BEGIN @@ -10084,27 +10001,27 @@ END DO; USE hahn; -- Other comment )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "createObject") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "createObject") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); + } - if (word == "__query_text") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '"\nUSE plato;\n$source = SELECT * FROM Input;\nINSERT INTO Output1 SELECT * FROM $source;\nINSERT INTO Output2 SELECT * FROM $source;\n")))#"); - } - }; + if (word == "__query_text") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '"\nUSE plato;\n$source = SELECT * FROM Input;\nINSERT INTO Output1 SELECT * FROM $source;\nINSERT INTO Output2 SELECT * FROM $source;\n")))#"); + } + }; - TWordCountHive elementStat = { {TString("createObject"), 0}, {TString("__query_text"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("createObject"), 0}, {TString("__query_text"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObject"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObject"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); +} - Y_UNIT_TEST(CreateStreamingQueryWithSettings) { - NYql::TAstParseResult res = SqlToYql(TStringBuilder() << R"sql( +Y_UNIT_TEST(CreateStreamingQueryWithSettings) { + NYql::TAstParseResult res = SqlToYql(TStringBuilder() << R"sql( USE plato; -- Some comment CREATE STREAMING QUERY MyQuery WITH ( @@ -10119,113 +10036,113 @@ END DO; USE hahn; -- Other comment )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "createObject") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "createObject") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); + } - if (word == "__query_text") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '"\nUSE plato;\n$source = SELECT * FROM Input;\nINSERT INTO Output1 SELECT * FROM $source;\nINSERT INTO Output2 SELECT * FROM $source;\n") '('"resource_pool" '"my_pool") '('"run" (Bool '"true")))#"); - } - }; + if (word == "__query_text") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '"\nUSE plato;\n$source = SELECT * FROM Input;\nINSERT INTO Output1 SELECT * FROM $source;\nINSERT INTO Output2 SELECT * FROM $source;\n") '('"resource_pool" '"my_pool") '('"run" (Bool '"true")))#"); + } + }; - TWordCountHive elementStat = { {TString("createObject"), 0}, {TString("__query_text"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("createObject"), 0}, {TString("__query_text"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObject"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObject"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); +} - Y_UNIT_TEST(CreateOrReplaceStreamingQuery) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateOrReplaceStreamingQuery) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE OR REPLACE STREAMING QUERY MyQuery AS DO BEGIN /* create or replace */ SELECT 42; END DO; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "createObjectOrReplace") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "createObjectOrReplace") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); + } - if (word == "__query_text") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" /* create or replace */ SELECT 42; ")))#"); - } - }; + if (word == "__query_text") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" /* create or replace */ SELECT 42; ")))#"); + } + }; - TWordCountHive elementStat = { {TString("createObjectOrReplace"), 0}, {TString("__query_text"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("createObjectOrReplace"), 0}, {TString("__query_text"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObjectOrReplace"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObjectOrReplace"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); +} - Y_UNIT_TEST(CreateStreamingQueryIfNotExists) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateStreamingQueryIfNotExists) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; CREATE STREAMING QUERY IF NOT EXISTS MyQuery AS DO BEGIN /* create if not exists */ SELECT 42; END DO; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "createObjectIfNotExists") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "createObjectIfNotExists") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); + } - if (word == "__query_text") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" /* create if not exists */ SELECT 42; ")))#"); - } - }; + if (word == "__query_text") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" /* create if not exists */ SELECT 42; ")))#"); + } + }; - TWordCountHive elementStat = { {TString("createObjectIfNotExists"), 0}, {TString("__query_text"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("createObjectIfNotExists"), 0}, {TString("__query_text"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObjectIfNotExists"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObjectIfNotExists"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); +} - Y_UNIT_TEST(CreateStreamingQueryWithTablePrefix) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(CreateStreamingQueryWithTablePrefix) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; PRAGMA TablePathPrefix='/aba'; CREATE STREAMING QUERY MyQuery AS DO BEGIN SELECT * FROM hahn.Input; END DO; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "createObject") { - UNIT_ASSERT_STRING_CONTAINS(line, "/aba/MyQuery"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "createObject") { + UNIT_ASSERT_STRING_CONTAINS(line, "/aba/MyQuery"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); + } - if (word == "__query_text") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" SELECT * FROM hahn.Input; ")))#"); - } - }; + if (word == "__query_text") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" SELECT * FROM hahn.Input; ")))#"); + } + }; - TWordCountHive elementStat = { {TString("createObject"), 0}, {TString("__query_text"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("createObject"), 0}, {TString("__query_text"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObject"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["createObject"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); +} - Y_UNIT_TEST(CreateStreamingQueryWithBadArguments) { +Y_UNIT_TEST(CreateStreamingQueryWithBadArguments) { #if ANTLR_VER == 3 - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE STREAMING QUERY MyQuery WITH (OPTION = "VALUE"); - )sql" , "<main>:3:66: Error: Unexpected token ';' : syntax error...\n\n"); + )sql", "<main>:3:66: Error: Unexpected token ';' : syntax error...\n\n"); #else - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE STREAMING QUERY MyQuery WITH (OPTION = "VALUE"); - )sql" , "<main>:3:66: Error: mismatched input ';' expecting AS\n"); + )sql", "<main>:3:66: Error: mismatched input ';' expecting AS\n"); #endif - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE STREAMING QUERY MyQuery WITH ( DUPLICATE_SETTING = "first_value", @@ -10235,9 +10152,9 @@ USE hahn; USE plato; INSERT INTO Output SELECT * FROM Input; END DO; - )sql" , "<main>:5:17: Error: Found duplicated parameter: DUPLICATE_SETTING\n"); + )sql", "<main>:5:17: Error: Found duplicated parameter: DUPLICATE_SETTING\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; CREATE STREAMING QUERY MyQuery WITH ( `__QUERY_TEXT` = "SELECT 42" @@ -10246,20 +10163,20 @@ USE hahn; USE plato; INSERT INTO Output SELECT * FROM Input; END DO; - )sql" , "<main>:4:17: Error: Streaming query parameter name should not start with prefix '__': __QUERY_TEXT\n"); + )sql", "<main>:4:17: Error: Streaming query parameter name should not start with prefix '__': __QUERY_TEXT\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; $named_node = 42; CREATE STREAMING QUERY MyQuery AS DO BEGIN SELECT $named_node; END DO; - )sql" , "<main>:6:24: Error: Unknown name: $named_node\n"); - } + )sql", "<main>:6:24: Error: Unknown name: $named_node\n"); +} - Y_UNIT_TEST(AlterStreamingQuerySetQuery) { - NYql::TAstParseResult res = SqlToYql(TStringBuilder() << R"sql( +Y_UNIT_TEST(AlterStreamingQuerySetQuery) { + NYql::TAstParseResult res = SqlToYql(TStringBuilder() << R"sql( USE plato; CREATE TABLE test (Key Int32 NOT NULL, PRIMARY KEY (Key)); -- Some comment @@ -10273,212 +10190,212 @@ END DO; USE hahn; -- Other comment )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "alterObject") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "alterObject") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); + } - if (word == "__query_text") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '"\nPRAGMA DisableAnsiInForEmptyOrNullableItemsCollections;\nUSE plato;\n$source = SELECT * FROM Input;\nINSERT INTO Output1 SELECT * FROM $source;\nINSERT INTO Output2 SELECT * FROM $source;\n")))#"); - } - }; + if (word == "__query_text") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '"\nPRAGMA DisableAnsiInForEmptyOrNullableItemsCollections;\nUSE plato;\n$source = SELECT * FROM Input;\nINSERT INTO Output1 SELECT * FROM $source;\nINSERT INTO Output2 SELECT * FROM $source;\n")))#"); + } + }; - TWordCountHive elementStat = { - {TString("alterObject"), 0}, - {TString("__query_text"), 0}, - {TString("(let world (World))"), 0}, - }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = { + {TString("alterObject"), 0}, + {TString("__query_text"), 0}, + {TString("(let world (World))"), 0}, + }; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["alterObject"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["(let world (World))"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["alterObject"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["(let world (World))"]); +} - Y_UNIT_TEST(AlterStreamingQuerySetOptions) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterStreamingQuerySetOptions) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER STREAMING QUERY MyQuery SET ( WAIT_CHECKPOINT = TRUE, RESOURCE_POOL = other_pool ); )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"resource_pool" '"other_pool") '('"wait_checkpoint" (Bool '"true"))))#"); - UNIT_ASSERT_STRING_CONTAINS(line, "alterObject"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('('"resource_pool" '"other_pool") '('"wait_checkpoint" (Bool '"true"))))#"); + UNIT_ASSERT_STRING_CONTAINS(line, "alterObject"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(AlterStreamingQuerySetBothOptionsAndQuery) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterStreamingQuerySetBothOptionsAndQuery) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER STREAMING QUERY MyQuery SET ( WAIT_CHECKPOINT = TRUE, RESOURCE_POOL = other_pool ) AS DO BEGIN /* alter */ SELECT 42; END DO; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "alterObject") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "alterObject") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); + } - if (word == "__query_text") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" /* alter */ SELECT 42; ") '('"resource_pool" '"other_pool") '('"wait_checkpoint" (Bool '"true"))))#"); - } - }; + if (word == "__query_text") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" /* alter */ SELECT 42; ") '('"resource_pool" '"other_pool") '('"wait_checkpoint" (Bool '"true"))))#"); + } + }; - TWordCountHive elementStat = { {TString("alterObject"), 0}, {TString("__query_text"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("alterObject"), 0}, {TString("__query_text"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["alterObject"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["alterObject"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); +} - Y_UNIT_TEST(AlterStreamingQueryIfExists) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterStreamingQueryIfExists) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; ALTER STREAMING QUERY IF EXISTS MyQuery AS DO BEGIN /* alter if exists */ SELECT 42; END DO; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "alterObjectIfExists") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "alterObjectIfExists") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); + } - if (word == "__query_text") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" /* alter if exists */ SELECT 42; ")))#"); - } - }; + if (word == "__query_text") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" /* alter if exists */ SELECT 42; ")))#"); + } + }; - TWordCountHive elementStat = { {TString("alterObjectIfExists"), 0}, {TString("__query_text"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("alterObjectIfExists"), 0}, {TString("__query_text"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["alterObjectIfExists"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["alterObjectIfExists"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); +} - Y_UNIT_TEST(AlterStreamingQueryWithTablePrefix) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(AlterStreamingQueryWithTablePrefix) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; PRAGMA TablePathPrefix='/aba'; ALTER STREAMING QUERY MyQuery AS DO BEGIN SELECT * FROM hahn.Input; END DO; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "alterObject") { - UNIT_ASSERT_STRING_CONTAINS(line, "/aba/MyQuery"); - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); - } + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "alterObject") { + UNIT_ASSERT_STRING_CONTAINS(line, "/aba/MyQuery"); + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_ast" (block '()#"); + } - if (word == "__query_text") { - UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" SELECT * FROM hahn.Input; ")))#"); - } - }; + if (word == "__query_text") { + UNIT_ASSERT_STRING_CONTAINS(line, R"#('('"__query_text" '" SELECT * FROM hahn.Input; ")))#"); + } + }; - TWordCountHive elementStat = { {TString("alterObject"), 0}, {TString("__query_text"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("alterObject"), 0}, {TString("__query_text"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["alterObject"]); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["alterObject"]); + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["__query_text"]); +} - Y_UNIT_TEST(AlterStreamingQueryWithBadArguments) { +Y_UNIT_TEST(AlterStreamingQueryWithBadArguments) { #if ANTLR_VER == 3 - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; ALTER STREAMING QUERY MyQuery; - )sql" , "<main>:3:41: Error: Unexpected token ';' : cannot match to any predicted input...\n\n"); + )sql", "<main>:3:41: Error: Unexpected token ';' : cannot match to any predicted input...\n\n"); #else - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; ALTER STREAMING QUERY MyQuery; - )sql" , "<main>:3:41: Error: mismatched input ';' expecting {AS, SET}\n"); + )sql", "<main>:3:41: Error: mismatched input ';' expecting {AS, SET}\n"); #endif - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; ALTER STREAMING QUERY MyQuery SET ( DUPLICATE_SETTING = "first_value", DUPLICATE_SETTING = "second_value" ); - )sql" , "<main>:5:17: Error: Found duplicated parameter: DUPLICATE_SETTING\n"); + )sql", "<main>:5:17: Error: Found duplicated parameter: DUPLICATE_SETTING\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; ALTER STREAMING QUERY MyQuery SET ( `__QUERY_TEXT` = "SELECT 42" ); - )sql" , "<main>:4:17: Error: Streaming query parameter name should not start with prefix '__': __QUERY_TEXT\n"); + )sql", "<main>:4:17: Error: Streaming query parameter name should not start with prefix '__': __QUERY_TEXT\n"); - ExpectFailWithError(R"sql( + ExpectFailWithError(R"sql( USE plato; $named_node = 42; ALTER STREAMING QUERY MyQuery AS DO BEGIN SELECT $named_node; END DO; - )sql" , "<main>:6:24: Error: Unknown name: $named_node\n"); - } + )sql", "<main>:6:24: Error: Unknown name: $named_node\n"); +} - Y_UNIT_TEST(DropStreamingQueryBasic) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropStreamingQueryBasic) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP STREAMING QUERY MyQuery; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); - UNIT_ASSERT_STRING_CONTAINS(line, "dropObject"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); + UNIT_ASSERT_STRING_CONTAINS(line, "dropObject"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); +} - Y_UNIT_TEST(DropStreamingQueryIfExists) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(DropStreamingQueryIfExists) { + NYql::TAstParseResult res = SqlToYql(R"sql( USE plato; DROP STREAMING QUERY IF EXISTS MyQuery; )sql"); - UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.Root, res.Issues.ToOneLineString()); - TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { - if (word == "Write") { - UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); - UNIT_ASSERT_STRING_CONTAINS(line, "dropObjectIfExists"); - } - }; + TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) { + if (word == "Write") { + UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features")); + UNIT_ASSERT_STRING_CONTAINS(line, "dropObjectIfExists"); + } + }; - TWordCountHive elementStat = { {TString("Write"), 0} }; - VerifyProgram(res, elementStat, verifyLine); + TWordCountHive elementStat = {{TString("Write"), 0}}; + VerifyProgram(res, elementStat, verifyLine); - UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); - } + UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]); } +} // Y_UNIT_TEST_SUITE(StreamingQuery) Y_UNIT_TEST_SUITE(TestGetQueryPosition) { - Y_UNIT_TEST(TestTokenFinding) { - const TString query = TStringBuilder() << R"( +Y_UNIT_TEST(TestTokenFinding) { + const TString query = TStringBuilder() << R"( )" << "\r" << R"(BEGIN)" << "\r\n" << R"( )" << "\n\r" << R"(END $b = ()" << "\r\r" << R"($x) -> { @@ -10490,256 +10407,256 @@ return /*Комментарий*/ $x; }; )"; - NSQLTranslationV1::TLexers lexers; + NSQLTranslationV1::TLexers lexers; #if ANTLR_VER == 3 - bool antlr4 = false; - lexers.Antlr3 = NSQLTranslationV1::MakeAntlr3LexerFactory(); + bool antlr4 = false; + lexers.Antlr3 = NSQLTranslationV1::MakeAntlr3LexerFactory(); #else - bool antlr4 = true; - lexers.Antlr4 = NSQLTranslationV1::MakeAntlr4LexerFactory(); + bool antlr4 = true; + lexers.Antlr4 = NSQLTranslationV1::MakeAntlr4LexerFactory(); #endif - ui64 lexerPosition = 0; - const auto onNextToken = [&](NSQLTranslation::TParsedToken&& token) { - NSQLv1Generated::TToken tokenProto; - tokenProto.SetLine(token.Line); - tokenProto.SetColumn(token.LinePos); - UNIT_ASSERT_VALUES_EQUAL_C(lexerPosition, NSQLTranslationV1::GetQueryPosition(query, tokenProto, antlr4), token.Line << ":" << token.LinePos << ":'" << token.Content << "'"); + ui64 lexerPosition = 0; + const auto onNextToken = [&](NSQLTranslation::TParsedToken&& token) { + NSQLv1Generated::TToken tokenProto; + tokenProto.SetLine(token.Line); + tokenProto.SetColumn(token.LinePos); + UNIT_ASSERT_VALUES_EQUAL_C(lexerPosition, NSQLTranslationV1::GetQueryPosition(query, tokenProto, antlr4), token.Line << ":" << token.LinePos << ":'" << token.Content << "'"); - lexerPosition += token.Content.size(); - }; + lexerPosition += token.Content.size(); + }; - const auto lexer = NSQLTranslationV1::MakeLexer(lexers, false, antlr4); + const auto lexer = NSQLTranslationV1::MakeLexer(lexers, false, antlr4); - NYql::TIssues issues; - const bool result = lexer->Tokenize(query, {}, onNextToken, issues, NSQLTranslation::SQL_MAX_PARSER_ERRORS); - UNIT_ASSERT_C(result, issues.ToOneLineString()); - } + NYql::TIssues issues; + const bool result = lexer->Tokenize(query, {}, onNextToken, issues, NSQLTranslation::SQL_MAX_PARSER_ERRORS); + UNIT_ASSERT_C(result, issues.ToOneLineString()); +} - Y_UNIT_TEST(TestTokenMissing) { - const TString query = "BEGIN /*Комментарий*/ \nEND"; - NSQLv1Generated::TToken tokenProto; +Y_UNIT_TEST(TestTokenMissing) { + const TString query = "BEGIN /*Комментарий*/ \nEND"; + NSQLv1Generated::TToken tokenProto; #if ANTLR_VER == 3 - bool antlr4 = false; + bool antlr4 = false; #else - bool antlr4 = true; + bool antlr4 = true; #endif - tokenProto.SetLine(3); - tokenProto.SetColumn(0); - UNIT_ASSERT_VALUES_EQUAL(std::string::npos, NSQLTranslationV1::GetQueryPosition(query, tokenProto, antlr4)); + tokenProto.SetLine(3); + tokenProto.SetColumn(0); + UNIT_ASSERT_VALUES_EQUAL(std::string::npos, NSQLTranslationV1::GetQueryPosition(query, tokenProto, antlr4)); - tokenProto.SetLine(2); - tokenProto.SetColumn(4); - UNIT_ASSERT_VALUES_EQUAL(std::string::npos, NSQLTranslationV1::GetQueryPosition(query, tokenProto, antlr4)); + tokenProto.SetLine(2); + tokenProto.SetColumn(4); + UNIT_ASSERT_VALUES_EQUAL(std::string::npos, NSQLTranslationV1::GetQueryPosition(query, tokenProto, antlr4)); - tokenProto.SetLine(1); - tokenProto.SetColumn(34); - UNIT_ASSERT_VALUES_EQUAL(std::string::npos, NSQLTranslationV1::GetQueryPosition(query, tokenProto, antlr4)); + tokenProto.SetLine(1); + tokenProto.SetColumn(34); + UNIT_ASSERT_VALUES_EQUAL(std::string::npos, NSQLTranslationV1::GetQueryPosition(query, tokenProto, antlr4)); - tokenProto.SetLine(1); - tokenProto.SetColumn(0); - UNIT_ASSERT_VALUES_EQUAL(0, NSQLTranslationV1::GetQueryPosition(query, tokenProto, antlr4)); - } + tokenProto.SetLine(1); + tokenProto.SetColumn(0); + UNIT_ASSERT_VALUES_EQUAL(0, NSQLTranslationV1::GetQueryPosition(query, tokenProto, antlr4)); } +} // Y_UNIT_TEST_SUITE(TestGetQueryPosition) Y_UNIT_TEST_SUITE(InlineUncorrelatedSubquery) { - Y_UNIT_TEST(EmptyTuple) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(EmptyTuple) { + NYql::TAstParseResult res = SqlToYql(R"sql( SELECT (); SELECT (()); SELECT (,); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(ParenthesisedExpression) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(ParenthesisedExpression) { + NYql::TAstParseResult res = SqlToYql(R"sql( SELECT 1; SELECT (1); SELECT ((1)); SELECT (((1))); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(Tuple) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(Tuple) { + NYql::TAstParseResult res = SqlToYql(R"sql( SELECT (1,); SELECT (1, 2); SELECT (1, 2, 3); SELECT (1, 2, 3, 4); SELECT ((1, 2)); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(Struct) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(Struct) { + NYql::TAstParseResult res = SqlToYql(R"sql( SELECT (1 AS a); SELECT (1 AS a, 2 AS b); SELECT (1 AS a, 2 AS b, 3 AS c); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(Lambda) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(Lambda) { + NYql::TAstParseResult res = SqlToYql(R"sql( SELECT (($a) -> { RETURN $a; })(1); SELECT (($a, $b) -> { RETURN $a + $b; })(1, 2); SELECT (($a, $b, $c) -> { RETURN $a + $b + $c; })(1, 2, 3); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(AtProjection) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2025, 4); +Y_UNIT_TEST(AtProjection) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = NYql::MakeLangVersion(2025, 4); - NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( + NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( SELECT (SELECT 1); SELECT (SELECT (SELECT 1)); )sql", settings); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(AtExpression) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2025, 4); +Y_UNIT_TEST(AtExpression) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = NYql::MakeLangVersion(2025, 4); - NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( + NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( SELECT 1 + (SELECT 1); SELECT (SELECT 1) + 1; )sql", settings); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(UnionParenthesis) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2025, 4); +Y_UNIT_TEST(UnionParenthesis) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = NYql::MakeLangVersion(2025, 4); - NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( + NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( SELECT ( SELECT 1 UNION SELECT 1); SELECT ( SELECT 1 UNION (SELECT 1)); SELECT ((SELECT 1) UNION SELECT 1); SELECT ((SELECT 1) UNION (SELECT 1)); )sql", settings); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(IntersectParenthesis) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2025, 4); +Y_UNIT_TEST(IntersectParenthesis) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = NYql::MakeLangVersion(2025, 4); - NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( + NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( SELECT ( SELECT 1 INTERSECT SELECT 1); SELECT ( SELECT 1 INTERSECT (SELECT 1)); SELECT ((SELECT 1) INTERSECT SELECT 1); SELECT ((SELECT 1) INTERSECT (SELECT 1)); )sql", settings); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(UnionIntersect) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2025, 4); +Y_UNIT_TEST(UnionIntersect) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = NYql::MakeLangVersion(2025, 4); - NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( + NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( SELECT (SELECT 1 UNION SELECT 1 UNION SELECT 1); SELECT (SELECT 1 UNION SELECT 1 INTERSECT SELECT 1); SELECT (SELECT 1 INTERSECT SELECT 1 UNION SELECT 1); SELECT (SELECT 1 INTERSECT SELECT 1 INTERSECT SELECT 1); )sql", settings); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(ScalarExpressionUnion) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2025, 4); +Y_UNIT_TEST(ScalarExpressionUnion) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = NYql::MakeLangVersion(2025, 4); - NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( + NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( SELECT ((2 + 2) UNION (2 * 2)); )sql", settings); - UNIT_ASSERT(!res.IsOk()); - UNIT_ASSERT_STRING_CONTAINS( - res.Issues.ToOneLineString(), - "2:24: Error: Expected SELECT/PROCESS/REDUCE statement"); - } + UNIT_ASSERT(!res.IsOk()); + UNIT_ASSERT_STRING_CONTAINS( + res.Issues.ToOneLineString(), + "2:24: Error: Expected SELECT/PROCESS/REDUCE statement"); +} - Y_UNIT_TEST(OrderByIgnorance1) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2025, 4); +Y_UNIT_TEST(OrderByIgnorance1) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = NYql::MakeLangVersion(2025, 4); - NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( + NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( SELECT (SELECT * FROM (SELECT * FROM (SELECT 1 AS x UNION SELECT 2 AS x) ORDER BY x)); )sql", settings); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - UNIT_ASSERT_STRING_CONTAINS( - res.Issues.ToOneLineString(), - "ORDER BY without LIMIT in subquery will be ignored"); - - TWordCountHive stat = {{TString("Sort"), 0}}; - VerifyProgram(res, stat); - UNIT_ASSERT_VALUES_EQUAL(stat["Sort"], 0); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); + UNIT_ASSERT_STRING_CONTAINS( + res.Issues.ToOneLineString(), + "ORDER BY without LIMIT in subquery will be ignored"); + + TWordCountHive stat = {{TString("Sort"), 0}}; + VerifyProgram(res, stat); + UNIT_ASSERT_VALUES_EQUAL(stat["Sort"], 0); +} - Y_UNIT_TEST(OrderByIgnorance2) { - NSQLTranslation::TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2025, 4); +Y_UNIT_TEST(OrderByIgnorance2) { + NSQLTranslation::TTranslationSettings settings; + settings.LangVer = NYql::MakeLangVersion(2025, 4); - NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( + NYql::TAstParseResult res = SqlToYqlWithSettings(R"sql( SELECT (SELECT * FROM (SELECT 1 AS x UNION SELECT 2 AS x) ORDER BY x); )sql", settings); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - UNIT_ASSERT_STRING_CONTAINS( - res.Issues.ToOneLineString(), - "ORDER BY without LIMIT in subquery will be ignored"); - - TWordCountHive stat = {{TString("Sort"), 0}}; - VerifyProgram(res, stat); - UNIT_ASSERT_VALUES_EQUAL(stat["Sort"], 0); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); + UNIT_ASSERT_STRING_CONTAINS( + res.Issues.ToOneLineString(), + "ORDER BY without LIMIT in subquery will be ignored"); + + TWordCountHive stat = {{TString("Sort"), 0}}; + VerifyProgram(res, stat); + UNIT_ASSERT_VALUES_EQUAL(stat["Sort"], 0); +} - Y_UNIT_TEST(InSubquery) { - NYql::TAstParseResult res; +Y_UNIT_TEST(InSubquery) { + NYql::TAstParseResult res; - res = SqlToYql(R"sql( + res = SqlToYql(R"sql( SELECT 1 IN (SELECT 1); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - res = SqlToYql(R"sql( + res = SqlToYql(R"sql( SELECT * FROM (SELECT 1 AS x) WHERE x IN (SELECT 1); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - res = SqlToYql(R"sql( + res = SqlToYql(R"sql( SELECT * FROM (SELECT 1 AS x) WHERE x IN ((SELECT 1)); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(GroupByUnit) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(GroupByUnit) { + NYql::TAstParseResult res = SqlToYql(R"sql( SELECT * FROM (SELECT 1) GROUP BY (); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(NamedNodeUnion) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(NamedNodeUnion) { + NYql::TAstParseResult res = SqlToYql(R"sql( $a = (SELECT 1); $b = (SELECT 1); $x = ($a UNION $b); SELECT * FROM $x; )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(NamedNodeExpr) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(NamedNodeExpr) { + NYql::TAstParseResult res = SqlToYql(R"sql( $a = 1; SELECT $a; $b = SELECT 1; SELECT $b; $c = (SELECT 1); SELECT $c; @@ -10747,34 +10664,34 @@ Y_UNIT_TEST_SUITE(InlineUncorrelatedSubquery) { SELECT $b + 1; SELECT ($b); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); +} - Y_UNIT_TEST(NamedNodeProcess) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(NamedNodeProcess) { + NYql::TAstParseResult res = SqlToYql(R"sql( $a = SELECT 1, 2; $a = PROCESS $a; SELECT $a; )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToString()); +} - Y_UNIT_TEST(SubqueryDeduplication) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(SubqueryDeduplication) { + NYql::TAstParseResult res = SqlToYql(R"sql( DEFINE SUBQUERY $sub() AS SELECT * FROM (SELECT 1); END DEFINE; SELECT * FROM $sub(); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); +} - Y_UNIT_TEST(NamedNode) { - NYql::TAstParseResult res = SqlToYql(R"sql( +Y_UNIT_TEST(NamedNode) { + NYql::TAstParseResult res = SqlToYql(R"sql( $x = (SELECT 1 AS x); SELECT 1 < $x; SELECT 1 < ($x); )sql"); - UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); - } + UNIT_ASSERT_C(res.IsOk(), res.Issues.ToOneLineString()); } +} // Y_UNIT_TEST_SUITE(InlineUncorrelatedSubquery) diff --git a/yql/essentials/sql/v1/sql_values.cpp b/yql/essentials/sql/v1/sql_values.cpp index 83608995c50..db4baacab29 100644 --- a/yql/essentials/sql/v1/sql_values.cpp +++ b/yql/essentials/sql/v1/sql_values.cpp @@ -29,9 +29,9 @@ TSourcePtr TSqlValues::Build(const TRule_values_stmt& node, TPosition& valuesPos auto columns = derivedColumns; if (Ctx_.WarnUnnamedColumns && columns.size() < columnsCount) { if (!Ctx_.Warning(valuesPos, TIssuesIds::YQL_UNNAMED_COLUMN, [&](auto& out) { - out << "Autogenerated column names column" << columns.size() - << "...column" << columnsCount - 1 << " will be used here"; - })) { + out << "Autogenerated column names column" << columns.size() + << "...column" << columnsCount - 1 << " will be used here"; + })) { return nullptr; } } @@ -52,16 +52,15 @@ TSourcePtr TSqlValues::Build(const TRule_values_stmt& node, TPosition& valuesPos items.push_back(BuildOrderedStructure(row.front()->GetPos(), row, labels)); } auto list = new TCallNodeImpl(valuesPos, "AsListMayWarn", items); - list = new TCallNodeImpl(valuesPos, "PersistableRepr", { list }); - list = new TCallNodeImpl(valuesPos, "AssumeColumnOrder", { list, BuildTuple(valuesPos, labels) }); + list = new TCallNodeImpl(valuesPos, "PersistableRepr", {list}); + list = new TCallNodeImpl(valuesPos, "AssumeColumnOrder", {list, BuildTuple(valuesPos, labels)}); auto result = BuildNodeSource(valuesPos, list, false); result->AllColumns(); return result; } bool TSqlValues::BuildRows(const TRule_values_source_row_list& node, TVector<TVector<TNodePtr>>& rows) { - rows = TVector<TVector<TNodePtr>> {{}}; - + rows = TVector<TVector<TNodePtr>>{{}}; if (!BuildRow(node.GetRule_values_source_row1(), rows.back())) { return false; @@ -69,7 +68,7 @@ bool TSqlValues::BuildRows(const TRule_values_source_row_list& node, TVector<TVe const size_t rowSize = rows.back().size(); - for (const auto& valuesSourceRow: node.GetBlock2()) { + for (const auto& valuesSourceRow : node.GetBlock2()) { rows.push_back({}); if (!BuildRow(valuesSourceRow.GetRule_values_source_row2(), rows.back())) { return false; @@ -89,13 +88,13 @@ bool TSqlValues::BuildRow(const TRule_values_source_row& inRow, TVector<TNodePtr } TSourcePtr TSqlValues::ValuesSource(const TRule_values_source& node, const TVector<TString>& columnsHint, - const TString& operationName) + const TString& operationName) { Ctx_.IncrementMonCounter("sql_features", "ValuesSource"); TPosition pos(Ctx_.Pos()); switch (node.Alt_case()) { case TRule_values_source::kAltValuesSource1: { - TVector<TVector<TNodePtr>> rows {{}}; + TVector<TVector<TNodePtr>> rows{{}}; const auto& rowList = node.GetAlt_values_source1().GetRule_values_stmt1().GetRule_values_source_row_list2(); if (!BuildRows(rowList, rows)) { return nullptr; diff --git a/yql/essentials/sql/v1/sql_values.h b/yql/essentials/sql/v1/sql_values.h index 7e19d1d8a0d..eaf5529cd63 100644 --- a/yql/essentials/sql/v1/sql_values.h +++ b/yql/essentials/sql/v1/sql_values.h @@ -15,11 +15,12 @@ public: } TSourcePtr Build(const TRule_values_stmt& node, TPosition& valuesPos, const TVector<TString>& derivedColumns = {}, TPosition derivedColumnsPos = TPosition()); + protected: bool BuildRows(const TRule_values_source_row_list& node, TVector<TVector<TNodePtr>>& rows); TSourcePtr ValuesSource(const TRule_values_source& node, const TVector<TString>& columnsHint, - const TString& operationName); + const TString& operationName); private: bool BuildRow(const TRule_values_source_row& inRow, TVector<TNodePtr>& outRow); diff --git a/yql/essentials/sql/v1/ya.make b/yql/essentials/sql/v1/ya.make index 0e89d150bf8..b3d0eac4c96 100644 --- a/yql/essentials/sql/v1/ya.make +++ b/yql/essentials/sql/v1/ya.make @@ -1,5 +1,7 @@ LIBRARY() +ENABLE(YQL_STYLE_CPP) + PEERDIR( library/cpp/charset/lite library/cpp/enumbitset |