diff --git a/core/trino-main/src/main/java/io/trino/sql/analyzer/StatementAnalyzer.java b/core/trino-main/src/main/java/io/trino/sql/analyzer/StatementAnalyzer.java index 6cb9cce5f858..299f19ce5dc5 100644 --- a/core/trino-main/src/main/java/io/trino/sql/analyzer/StatementAnalyzer.java +++ b/core/trino-main/src/main/java/io/trino/sql/analyzer/StatementAnalyzer.java @@ -1580,6 +1580,16 @@ protected Scope visitTableFunctionInvocation(TableFunctionInvocation node, Optio // so the function's analyze() method should not return the proper columns descriptor. throw semanticException(AMBIGUOUS_RETURN_TYPE, node, "Returned relation type for table function %s is ambiguous", node.getName()); } + if (function.getArguments().stream() + .filter(TableArgumentSpecification.class::isInstance) + .map(TableArgumentSpecification.class::cast) + .noneMatch(TableArgumentSpecification::isPassThroughColumns)) { + // According to SQL standard ISO/IEC 9075-2, 10.4 , p. 764, + // if there is no generic table parameter that specifies PASS THROUGH, then number of proper columns shall be positive. + // For GENERIC_TABLE and DescribedTable returned types, this is enforced by the Descriptor constructor, which requires positive number of fields. + // Here we enforce it for the remaining returned type specification: ONLY_PASS_THROUGH. + throw new TrinoException(FUNCTION_IMPLEMENTATION_ERROR, "A table function with ONLY_PASS_THROUGH return type must have a table argument with pass-through columns."); + } properColumnsDescriptor = null; } else if (returnTypeSpecification == GENERIC_TABLE) { diff --git a/core/trino-main/src/test/java/io/trino/connector/TestingTableFunctions.java b/core/trino-main/src/test/java/io/trino/connector/TestingTableFunctions.java index 3a94bacd9509..a2c849a59dcd 100644 --- a/core/trino-main/src/test/java/io/trino/connector/TestingTableFunctions.java +++ b/core/trino-main/src/test/java/io/trino/connector/TestingTableFunctions.java @@ -267,6 +267,7 @@ public OnlyPassThroughFunction() ImmutableList.of( TableArgumentSpecification.builder() .name("INPUT") + .passThroughColumns() .keepWhenEmpty() .build()), ONLY_PASS_THROUGH);