diff options
author | avevad <avevad@yandex-team.com> | 2024-12-09 11:48:43 +0300 |
---|---|---|
committer | avevad <avevad@yandex-team.com> | 2024-12-09 12:07:33 +0300 |
commit | 365b065ca32ba05d72f86723169f846d0ee12189 (patch) | |
tree | 5e038eb3e468aa71927441b964e326a0cbbb2e1c | |
parent | bc7efd59c3940f609c01a8af3ea6c6d69cbc456c (diff) | |
download | ydb-365b065ca32ba05d72f86723169f846d0ee12189.tar.gz |
YQL-19123 More SQL features for Variant type
More SQL features for Variant type
commit_hash:51c15343e2d24190ec59085888dfa3fd008cafcc
9 files changed, 477 insertions, 12 deletions
diff --git a/yql/essentials/core/type_ann/type_ann_core.cpp b/yql/essentials/core/type_ann/type_ann_core.cpp index 2474f046ae..8dd928d4aa 100644 --- a/yql/essentials/core/type_ann/type_ann_core.cpp +++ b/yql/essentials/core/type_ann/type_ann_core.cpp @@ -946,6 +946,30 @@ namespace NTypeAnnImpl { return result; } + TMaybe<ui32> FindOrReportMissingMember(TStringBuf memberName, const TTupleExprType& tupleType, TString& errStr) { + ui32 index = 0; + if (!TryFromString(memberName, index)) { + errStr = TStringBuilder() << "Failed to convert to integer: " << memberName; + return Nothing(); + } + if (index >= tupleType.GetSize()) { + errStr = TStringBuilder() + << "Index out of range. Index: " + << index << ", size: " << tupleType.GetSize(); + return Nothing(); + } + return index; + } + + TMaybe<ui32> FindOrReportMissingMember(TStringBuf memberName, TPositionHandle pos, const TTupleExprType& tupleType, TExprContext& ctx) { + TString errStr; + auto result = FindOrReportMissingMember(memberName, tupleType, errStr); + if (!result) { + ctx.AddError(TIssue(ctx.GetPosition(pos), errStr)); + } + return result; + } + IGraphTransformer::TStatus MemberWrapper(const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) { if (!EnsureArgsCount(*input, 2, ctx.Expr)) { return IGraphTransformer::TStatus::Error; @@ -8534,6 +8558,50 @@ template <NKikimr::NUdf::EDataSlot DataSlot> return IGraphTransformer::TStatus::Ok; } + IGraphTransformer::TStatus SqlVariantItemWrapper(const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) { + if (!EnsureArgsCount(*input, 1, ctx.Expr)) { + return IGraphTransformer::TStatus::Error; + } + + if (IsNull(input->Head())) { + output = input->HeadPtr(); + return IGraphTransformer::TStatus::Repeat; + } + + if (input->Head().GetTypeAnn() && input->Head().GetTypeAnn()->GetKind() == ETypeAnnotationKind::Optional) { + auto optType = input->Head().GetTypeAnn()->Cast<TOptionalExprType>(); + if (!EnsureVariantType(input->Head().Pos(), *optType->GetItemType(), ctx.Expr)) { + return IGraphTransformer::TStatus::Error; + } + auto varType = optType->GetItemType()->Cast<TVariantExprType>(); + auto isOptionalItem = false; + if (varType->GetUnderlyingType()->GetKind() == ETypeAnnotationKind::Tuple) { + auto tupType = varType->GetUnderlyingType()->Cast<TTupleExprType>(); + if (tupType->GetSize() > 0 && tupType->GetItems()[0]->GetKind() == ETypeAnnotationKind::Optional) { + isOptionalItem = true; + } + } else { + auto strType = varType->GetUnderlyingType()->Cast<TStructExprType>(); + if (strType->GetSize() > 0 && strType->GetItems()[0]->GetItemType()->GetKind() == ETypeAnnotationKind::Optional) { + isOptionalItem = true; + } + } + output = ctx.Expr.Builder(input->Pos()) + .Callable(isOptionalItem ? "FlatMap" : "Map") + .Add(0, input->HeadPtr()) + .Lambda(1) + .Param("var") + .Callable("VariantItem") + .Arg(0, "var") + .Seal() + .Seal() + .Seal().Build(); + } else { + output = ctx.Expr.RenameNode(*input, "VariantItem"); + } + return IGraphTransformer::TStatus::Repeat; + } + IGraphTransformer::TStatus VariantItemWrapper(const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) { Y_UNUSED(output); if (!EnsureArgsCount(*input, 1, ctx.Expr)) { @@ -8591,6 +8659,112 @@ template <NKikimr::NUdf::EDataSlot DataSlot> return IGraphTransformer::TStatus::Ok; } + IGraphTransformer::TStatus SqlVisitWrapper(const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) { + if (!EnsureMinArgsCount(*input, 2, ctx.Expr)) { + return IGraphTransformer::TStatus::Error; + } + + if (IsNull(input->Head())) { + output = input->HeadPtr(); + return IGraphTransformer::TStatus::Repeat; + } + + if (input->Head().GetTypeAnn() && input->Head().GetTypeAnn()->GetKind() == ETypeAnnotationKind::Optional) { + auto appendOtherArgs = [&] (auto &builder) -> auto { + for (size_t pos = 1; pos < input->ChildrenSize(); pos++) { + builder.Add(pos, input->ChildPtr(pos)); + } + return builder; + }; + + auto optType = input->Head().GetTypeAnn()->Cast<TOptionalExprType>(); + if (!EnsureVariantType(input->Pos(), *optType->GetItemType(), ctx.Expr)) { + return IGraphTransformer::TStatus::Error; + } + auto varType = optType->GetItemType()->Cast<TVariantExprType>(); + const TTupleExprType* tupType = nullptr; + const TStructExprType* strType = nullptr; + if (varType->GetUnderlyingType()->GetKind() == ETypeAnnotationKind::Tuple) { + tupType = varType->GetUnderlyingType()->Cast<TTupleExprType>(); + } else { + strType = varType->GetUnderlyingType()->Cast<TStructExprType>(); + } + + bool isOptionalResult = false; + bool repeat = false; + for (size_t idx = 1; idx < input->ChildrenSize(); idx++) { + auto child = input->ChildPtr(idx); + if (child->IsAtom()) { + const TTypeAnnotationNode* itemType; + if (tupType) { + auto pos = FindOrReportMissingMember(child->Content(), child->Pos(), *tupType, ctx.Expr); + if (!pos) { + return IGraphTransformer::TStatus::Error; + } + itemType = tupType->GetItems()[*pos]; + } else { + auto pos = FindOrReportMissingMember(child->Content(), child->Pos(), *strType, ctx.Expr); + if (!pos) { + return IGraphTransformer::TStatus::Error; + } + itemType = strType->GetItems()[*pos]->GetItemType(); + } + + idx++; + if (idx == input->ChildrenSize()) { + ctx.Expr.AddError(TIssue(ctx.Expr.GetPosition(child->Pos()), "Expected lambda after this argument")); + return IGraphTransformer::TStatus::Error; + } + + auto status = ConvertToLambda(input->ChildRef(idx), ctx.Expr, 1); + if (status.Level != IGraphTransformer::TStatus::Ok) { + return status; + } + + auto& lambda = input->ChildRef(idx); + if (!UpdateLambdaAllArgumentsTypes(lambda, {itemType}, ctx.Expr)) { + return IGraphTransformer::TStatus::Error; + } + + if (!lambda->GetTypeAnn()) { + repeat = true; + continue; + } + + if (lambda->GetTypeAnn()->GetKind() == ETypeAnnotationKind::Optional) { + isOptionalResult = true; + } + } else { + if (!EnsureComputable(*child, ctx.Expr)) { + return IGraphTransformer::TStatus::Error; + } + if (child->GetTypeAnn()->GetKind() == ETypeAnnotationKind::Optional) { + isOptionalResult = true; + } + } + } + + if (repeat) { + return IGraphTransformer::TStatus::Repeat; + } + + output = appendOtherArgs(ctx.Expr.Builder(input->Pos()) + .Callable(isOptionalResult ? "FlatMap" : "Map") + .Add(0, input->HeadPtr()) + .Lambda(1) + .Param("var") + .Callable("Visit") + .Arg(0, "var")) + .Seal() + .Seal() + .Seal().Build(); + } else { + output = ctx.Expr.RenameNode(*input, "Visit"); + } + + return IGraphTransformer::TStatus::Repeat; + } + IGraphTransformer::TStatus VisitWrapper(const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) { Y_UNUSED(output); if (!EnsureMinArgsCount(*input, 2, ctx.Expr)) { @@ -8625,21 +8799,13 @@ template <NKikimr::NUdf::EDataSlot DataSlot> const TTypeAnnotationNode* itemType; ui32 itemIndex; if (tupleType) { - ui32 index = 0; - if (!TryFromString(child->Content(), index)) { - ctx.Expr.AddError(TIssue(ctx.Expr.GetPosition(child->Pos()), TStringBuilder() << "Failed to convert to integer: " << child->Content())); - return IGraphTransformer::TStatus::Error; - } - - if (index >= tupleType->GetSize()) { - ctx.Expr.AddError(TIssue(ctx.Expr.GetPosition(child->Pos()), TStringBuilder() - << "Index out of range. Index: " - << index << ", size: " << tupleType->GetSize())); + auto pos = FindOrReportMissingMember(child->Content(), child->Pos(), *tupleType, ctx.Expr); + if (!pos) { return IGraphTransformer::TStatus::Error; } - itemType = tupleType->GetItems()[index]; - itemIndex = index; + itemType = tupleType->GetItems()[*pos]; + itemIndex = *pos; } else { auto pos = FindOrReportMissingMember(child->Content(), child->Pos(), *structType, ctx.Expr); if (!pos) { @@ -8763,6 +8929,10 @@ template <NKikimr::NUdf::EDataSlot DataSlot> variantType = itemType->Cast<TVariantExprType>(); } + else if (IsNull(input->Head())) { + output = input->HeadPtr(); + return IGraphTransformer::TStatus::Repeat; + } else { if (!EnsureVariantType(input->Head(), ctx.Expr)) { return IGraphTransformer::TStatus::Error; @@ -12421,7 +12591,9 @@ template <NKikimr::NUdf::EDataSlot DataSlot> Functions["FlattenMembersType"] = &TypeArgWrapper<ETypeArgument::FlattenMembers>; Functions["VariantUnderlyingType"] = &TypeArgWrapper<ETypeArgument::VariantUnderlying>; Functions["Guess"] = &GuessWrapper; + Functions["SqlVariantItem"] = &SqlVariantItemWrapper; Functions["VariantItem"] = &VariantItemWrapper; + Functions["SqlVisit"] = &SqlVisitWrapper; Functions["Visit"] = &VisitWrapper; Functions["Way"] = &WayWrapper; Functions["SqlAccess"] = &SqlAccessWrapper; diff --git a/yql/essentials/sql/v1/builtin.cpp b/yql/essentials/sql/v1/builtin.cpp index 5d33b2061f..a4bec63066 100644 --- a/yql/essentials/sql/v1/builtin.cpp +++ b/yql/essentials/sql/v1/builtin.cpp @@ -3010,6 +3010,7 @@ struct TBuiltinFuncData { {"callableresulttype", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("CallableResultType", 1, 1) }, {"callableargumenttype", BuildSimpleBuiltinFactoryCallback<TYqlCallableArgumentType>() }, {"variantunderlyingtype", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("VariantUnderlyingType", 1, 1) }, + {"variantitem", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("SqlVariantItem", 1, 1) }, {"fromysonsimpletype", BuildNamedArgcBuiltinFactoryCallback<TCallNodeImpl>("FromYsonSimpleType", 2, 2) }, {"currentutcdate", BuildNamedDepsArgcBuiltinFactoryCallback<TCallNodeDepArgs>(0, "CurrentUtcDate", 0, -1) }, {"currentutcdatetime", BuildNamedDepsArgcBuiltinFactoryCallback<TCallNodeDepArgs>(0, "CurrentUtcDatetime", 0, -1) }, @@ -3705,6 +3706,54 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec BuildTuple(pos, {BuildQuotedAtom(pos, ""), args[1]}), }; return new TCallNodeImpl(pos, "FlattenMembers", 2, 2, flattenMembersArgs); + } else if (normalizedName == "visit" || normalizedName == "visitordefault") { + bool withDefault = normalizedName == "visitordefault"; + TNodePtr variant; + TVector<TNodePtr> labels, handlers; + TMaybe<TNodePtr> dflt; + if (mustUseNamed && *mustUseNamed) { + *mustUseNamed = false; + 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"); + } + auto &named = *args[1]->GetStructNode(); + variant = positional.GetTupleElement(0); + auto &namedExprs = named.GetExprs(); + labels.reserve(namedExprs.size()); + handlers.reserve(namedExprs.size()); + for (size_t idx = 0; idx < namedExprs.size(); idx++) { + labels.push_back(BuildQuotedAtom(pos, namedExprs[idx]->GetLabel())); + handlers.push_back(namedExprs[idx]); + } + if (withDefault) { + dflt = positional.GetTupleElement(positional.GetTupleSize() - 1); + } + } else { + variant = args[0]; + size_t defaultSuffix = withDefault ? 1 : 0; + labels.reserve(args.size() - 1 - defaultSuffix); + handlers.reserve(args.size() - 1 - defaultSuffix); + for (size_t idx = 0; idx + 1 < args.size() - defaultSuffix; idx++) { + labels.push_back(BuildQuotedAtom(pos, ToString(idx))); + handlers.push_back(args[idx + 1]); + } + if (withDefault) { + dflt = args.back(); + } + } + TVector<TNodePtr> resultArgs; + resultArgs.reserve(1 + labels.size() + handlers.size()); + resultArgs.emplace_back(std::move(variant)); + for (size_t idx = 0; idx < labels.size(); idx++) { + resultArgs.emplace_back(std::move(labels[idx])); + resultArgs.emplace_back(std::move(handlers[idx])); + } + if (dflt.Defined()) { + resultArgs.emplace_back(std::move(dflt->Get())); + } + return new TCallNodeImpl(pos, "SqlVisit", 1, -1, resultArgs); } else if (normalizedName == "sqlexternalfunction") { return new TCallNodeImpl(pos, "SqlExternalFunction", args); } else { diff --git a/yql/essentials/tests/sql/sql2yql/canondata/result.json b/yql/essentials/tests/sql/sql2yql/canondata/result.json index 553fd35c78..ee6df683bf 100644 --- a/yql/essentials/tests/sql/sql2yql/canondata/result.json +++ b/yql/essentials/tests/sql/sql2yql/canondata/result.json @@ -6908,6 +6908,13 @@ "uri": "https://{canondata_backend}/1937429/434276f26b2857be3c5ad3fdbbf877d2bf775ac5/resource.tar.gz#test_sql2yql.test_expr-uuid_order_/sql.yql" } ], + "test_sql2yql.test[expr-variant_builtins_opt]": [ + { + "checksum": "00f7f7ba82bd2474f7b1bfd7771323f9", + "size": 3847, + "uri": "https://{canondata_backend}/1936842/4ad1682e9f564ef555f5e0180b972a1adad2fc43/resource.tar.gz#test_sql2yql.test_expr-variant_builtins_opt_/sql.yql" + } + ], "test_sql2yql.test[expr-variant_list_sort]": [ { "checksum": "abd93bfb65a1cb17235be843d4cbd2c3", @@ -6915,6 +6922,13 @@ "uri": "https://{canondata_backend}/1936273/4a1b39013e1bae40e722cff8ccef8829784964e2/resource.tar.gz#test_sql2yql.test_expr-variant_list_sort_/sql.yql" } ], + "test_sql2yql.test[expr-variant_struct_builtins]": [ + { + "checksum": "cb90540556b74bdbb9a95959c62a3cbf", + "size": 5780, + "uri": "https://{canondata_backend}/1936842/4ad1682e9f564ef555f5e0180b972a1adad2fc43/resource.tar.gz#test_sql2yql.test_expr-variant_struct_builtins_/sql.yql" + } + ], "test_sql2yql.test[expr-variant_struct_comp]": [ { "checksum": "3f85119441280a8729ef912910ac7745", @@ -6922,6 +6936,13 @@ "uri": "https://{canondata_backend}/1936273/4a1b39013e1bae40e722cff8ccef8829784964e2/resource.tar.gz#test_sql2yql.test_expr-variant_struct_comp_/sql.yql" } ], + "test_sql2yql.test[expr-variant_tuple_builtins]": [ + { + "checksum": "41d01afdf58dcca513a44186a279efcb", + "size": 5682, + "uri": "https://{canondata_backend}/1936842/4ad1682e9f564ef555f5e0180b972a1adad2fc43/resource.tar.gz#test_sql2yql.test_expr-variant_tuple_builtins_/sql.yql" + } + ], "test_sql2yql.test[expr-variant_tuple_comp]": [ { "checksum": "62f3d0d5c99c037db94a4f8f3c3c9d1d", @@ -24821,16 +24842,31 @@ "uri": "file://test_sql_format.test_expr-uuid_order_/formatted.sql" } ], + "test_sql_format.test[expr-variant_builtins_opt]": [ + { + "uri": "file://test_sql_format.test_expr-variant_builtins_opt_/formatted.sql" + } + ], "test_sql_format.test[expr-variant_list_sort]": [ { "uri": "file://test_sql_format.test_expr-variant_list_sort_/formatted.sql" } ], + "test_sql_format.test[expr-variant_struct_builtins]": [ + { + "uri": "file://test_sql_format.test_expr-variant_struct_builtins_/formatted.sql" + } + ], "test_sql_format.test[expr-variant_struct_comp]": [ { "uri": "file://test_sql_format.test_expr-variant_struct_comp_/formatted.sql" } ], + "test_sql_format.test[expr-variant_tuple_builtins]": [ + { + "uri": "file://test_sql_format.test_expr-variant_tuple_builtins_/formatted.sql" + } + ], "test_sql_format.test[expr-variant_tuple_comp]": [ { "uri": "file://test_sql_format.test_expr-variant_tuple_comp_/formatted.sql" diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-variant_builtins_opt_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-variant_builtins_opt_/formatted.sql new file mode 100644 index 0000000000..3023dcf5c2 --- /dev/null +++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-variant_builtins_opt_/formatted.sql @@ -0,0 +1,30 @@ +$vartype = Variant<a: Optional<String>, b: Optional<String>>; + +$handle_a = ($x) -> { + RETURN CAST(($x || "1") AS Uint32); +}; + +$handle_b = ($x) -> { + RETURN CAST(($x || "2") AS Uint32); +}; + +$var_a = VARIANT ("5", "a", $vartype); +$var_b = VARIANT ("6", "b", $vartype); + +SELECT + Visit(Just($var_a), $handle_a AS a, $handle_b AS b), + Visit(Just($var_b), $handle_a AS a, $handle_b AS b), + VisitOrDefault(Just($var_b), Just(777u), $handle_a AS a), + VariantItem(Just($var_b)) +; + +$vartype_t = Variant<Optional<String>, Optional<String>>; +$var_1 = VARIANT ("7", "0", $vartype_t); +$var_2 = VARIANT ("8", "1", $vartype_t); + +SELECT + Visit(Just($var_1), $handle_a, $handle_b), + Visit(Just($var_2), $handle_a, $handle_b), + VisitOrDefault(Just($var_2), $handle_a, Just(777u)), + VariantItem(Just($var_b)) +; diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-variant_struct_builtins_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-variant_struct_builtins_/formatted.sql new file mode 100644 index 0000000000..1192a90d9b --- /dev/null +++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-variant_struct_builtins_/formatted.sql @@ -0,0 +1,46 @@ +$vartype = Variant<num: Int32, flag: Bool, str: String>; + +$handle_num = ($x) -> { + RETURN 2 * $x; +}; + +$handle_flag = ($x) -> { + RETURN If($x, 200, 10); +}; + +$handle_str = ($x) -> { + RETURN Unwrap(CAST(LENGTH($x) AS Int32)); +}; + +$visitor = ($var) -> { + RETURN Visit($var, $handle_num AS num, $handle_flag AS flag, $handle_str AS str); +}; + +SELECT + $visitor(VARIANT (5, "num", $vartype)), + $visitor(Just(VARIANT (TRUE, "flag", $vartype))), + $visitor(Just(VARIANT ("somestr", "str", $vartype))), + $visitor(Nothing(OptionalType($vartype))), + $visitor(NULL) +; + +$visitor_def = ($var) -> { + RETURN VisitOrDefault($var, 999, $handle_num AS num, $handle_flag AS flag); +}; + +SELECT + $visitor_def(VARIANT (5, "num", $vartype)), + $visitor_def(Just(VARIANT (TRUE, "flag", $vartype))), + $visitor_def(Just(VARIANT ("somestr", "str", $vartype))), + $visitor_def(Nothing(OptionalType($vartype))), + $visitor_def(NULL) +; + +$vartype1 = Variant<num1: Int32, num2: Int32, num3: Int32>; + +SELECT + VariantItem(VARIANT (7, "num2", $vartype1)), + VariantItem(Just(VARIANT (5, "num1", $vartype1))), + VariantItem(Nothing(OptionalType($vartype1))), + VariantItem(NULL) +; diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-variant_tuple_builtins_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-variant_tuple_builtins_/formatted.sql new file mode 100644 index 0000000000..b1e21cda10 --- /dev/null +++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-variant_tuple_builtins_/formatted.sql @@ -0,0 +1,46 @@ +$vartype = Variant<Int32, Bool, String>; + +$handle_num = ($x) -> { + RETURN 2 * $x; +}; + +$handle_flag = ($x) -> { + RETURN If($x, 200, 10); +}; + +$handle_str = ($x) -> { + RETURN Unwrap(CAST(LENGTH($x) AS Int32)); +}; + +$visitor = ($var) -> { + RETURN Visit($var, $handle_num, $handle_flag, $handle_str); +}; + +SELECT + $visitor(VARIANT (5, "0", $vartype)), + $visitor(Just(VARIANT (TRUE, "1", $vartype))), + $visitor(Just(VARIANT ("somestr", "2", $vartype))), + $visitor(Nothing(OptionalType($vartype))), + $visitor(NULL) +; + +$visitor_def = ($var) -> { + RETURN VisitOrDefault($var, $handle_num, $handle_flag, 999); +}; + +SELECT + $visitor_def(VARIANT (5, "0", $vartype)), + $visitor_def(Just(VARIANT (TRUE, "1", $vartype))), + $visitor_def(Just(VARIANT ("somestr", "2", $vartype))), + $visitor_def(Nothing(OptionalType($vartype))), + $visitor_def(NULL) +; + +$vartype1 = Variant<Int32, Int32, Int32>; + +SELECT + VariantItem(VARIANT (7, "1", $vartype1)), + VariantItem(Just(VARIANT (5, "0", $vartype1))), + VariantItem(Nothing(OptionalType($vartype1))), + VariantItem(NULL) +; diff --git a/yql/essentials/tests/sql/suites/expr/variant_builtins_opt.sql b/yql/essentials/tests/sql/suites/expr/variant_builtins_opt.sql new file mode 100644 index 0000000000..443802fe56 --- /dev/null +++ b/yql/essentials/tests/sql/suites/expr/variant_builtins_opt.sql @@ -0,0 +1,26 @@ +$vartype = Variant<a: Optional<String>, b: Optional<String>>; + +$handle_a = ($x) -> { return CAST(($x || "1") AS Uint32); }; +$handle_b = ($x) -> { return CAST(($x || "2") AS Uint32); }; + +$var_a = Variant("5", "a", $vartype); +$var_b = Variant("6", "b", $vartype); + +SELECT + Visit(Just($var_a), $handle_a AS a, $handle_b AS b), + Visit(Just($var_b), $handle_a AS a, $handle_b AS b), + VisitOrDefault(Just($var_b), Just(777u), $handle_a AS a), + VariantItem(Just($var_b)) +; + +$vartype_t = Variant<Optional<String>, Optional<String>>; + +$var_1 = Variant("7", "0", $vartype_t); +$var_2 = Variant("8", "1", $vartype_t); + +SELECT + Visit(Just($var_1), $handle_a, $handle_b), + Visit(Just($var_2), $handle_a, $handle_b), + VisitOrDefault(Just($var_2), $handle_a, Just(777u)), + VariantItem(Just($var_b)) +; diff --git a/yql/essentials/tests/sql/suites/expr/variant_struct_builtins.sql b/yql/essentials/tests/sql/suites/expr/variant_struct_builtins.sql new file mode 100644 index 0000000000..71a09810da --- /dev/null +++ b/yql/essentials/tests/sql/suites/expr/variant_struct_builtins.sql @@ -0,0 +1,30 @@ +$vartype = Variant<num: Int32, flag: Bool, str: String>; +$handle_num = ($x) -> { return 2 * $x; }; +$handle_flag = ($x) -> { return If($x, 200, 10); }; +$handle_str = ($x) -> { return Unwrap(CAST(LENGTH($x) AS Int32)); }; + +$visitor = ($var) -> { return Visit($var, $handle_num AS num, $handle_flag AS flag, $handle_str AS str); }; +SELECT + $visitor(Variant(5, "num", $vartype)), + $visitor(Just(Variant(True, "flag", $vartype))), + $visitor(Just(Variant("somestr", "str", $vartype))), + $visitor(Nothing(OptionalType($vartype))), + $visitor(NULL) +; + +$visitor_def = ($var) -> { return VisitOrDefault($var, 999, $handle_num AS num, $handle_flag AS flag); }; +SELECT + $visitor_def(Variant(5, "num", $vartype)), + $visitor_def(Just(Variant(True, "flag", $vartype))), + $visitor_def(Just(Variant("somestr", "str", $vartype))), + $visitor_def(Nothing(OptionalType($vartype))), + $visitor_def(NULL) +; + +$vartype1 = Variant<num1: Int32, num2: Int32, num3: Int32>; +SELECT + VariantItem(Variant(7, "num2", $vartype1)), + VariantItem(Just(Variant(5, "num1", $vartype1))), + VariantItem(Nothing(OptionalType($vartype1))), + VariantItem(NULL) +;
\ No newline at end of file diff --git a/yql/essentials/tests/sql/suites/expr/variant_tuple_builtins.sql b/yql/essentials/tests/sql/suites/expr/variant_tuple_builtins.sql new file mode 100644 index 0000000000..35d1775708 --- /dev/null +++ b/yql/essentials/tests/sql/suites/expr/variant_tuple_builtins.sql @@ -0,0 +1,30 @@ +$vartype = Variant<Int32, Bool, String>; +$handle_num = ($x) -> { return 2 * $x; }; +$handle_flag = ($x) -> { return If($x, 200, 10); }; +$handle_str = ($x) -> { return Unwrap(CAST(LENGTH($x) AS Int32)); }; + +$visitor = ($var) -> { return Visit($var, $handle_num, $handle_flag, $handle_str); }; +SELECT + $visitor(Variant(5, "0", $vartype)), + $visitor(Just(Variant(True, "1", $vartype))), + $visitor(Just(Variant("somestr", "2", $vartype))), + $visitor(Nothing(OptionalType($vartype))), + $visitor(NULL) +; + +$visitor_def = ($var) -> { return VisitOrDefault($var, $handle_num, $handle_flag, 999); }; +SELECT + $visitor_def(Variant(5, "0", $vartype)), + $visitor_def(Just(Variant(True, "1", $vartype))), + $visitor_def(Just(Variant("somestr", "2", $vartype))), + $visitor_def(Nothing(OptionalType($vartype))), + $visitor_def(NULL) +; + +$vartype1 = Variant<Int32, Int32, Int32>; +SELECT + VariantItem(Variant(7, "1", $vartype1)), + VariantItem(Just(Variant(5, "0", $vartype1))), + VariantItem(Nothing(OptionalType($vartype1))), + VariantItem(NULL) +;
\ No newline at end of file |