Skip to content

Conversation

@cht42
Copy link
Contributor

@cht42 cht42 commented Nov 12, 2025

@cht42 cht42 force-pushed the cht/exchange branch 2 times, most recently from 458aef0 to 8c33967 Compare November 13, 2025 11:17
@cht42
Copy link
Contributor Author

cht42 commented Nov 18, 2025

@nielspardon do you have any other comments ? or is the PR good to merge ?

Copy link
Member

@nielspardon nielspardon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the changes look good. I only have some minor remarks

Comment on lines 1020 to 1025
ProtoExpressionConverter converter =
new ProtoExpressionConverter(lookup, extensions, input.getRecordType(), this);
List<FieldReference> fieldReferences =
rel.getScatterByFields().getFieldsList().stream()
.map(converter::from)
.collect(Collectors.toList());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do realize most of the other usages of ProtoExpressionConverter in this class also just use converter as the variable name. Given that we have so many different converters in the code base it might make sense to use a more specific variable name to make it clear which one it is. We could use the approach from the newAggregate() method in this class which calls the variable protoExprConverter.

Suggested change
ProtoExpressionConverter converter =
new ProtoExpressionConverter(lookup, extensions, input.getRecordType(), this);
List<FieldReference> fieldReferences =
rel.getScatterByFields().getFieldsList().stream()
.map(converter::from)
.collect(Collectors.toList());
ProtoExpressionConverter protoExprConverter =
new ProtoExpressionConverter(lookup, extensions, input.getRecordType(), this);
List<FieldReference> fieldReferences =
rel.getScatterByFields().getFieldsList().stream()
.map(protoExprConverter::from)
.collect(Collectors.toList());

Comment on lines 1048 to 1056
ProtoExpressionConverter converter =
new ProtoExpressionConverter(lookup, extensions, input.getRecordType(), this);

ImmutableSingleBucketExchange.Builder builder =
SingleBucketExchange.builder()
.input(input)
.partitionCount(rel.getPartitionCount())
.targets(targets)
.expression(converter.from(rel.getSingleTarget().getExpression()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, we could use a more specific variable name

Suggested change
ProtoExpressionConverter converter =
new ProtoExpressionConverter(lookup, extensions, input.getRecordType(), this);
ImmutableSingleBucketExchange.Builder builder =
SingleBucketExchange.builder()
.input(input)
.partitionCount(rel.getPartitionCount())
.targets(targets)
.expression(converter.from(rel.getSingleTarget().getExpression()));
ProtoExpressionConverter protoExprConverter =
new ProtoExpressionConverter(lookup, extensions, input.getRecordType(), this);
ImmutableSingleBucketExchange.Builder builder =
SingleBucketExchange.builder()
.input(input)
.partitionCount(rel.getPartitionCount())
.targets(targets)
.expression(protoExprConverter.from(rel.getSingleTarget().getExpression()));

Comment on lines 1072 to 1081
ProtoExpressionConverter converter =
new ProtoExpressionConverter(lookup, extensions, input.getRecordType(), this);

ImmutableMultiBucketExchange.Builder builder =
MultiBucketExchange.builder()
.input(input)
.partitionCount(rel.getPartitionCount())
.targets(targets)
.expression(converter.from(rel.getMultiTarget().getExpression()))
.constrainedToCount(rel.getMultiTarget().getConstrainedToCount());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, we could use a more specific variable name

Suggested change
ProtoExpressionConverter converter =
new ProtoExpressionConverter(lookup, extensions, input.getRecordType(), this);
ImmutableMultiBucketExchange.Builder builder =
MultiBucketExchange.builder()
.input(input)
.partitionCount(rel.getPartitionCount())
.targets(targets)
.expression(converter.from(rel.getMultiTarget().getExpression()))
.constrainedToCount(rel.getMultiTarget().getConstrainedToCount());
ProtoExpressionConverter protoExprConverter =
new ProtoExpressionConverter(lookup, extensions, input.getRecordType(), this);
ImmutableMultiBucketExchange.Builder builder =
MultiBucketExchange.builder()
.input(input)
.partitionCount(rel.getPartitionCount())
.targets(targets)
.expression(protoExprConverter.from(rel.getMultiTarget().getExpression()))
.constrainedToCount(rel.getMultiTarget().getConstrainedToCount());

Comment on lines 629 to 634
if (target.getType() instanceof TargetType.Uri) {
builder.setUri(((TargetType.Uri) target.getType()).getUri());
}
if (target.getType() instanceof TargetType.Extended) {
builder.setExtended(((TargetType.Extended) target.getType()).getExtended());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given that TargetType.Uri and TargetType.Extended are classes target.getType() can not be both so I would write this with an else if:

Suggested change
if (target.getType() instanceof TargetType.Uri) {
builder.setUri(((TargetType.Uri) target.getType()).getUri());
}
if (target.getType() instanceof TargetType.Extended) {
builder.setExtended(((TargetType.Extended) target.getType()).getExtended());
}
if (target.getType() instanceof TargetType.Uri) {
builder.setUri(((TargetType.Uri) target.getType()).getUri());
} else if (target.getType() instanceof TargetType.Extended) {
builder.setExtended(((TargetType.Extended) target.getType()).getExtended());
}

Comment on lines 221 to 278
.append("=partitionCount")
.append(exchange.getPartitionCount)
.append("=targets")
.append(exchange.getTargets)
.append("fields=")
.append(exchange.getFields)
})
}

override def visit(exchange: SingleBucketExchange, context: EmptyVisitationContext): String = {
withBuilder(exchange, 10)(
builder => {
builder
.append("=partitionCount")
.append(exchange.getPartitionCount)
.append("=targets")
.append(exchange.getTargets)
.append("=expression")
.append(exchange.getExpression)
})
}

override def visit(exchange: MultiBucketExchange, context: EmptyVisitationContext): String = {
withBuilder(exchange, 10)(
builder => {
builder
.append("=partitionCount")
.append(exchange.getPartitionCount)
.append("=targets")
.append(exchange.getTargets)
.append("=expression")
.append(exchange.getExpression)
.append("=constrainedToCount")
.append(exchange.getConstrainedToCount)
})
}

override def visit(exchange: RoundRobinExchange, context: EmptyVisitationContext): String = {
withBuilder(exchange, 10)(
builder => {
builder
.append("=partitionCount")
.append(exchange.getPartitionCount)
.append("=targets")
.append(exchange.getTargets)
.append("=exact")
.append(exchange.getExact)
})
}

override def visit(exchange: BroadcastExchange, context: EmptyVisitationContext): String = {
withBuilder(exchange, 10)(
builder => {
builder
.append("=partitionCount")
.append(exchange.getPartitionCount)
.append("=targets")
.append(exchange.getTargets)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't the equals sign always be the suffix of these string literals?

@nielspardon
Copy link
Member

Thanks for addressing the feedback. the one thing I didn't notice yesterday which would be great if you can take care of is to also add some unit tests for the changes in the core. We have relation roundtrip test here which you can mirror: https://github.com/substrait-io/substrait-java/tree/main/core/src/test/java/io/substrait/type/proto

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants