@@ -946,6 +946,30 @@ namespace NTypeAnnImpl {
946
946
return result;
947
947
}
948
948
949
+ TMaybe<ui32> FindOrReportMissingMember(TStringBuf memberName, const TTupleExprType& tupleType, TString& errStr) {
950
+ ui32 index = 0;
951
+ if (!TryFromString(memberName, index)) {
952
+ errStr = TStringBuilder() << "Failed to convert to integer: " << memberName;
953
+ return Nothing();
954
+ }
955
+ if (index >= tupleType.GetSize()) {
956
+ errStr = TStringBuilder()
957
+ << "Index out of range. Index: "
958
+ << index << ", size: " << tupleType.GetSize();
959
+ return Nothing();
960
+ }
961
+ return index;
962
+ }
963
+
964
+ TMaybe<ui32> FindOrReportMissingMember(TStringBuf memberName, TPositionHandle pos, const TTupleExprType& tupleType, TExprContext& ctx) {
965
+ TString errStr;
966
+ auto result = FindOrReportMissingMember(memberName, tupleType, errStr);
967
+ if (!result) {
968
+ ctx.AddError(TIssue(ctx.GetPosition(pos), errStr));
969
+ }
970
+ return result;
971
+ }
972
+
949
973
IGraphTransformer::TStatus MemberWrapper(const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) {
950
974
if (!EnsureArgsCount(*input, 2, ctx.Expr)) {
951
975
return IGraphTransformer::TStatus::Error;
@@ -8534,6 +8558,50 @@ template <NKikimr::NUdf::EDataSlot DataSlot>
8534
8558
return IGraphTransformer::TStatus::Ok;
8535
8559
}
8536
8560
8561
+ IGraphTransformer::TStatus SqlVariantItemWrapper(const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) {
8562
+ if (!EnsureArgsCount(*input, 1, ctx.Expr)) {
8563
+ return IGraphTransformer::TStatus::Error;
8564
+ }
8565
+
8566
+ if (IsNull(input->Head())) {
8567
+ output = input->HeadPtr();
8568
+ return IGraphTransformer::TStatus::Repeat;
8569
+ }
8570
+
8571
+ if (input->Head().GetTypeAnn() && input->Head().GetTypeAnn()->GetKind() == ETypeAnnotationKind::Optional) {
8572
+ auto optType = input->Head().GetTypeAnn()->Cast<TOptionalExprType>();
8573
+ if (!EnsureVariantType(input->Head().Pos(), *optType->GetItemType(), ctx.Expr)) {
8574
+ return IGraphTransformer::TStatus::Error;
8575
+ }
8576
+ auto varType = optType->GetItemType()->Cast<TVariantExprType>();
8577
+ auto isOptionalItem = false;
8578
+ if (varType->GetUnderlyingType()->GetKind() == ETypeAnnotationKind::Tuple) {
8579
+ auto tupType = varType->GetUnderlyingType()->Cast<TTupleExprType>();
8580
+ if (tupType->GetSize() > 0 && tupType->GetItems()[0]->GetKind() == ETypeAnnotationKind::Optional) {
8581
+ isOptionalItem = true;
8582
+ }
8583
+ } else {
8584
+ auto strType = varType->GetUnderlyingType()->Cast<TStructExprType>();
8585
+ if (strType->GetSize() > 0 && strType->GetItems()[0]->GetItemType()->GetKind() == ETypeAnnotationKind::Optional) {
8586
+ isOptionalItem = true;
8587
+ }
8588
+ }
8589
+ output = ctx.Expr.Builder(input->Pos())
8590
+ .Callable(isOptionalItem ? "FlatMap" : "Map")
8591
+ .Add(0, input->HeadPtr())
8592
+ .Lambda(1)
8593
+ .Param("var")
8594
+ .Callable("VariantItem")
8595
+ .Arg(0, "var")
8596
+ .Seal()
8597
+ .Seal()
8598
+ .Seal().Build();
8599
+ } else {
8600
+ output = ctx.Expr.RenameNode(*input, "VariantItem");
8601
+ }
8602
+ return IGraphTransformer::TStatus::Repeat;
8603
+ }
8604
+
8537
8605
IGraphTransformer::TStatus VariantItemWrapper(const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) {
8538
8606
Y_UNUSED(output);
8539
8607
if (!EnsureArgsCount(*input, 1, ctx.Expr)) {
@@ -8591,6 +8659,112 @@ template <NKikimr::NUdf::EDataSlot DataSlot>
8591
8659
return IGraphTransformer::TStatus::Ok;
8592
8660
}
8593
8661
8662
+ IGraphTransformer::TStatus SqlVisitWrapper(const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) {
8663
+ if (!EnsureMinArgsCount(*input, 2, ctx.Expr)) {
8664
+ return IGraphTransformer::TStatus::Error;
8665
+ }
8666
+
8667
+ if (IsNull(input->Head())) {
8668
+ output = input->HeadPtr();
8669
+ return IGraphTransformer::TStatus::Repeat;
8670
+ }
8671
+
8672
+ if (input->Head().GetTypeAnn() && input->Head().GetTypeAnn()->GetKind() == ETypeAnnotationKind::Optional) {
8673
+ auto appendOtherArgs = [&] (auto &builder) -> auto {
8674
+ for (size_t pos = 1; pos < input->ChildrenSize(); pos++) {
8675
+ builder.Add(pos, input->ChildPtr(pos));
8676
+ }
8677
+ return builder;
8678
+ };
8679
+
8680
+ auto optType = input->Head().GetTypeAnn()->Cast<TOptionalExprType>();
8681
+ if (!EnsureVariantType(input->Pos(), *optType->GetItemType(), ctx.Expr)) {
8682
+ return IGraphTransformer::TStatus::Error;
8683
+ }
8684
+ auto varType = optType->GetItemType()->Cast<TVariantExprType>();
8685
+ const TTupleExprType* tupType = nullptr;
8686
+ const TStructExprType* strType = nullptr;
8687
+ if (varType->GetUnderlyingType()->GetKind() == ETypeAnnotationKind::Tuple) {
8688
+ tupType = varType->GetUnderlyingType()->Cast<TTupleExprType>();
8689
+ } else {
8690
+ strType = varType->GetUnderlyingType()->Cast<TStructExprType>();
8691
+ }
8692
+
8693
+ bool isOptionalResult = false;
8694
+ bool repeat = false;
8695
+ for (size_t idx = 1; idx < input->ChildrenSize(); idx++) {
8696
+ auto child = input->ChildPtr(idx);
8697
+ if (child->IsAtom()) {
8698
+ const TTypeAnnotationNode* itemType;
8699
+ if (tupType) {
8700
+ auto pos = FindOrReportMissingMember(child->Content(), child->Pos(), *tupType, ctx.Expr);
8701
+ if (!pos) {
8702
+ return IGraphTransformer::TStatus::Error;
8703
+ }
8704
+ itemType = tupType->GetItems()[*pos];
8705
+ } else {
8706
+ auto pos = FindOrReportMissingMember(child->Content(), child->Pos(), *strType, ctx.Expr);
8707
+ if (!pos) {
8708
+ return IGraphTransformer::TStatus::Error;
8709
+ }
8710
+ itemType = strType->GetItems()[*pos]->GetItemType();
8711
+ }
8712
+
8713
+ idx++;
8714
+ if (idx == input->ChildrenSize()) {
8715
+ ctx.Expr.AddError(TIssue(ctx.Expr.GetPosition(child->Pos()), "Expected lambda after this argument"));
8716
+ return IGraphTransformer::TStatus::Error;
8717
+ }
8718
+
8719
+ auto status = ConvertToLambda(input->ChildRef(idx), ctx.Expr, 1);
8720
+ if (status.Level != IGraphTransformer::TStatus::Ok) {
8721
+ return status;
8722
+ }
8723
+
8724
+ auto& lambda = input->ChildRef(idx);
8725
+ if (!UpdateLambdaAllArgumentsTypes(lambda, {itemType}, ctx.Expr)) {
8726
+ return IGraphTransformer::TStatus::Error;
8727
+ }
8728
+
8729
+ if (!lambda->GetTypeAnn()) {
8730
+ repeat = true;
8731
+ continue;
8732
+ }
8733
+
8734
+ if (lambda->GetTypeAnn()->GetKind() == ETypeAnnotationKind::Optional) {
8735
+ isOptionalResult = true;
8736
+ }
8737
+ } else {
8738
+ if (!EnsureComputable(*child, ctx.Expr)) {
8739
+ return IGraphTransformer::TStatus::Error;
8740
+ }
8741
+ if (child->GetTypeAnn()->GetKind() == ETypeAnnotationKind::Optional) {
8742
+ isOptionalResult = true;
8743
+ }
8744
+ }
8745
+ }
8746
+
8747
+ if (repeat) {
8748
+ return IGraphTransformer::TStatus::Repeat;
8749
+ }
8750
+
8751
+ output = appendOtherArgs(ctx.Expr.Builder(input->Pos())
8752
+ .Callable(isOptionalResult ? "FlatMap" : "Map")
8753
+ .Add(0, input->HeadPtr())
8754
+ .Lambda(1)
8755
+ .Param("var")
8756
+ .Callable("Visit")
8757
+ .Arg(0, "var"))
8758
+ .Seal()
8759
+ .Seal()
8760
+ .Seal().Build();
8761
+ } else {
8762
+ output = ctx.Expr.RenameNode(*input, "Visit");
8763
+ }
8764
+
8765
+ return IGraphTransformer::TStatus::Repeat;
8766
+ }
8767
+
8594
8768
IGraphTransformer::TStatus VisitWrapper(const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) {
8595
8769
Y_UNUSED(output);
8596
8770
if (!EnsureMinArgsCount(*input, 2, ctx.Expr)) {
@@ -8625,21 +8799,13 @@ template <NKikimr::NUdf::EDataSlot DataSlot>
8625
8799
const TTypeAnnotationNode* itemType;
8626
8800
ui32 itemIndex;
8627
8801
if (tupleType) {
8628
- ui32 index = 0;
8629
- if (!TryFromString(child->Content(), index)) {
8630
- ctx.Expr.AddError(TIssue(ctx.Expr.GetPosition(child->Pos()), TStringBuilder() << "Failed to convert to integer: " << child->Content()));
8631
- return IGraphTransformer::TStatus::Error;
8632
- }
8633
-
8634
- if (index >= tupleType->GetSize()) {
8635
- ctx.Expr.AddError(TIssue(ctx.Expr.GetPosition(child->Pos()), TStringBuilder()
8636
- << "Index out of range. Index: "
8637
- << index << ", size: " << tupleType->GetSize()));
8802
+ auto pos = FindOrReportMissingMember(child->Content(), child->Pos(), *tupleType, ctx.Expr);
8803
+ if (!pos) {
8638
8804
return IGraphTransformer::TStatus::Error;
8639
8805
}
8640
8806
8641
- itemType = tupleType->GetItems()[index ];
8642
- itemIndex = index ;
8807
+ itemType = tupleType->GetItems()[*pos ];
8808
+ itemIndex = *pos ;
8643
8809
} else {
8644
8810
auto pos = FindOrReportMissingMember(child->Content(), child->Pos(), *structType, ctx.Expr);
8645
8811
if (!pos) {
@@ -8763,6 +8929,10 @@ template <NKikimr::NUdf::EDataSlot DataSlot>
8763
8929
8764
8930
variantType = itemType->Cast<TVariantExprType>();
8765
8931
}
8932
+ else if (IsNull(input->Head())) {
8933
+ output = input->HeadPtr();
8934
+ return IGraphTransformer::TStatus::Repeat;
8935
+ }
8766
8936
else {
8767
8937
if (!EnsureVariantType(input->Head(), ctx.Expr)) {
8768
8938
return IGraphTransformer::TStatus::Error;
@@ -12421,7 +12591,9 @@ template <NKikimr::NUdf::EDataSlot DataSlot>
12421
12591
Functions["FlattenMembersType"] = &TypeArgWrapper<ETypeArgument::FlattenMembers>;
12422
12592
Functions["VariantUnderlyingType"] = &TypeArgWrapper<ETypeArgument::VariantUnderlying>;
12423
12593
Functions["Guess"] = &GuessWrapper;
12594
+ Functions["SqlVariantItem"] = &SqlVariantItemWrapper;
12424
12595
Functions["VariantItem"] = &VariantItemWrapper;
12596
+ Functions["SqlVisit"] = &SqlVisitWrapper;
12425
12597
Functions["Visit"] = &VisitWrapper;
12426
12598
Functions["Way"] = &WayWrapper;
12427
12599
Functions["SqlAccess"] = &SqlAccessWrapper;
0 commit comments