@@ -26,6 +26,22 @@ namespace {
26
26
return x->GetTypeAnn () && x->GetTypeAnn ()->GetKind () == ETypeAnnotationKind::EmptyList;
27
27
};
28
28
29
+ bool IsFieldSubset (const TStructExprType& structType, const TStructExprType& sourceStructType) {
30
+ for (auto & item : structType.GetItems ()) {
31
+ auto name = item->GetName ();
32
+ auto type = item->GetItemType ();
33
+ if (auto idx = sourceStructType.FindItem (name)) {
34
+ if (sourceStructType.GetItems ()[*idx]->GetItemType () == type) {
35
+ continue ;
36
+ }
37
+ }
38
+
39
+ return false ;
40
+ }
41
+
42
+ return true ;
43
+ }
44
+
29
45
TExprNode::TPtr RewriteMultiAggregate (const TExprNode& node, TExprContext& ctx) {
30
46
auto exprLambda = node.Child (1 );
31
47
const TStructExprType* structType = nullptr ;
@@ -551,20 +567,48 @@ namespace {
551
567
traitsInputItemType = traitsInputItemType->Cast <TListExprType>()->GetItemType ();
552
568
}
553
569
554
- const TStructExprType* traitsInputStruct = traitsInputItemType->Cast <TStructExprType>();
555
- // traitsInputStruct should be subset of inputStruct
556
- for (auto & item : traitsInputStruct->GetItems ()) {
557
- auto name = item->GetName ();
558
- auto type = item->GetItemType ();
559
- if (auto idx = inputStructType.FindItem (name)) {
560
- if (inputStructType.GetItems ()[*idx]->GetItemType () == type) {
561
- continue ;
570
+ bool isDistinct = calcSpec->IsCallable (" WindowTraits" ) && func->ChildrenSize () == 3 ;
571
+ if (isDistinct) {
572
+ auto distinctColumn = func->Child (2 );
573
+ if (!EnsureAtom (*distinctColumn, ctx)) {
574
+ return IGraphTransformer::TStatus::Error;
575
+ }
576
+
577
+ auto distinctColumnType = inputStructType.FindItemType (distinctColumn->Content ());
578
+ if (!distinctColumnType) {
579
+ ctx.AddError (TIssue (ctx.GetPosition (distinctColumn->Pos ()),
580
+ TStringBuilder () << " Unknown key column " << distinctColumn->Content () << " for distinct, input type is " <<
581
+ static_cast <const TTypeAnnotationNode&>(inputStructType)));
582
+ return IGraphTransformer::TStatus::Error;
583
+ }
584
+
585
+ if (distinctColumnType->GetKind () == ETypeAnnotationKind::Struct) {
586
+ const TStructExprType* traitsInputStruct = traitsInputItemType->Cast <TStructExprType>();
587
+ const TStructExprType* distinctColumnStructType = distinctColumnType->Cast <TStructExprType>();
588
+ if (!IsFieldSubset (*traitsInputStruct, *distinctColumnStructType)) {
589
+ ctx.AddError (TIssue (ctx.GetPosition (traitsInputTypeNode->Pos ()),
590
+ TStringBuilder () << " Expected window traits input type " << *traitsInputItemType << " to be subset of distinct key struct type" <<
591
+ static_cast <const TTypeAnnotationNode&>(*distinctColumnStructType)));
592
+ return IGraphTransformer::TStatus::Error;
562
593
}
594
+ } else if (distinctColumnType != traitsInputItemType) {
595
+ ctx.AddError (TIssue (ctx.GetPosition (distinctColumn->Pos ()),
596
+ TStringBuilder () << " Expected window traits input type " << *traitsInputItemType << " to be same as distinct key type " << *distinctColumnType));
597
+ return IGraphTransformer::TStatus::Error;
598
+ }
599
+
600
+ if (!EnsureHashableKey (distinctColumn->Pos (), distinctColumnType, ctx) ||
601
+ !EnsureEquatableKey (distinctColumn->Pos (), distinctColumnType, ctx)) {
602
+ return IGraphTransformer::TStatus::Error;
603
+ }
604
+ } else {
605
+ const TStructExprType* traitsInputStruct = traitsInputItemType->Cast <TStructExprType>();
606
+ if (!IsFieldSubset (*traitsInputStruct, inputStructType)) {
607
+ ctx.AddError (TIssue (ctx.GetPosition (traitsInputTypeNode->Pos ()), TStringBuilder () << " Invalid " <<
608
+ calcSpec->Content () << " traits input type: " << *traitsInputItemType << " , expecting subset of " <<
609
+ static_cast <const TTypeAnnotationNode&>(inputStructType)));
610
+ return IGraphTransformer::TStatus::Error;
563
611
}
564
- ctx.AddError (TIssue (ctx.GetPosition (traitsInputTypeNode->Pos ()), TStringBuilder () << " Invalid " <<
565
- calcSpec->Content () << " traits input type: " << *traitsInputItemType << " , expecting subset of " <<
566
- static_cast <const TTypeAnnotationNode&>(inputStructType)));
567
- return IGraphTransformer::TStatus::Error;
568
612
}
569
613
570
614
if (calcSpec->IsCallable (" WindowTraits" )) {
@@ -6018,9 +6062,14 @@ namespace {
6018
6062
}
6019
6063
6020
6064
for (ui32 i = 1 ; i < input->ChildrenSize (); ++i) {
6021
- if (!EnsureTupleSize (*input->Child (i), 2 , ctx.Expr )) {
6065
+ if (!EnsureTupleMinSize (*input->Child (i), 2 , ctx.Expr )) {
6022
6066
return IGraphTransformer::TStatus::Error;
6023
6067
}
6068
+
6069
+ if (!EnsureTupleMaxSize (*input->Child (i), 3 , ctx.Expr )) {
6070
+ return IGraphTransformer::TStatus::Error;
6071
+ }
6072
+
6024
6073
auto currColumn = input->Child (i)->Child (0 )->Content ();
6025
6074
auto calcSpec = input->Child (i)->Child (1 );
6026
6075
if (!calcSpec->IsCallable ({" WindowTraits" , " Lag" , " Lead" , " RowNumber" , " Rank" , " DenseRank" , " PercentRank" , " CumeDist" , " NTile" , " Void" })) {
@@ -6029,6 +6078,11 @@ namespace {
6029
6078
return IGraphTransformer::TStatus::Error;
6030
6079
}
6031
6080
6081
+ if (input->Child (i)->ChildrenSize () == 3 && !calcSpec->IsCallable (" WindowTraits" )) {
6082
+ ctx.Expr .AddError (TIssue (ctx.Expr .GetPosition (calcSpec->Pos ()), " DISTINCT is allowed only for aggregate functions" ));
6083
+ return IGraphTransformer::TStatus::Error;
6084
+ }
6085
+
6032
6086
if (i + 1 < input->ChildrenSize ()) {
6033
6087
auto nextColumn = input->Child (i + 1 )->Child (0 )->Content ();
6034
6088
if (currColumn == nextColumn) {
0 commit comments