Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/src/main/java/io/substrait/dialect/ExpandFieldType.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
public enum ExpandFieldType {
/** A field whose value switches between expressions per expansion. */
SWITCHING_FIELD,
/** A field with a constant value across expansions. */
CONSTANT_FIELD
/** A field with the same value across expansions. */
CONSISTENT_FIELD
}
4 changes: 4 additions & 0 deletions core/src/main/java/io/substrait/dialect/ExpressionKind.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ public enum ExpressionKind {
NESTED,
/** A dynamic parameter expression. */
DYNAMIC_PARAMETER,
/** A lambda expression. */
LAMBDA,
/** A lambda invocation expression. */
LAMBDA_INVOCATION,
/** An execution-context variable expression. */
EXECUTION_CONTEXT_VARIABLE
}
2 changes: 2 additions & 0 deletions core/src/main/java/io/substrait/dialect/RelationKind.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public enum RelationKind {
EXCHANGE,
/** The expand relation. */
EXPAND,
/** The top-N relation. */
TOP_N,
/** The single-input extension relation. */
EXTENSION_SINGLE,
/** The multi-input extension relation. */
Expand Down
37 changes: 27 additions & 10 deletions core/src/main/java/io/substrait/dialect/SupportedRelation.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ public abstract class SupportedRelation {
public abstract List<ExpandFieldType> fieldTypes();

/**
* Supported message type URIs for {@code EXTENSION_SINGLE}/{@code MULTI}/{@code LEAF}.
* Supported message type URIs for {@code EXTENSION_SINGLE}/{@code MULTI}/{@code LEAF}, which must
* name at least one.
*
* @return the supported message type URIs
*/
Expand All @@ -100,21 +101,37 @@ protected void checkWriteTypes() {
}

/**
* Whether this entry can be written as a bare enum string. Extension relations are never bare:
* they are absent from the schema's bare-enum list.
*
* @return {@code true} if the entry carries no configuration
* The schema requires an extension relation entry to name at least one message type, the same way
* a {@code USER_DEFINED} type entry names its extension.
*/
public boolean isBare() {
switch (relation()) {
@Value.Check
protected void checkMessageTypes() {
if (isExtension(relation()) && messageTypes().isEmpty()) {
throw new IllegalArgumentException(
relation() + " relations must declare at least one supported message type.");
}
}

private static boolean isExtension(RelationKind relation) {
switch (relation) {
case EXTENSION_SINGLE:
case EXTENSION_MULTI:
case EXTENSION_LEAF:
return false;
return true;
default:
break;
return false;
}
return !metadata().isPresent()
}

/**
* Whether this entry can be written as a bare enum string. Extension relations are never bare:
* they are absent from the schema's bare-enum list.
*
* @return {@code true} if the entry carries no configuration
*/
public boolean isBare() {
return !isExtension(relation())
&& !metadata().isPresent()
&& joinTypes().isEmpty()
&& readTypes().isEmpty()
&& operations().isEmpty()
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/io/substrait/dialect/TypeKind.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public enum TypeKind {
LIST,
/** The map type. */
MAP,
/** The function type, the type of a lambda expression. */
FUNC,
/** A user-defined extension type. */
USER_DEFINED
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ void configuredRelationSerializesAsObject() {
@Test
void extensionRelationIsNeverBare() {
SupportedRelation extension =
SupportedRelation.builder().relation(RelationKind.EXTENSION_LEAF).build();
SupportedRelation.builder()
.relation(RelationKind.EXTENSION_LEAF)
.addMessageTypes("type.googleapis.com/google.profile.Person")
.build();
assertFalse(extension.isBare());

String yaml = Dialect.toYaml(Dialect.builder().addSupportedRelations(extension).build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ private static Dialect sampleDialect() {
.putDependencies("spark", "extension:substrait:spark")
// Types: bare, precision (max_precision), system_metadata, and user-defined.
.addSupportedTypes(SupportedType.of(TypeKind.BOOL))
.addSupportedTypes(SupportedType.of(TypeKind.FUNC))
.addSupportedTypes(
SupportedType.builder()
.type(TypeKind.PRECISION_TIMESTAMP)
Expand All @@ -38,6 +39,7 @@ private static Dialect sampleDialect() {
.build())
// Relations: bare, join, read, set, write, ddl, exchange, expand, extension.
.addSupportedRelations(SupportedRelation.of(RelationKind.FILTER))
.addSupportedRelations(SupportedRelation.of(RelationKind.TOP_N))
.addSupportedRelations(
SupportedRelation.builder()
.relation(RelationKind.JOIN)
Expand Down Expand Up @@ -71,15 +73,17 @@ private static Dialect sampleDialect() {
.addSupportedRelations(
SupportedRelation.builder()
.relation(RelationKind.EXPAND)
.addFieldTypes(ExpandFieldType.SWITCHING_FIELD)
.addFieldTypes(ExpandFieldType.SWITCHING_FIELD, ExpandFieldType.CONSISTENT_FIELD)
.build())
.addSupportedRelations(
SupportedRelation.builder()
.relation(RelationKind.EXTENSION_SINGLE)
.addMessageTypes("type.googleapis.com/google.profile.Person")
.build())
// Expressions: bare, cast, subquery, nested, execution-context-variable.
// Expressions: bare, lambda, cast, subquery, nested, execution-context-variable.
.addSupportedExpressions(SupportedExpression.of(ExpressionKind.LITERAL))
.addSupportedExpressions(SupportedExpression.of(ExpressionKind.LAMBDA))
.addSupportedExpressions(SupportedExpression.of(ExpressionKind.LAMBDA_INVOCATION))
.addSupportedExpressions(
SupportedExpression.builder()
.expression(ExpressionKind.CAST)
Expand Down
13 changes: 13 additions & 0 deletions core/src/test/java/io/substrait/dialect/DialectValidationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,17 @@ void writeAndDdlWriteTypesAreMutuallyExclusive() {
.addDdlWriteTypes(DdlWriteType.NAMED_OBJECT)
.build());
}

@Test
void extensionRelationsRequireMessageTypes() {
for (RelationKind kind :
new RelationKind[] {
RelationKind.EXTENSION_SINGLE, RelationKind.EXTENSION_MULTI, RelationKind.EXTENSION_LEAF
}) {
assertThrows(
IllegalArgumentException.class,
() -> SupportedRelation.builder().relation(kind).build(),
kind.name());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,11 @@ void aConcreteReturnStillChecksSharedParameters() {
assertTrue(
comparison.getMessage().contains("Inconsistent binding for type parameter 'any1'"),
comparison.getMessage());
}

UnsupportedOperationException strpos =
assertThrows(
UnsupportedOperationException.class,
() -> resolve("strpos:vchar_vchar", R.varChar(20), R.varChar(3)));
assertTrue(
strpos.getMessage().contains("Inconsistent binding for type parameter 'L1'"),
strpos.getMessage());
@Test
void independentParametersBindSeparately() {
assertEquals(R.I64, resolve("strpos:vchar_vchar", R.varChar(20), R.varChar(3)));
}

@Test
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ spark-3-5 = "3.5.4"
spark-4-0 = "4.0.2"
spotless = "8.10.2"
# substrait-packaging artifacts, versioned by the Substrait spec release they are generated from.
substrait-packaging = "0.102.0"
substrait-packaging = "0.103.0"
testcontainers = "2.0.5"
validator = "3.0.7"

Expand Down
Loading