diff --git a/sql/src/main/java/org/apache/druid/sql/SqlLifecycle.java b/sql/src/main/java/org/apache/druid/sql/SqlLifecycle.java index 9007c775355..b3b9fee8266 100644 --- a/sql/src/main/java/org/apache/druid/sql/SqlLifecycle.java +++ b/sql/src/main/java/org/apache/druid/sql/SqlLifecycle.java @@ -28,6 +28,7 @@ import org.apache.calcite.tools.RelConversionException; import org.apache.calcite.tools.ValidationException; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.ISE; +import org.apache.druid.java.util.common.Pair; import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.java.util.common.guava.Sequence; import org.apache.druid.java.util.common.guava.SequenceWrapper; @@ -40,6 +41,7 @@ import org.apache.druid.query.QueryContext; import org.apache.druid.query.QueryContexts; import org.apache.druid.query.QueryInterruptedException; import org.apache.druid.query.QueryTimeoutException; +import org.apache.druid.segment.column.RowSignature; import org.apache.druid.server.QueryScheduler; import org.apache.druid.server.QueryStats; import org.apache.druid.server.RequestLogLine; @@ -55,6 +57,7 @@ import org.apache.druid.sql.calcite.planner.PlannerContext; import org.apache.druid.sql.calcite.planner.PlannerFactory; import org.apache.druid.sql.calcite.planner.PlannerResult; import org.apache.druid.sql.calcite.planner.PrepareResult; +import org.apache.druid.sql.calcite.table.RowSignatures; import org.apache.druid.sql.http.SqlParameter; import org.apache.druid.sql.http.SqlQuery; @@ -357,8 +360,11 @@ public class SqlLifecycle return plannerResult.run(); } + /** + * Only for testing... returns result row signature and sequence of results + */ @VisibleForTesting - public Sequence runSimple( + public Pair> runSimple( String sql, Map queryContext, List parameters, @@ -381,14 +387,20 @@ public class SqlLifecycle throw e; } - return Sequences.wrap(result, new SequenceWrapper() - { - @Override - public void after(boolean isDone, Throwable thrown) - { - finalizeStateAndEmitLogsAndMetrics(thrown, null, -1); - } - }); + return new Pair<>( + RowSignatures.fromRelDataType(plannerResult.rowType().getFieldNames(), plannerResult.rowType()), + Sequences.wrap( + result, + new SequenceWrapper() + { + @Override + public void after(boolean isDone, Throwable thrown) + { + finalizeStateAndEmitLogsAndMetrics(thrown, null, -1); + } + } + ) + ); } @VisibleForTesting diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/NestedDataOperatorConversions.java b/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/NestedDataOperatorConversions.java index 68e2f075014..e275434cd51 100644 --- a/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/NestedDataOperatorConversions.java +++ b/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/NestedDataOperatorConversions.java @@ -29,6 +29,7 @@ import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.type.OperandTypes; import org.apache.calcite.sql.type.SqlOperandCountRanges; +import org.apache.calcite.sql.type.SqlReturnTypeInference; import org.apache.calcite.sql.type.SqlTypeFamily; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.druid.java.util.common.StringUtils; @@ -56,6 +57,12 @@ import java.util.List; public class NestedDataOperatorConversions { + public static final SqlReturnTypeInference NESTED_RETURN_TYPE_INFERENCE = opBinding -> RowSignatures.makeComplexType( + opBinding.getTypeFactory(), + NestedDataComplexTypeSerde.TYPE, + true + ); + public static class GetPathOperatorConversion implements SqlOperatorConversion { private static final String FUNCTION_NAME = StringUtils.toUpperCase("get_path"); @@ -236,13 +243,7 @@ public class NestedDataOperatorConversions private static final SqlFunction SQL_FUNCTION = OperatorConversions .operatorBuilder(FUNCTION_NAME) .operandTypeChecker(OperandTypes.family(new SqlTypeFamily[]{SqlTypeFamily.ANY, SqlTypeFamily.CHARACTER, SqlTypeFamily.ANY, SqlTypeFamily.ANY, SqlTypeFamily.ANY})) - .returnTypeCascadeNullable( - new RowSignatures.ComplexSqlType( - SqlTypeName.OTHER, - NestedDataComplexTypeSerde.TYPE, - true - ).getSqlTypeName() - ) + .returnTypeInference(NESTED_RETURN_TYPE_INFERENCE) .functionCategory(SqlFunctionCategory.SYSTEM) .build(); @@ -429,16 +430,12 @@ public class NestedDataOperatorConversions continue; } operandTypes[i] = typeFactory.createTypeWithNullability( - typeFactory.createSqlType(SqlTypeName.ANY), true); + typeFactory.createSqlType(SqlTypeName.ANY), + true + ); } }) - .returnTypeCascadeNullable( - new RowSignatures.ComplexSqlType( - SqlTypeName.OTHER, - NestedDataComplexTypeSerde.TYPE, - true - ).getSqlTypeName() - ) + .returnTypeInference(NESTED_RETURN_TYPE_INFERENCE) .functionCategory(SqlFunctionCategory.SYSTEM) .build(); @@ -484,13 +481,7 @@ public class NestedDataOperatorConversions private static final SqlFunction SQL_FUNCTION = OperatorConversions .operatorBuilder(StringUtils.toUpperCase(FUNCTION_NAME)) .operandTypes(SqlTypeFamily.ANY) - .returnTypeCascadeNullable( - new RowSignatures.ComplexSqlType( - SqlTypeName.OTHER, - NestedDataComplexTypeSerde.TYPE, - true - ).getSqlTypeName() - ) + .returnTypeInference(NESTED_RETURN_TYPE_INFERENCE) .functionCategory(SqlFunctionCategory.USER_DEFINED_FUNCTION) .build(); @@ -566,13 +557,7 @@ public class NestedDataOperatorConversions private static final SqlFunction SQL_FUNCTION = OperatorConversions .operatorBuilder(StringUtils.toUpperCase(FUNCTION_NAME)) .operandTypes(SqlTypeFamily.ANY) - .returnTypeCascadeNullable( - new RowSignatures.ComplexSqlType( - SqlTypeName.OTHER, - NestedDataComplexTypeSerde.TYPE, - true - ).getSqlTypeName() - ) + .returnTypeInference(NESTED_RETURN_TYPE_INFERENCE) .functionCategory(SqlFunctionCategory.USER_DEFINED_FUNCTION) .build(); diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java index e3feaa2a2f7..33a96a46fbb 100644 --- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java +++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java @@ -409,7 +409,8 @@ public class DruidPlanner implements Closeable // because no values were provided. (Values are not required in the PREPARE case // but now that we're planning, we require them.) RelNode parameterized = possiblyLimitedRoot.rel.accept( - new RelParameterizerShuttle(plannerContext)); + new RelParameterizerShuttle(plannerContext) + ); final DruidRel druidRel = (DruidRel) planner.transform( CalciteRulesManager.DRUID_CONVENTION_RULES, planner.getEmptyTraitSet() diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/table/RowSignatures.java b/sql/src/main/java/org/apache/druid/sql/calcite/table/RowSignatures.java index 04d49573ce4..13e2c268d06 100644 --- a/sql/src/main/java/org/apache/druid/sql/calcite/table/RowSignatures.java +++ b/sql/src/main/java/org/apache/druid/sql/calcite/table/RowSignatures.java @@ -147,10 +147,7 @@ public class RowSignatures } break; case COMPLEX: - type = typeFactory.createTypeWithNullability( - new ComplexSqlType(SqlTypeName.OTHER, columnType, true), - true - ); + type = makeComplexType(typeFactory, columnType, true); break; default: throw new ISE("valueType[%s] not translatable", columnType); @@ -164,7 +161,37 @@ public class RowSignatures } /** - * Calcite {@link RelDataType} for Druid complex columns, to preserve complex type information + * Creates a {@link ComplexSqlType} using the supplied {@link RelDataTypeFactory} to ensure that the + * {@link ComplexSqlType} is interned. This is important because Calcite checks that the references are equal + * instead of the objects being equivalent. + * + * This method uses {@link RelDataTypeFactory#createTypeWithNullability(RelDataType, boolean) ensures that if the + * type factory is a {@link org.apache.calcite.rel.type.RelDataTypeFactoryImpl} that the type is passed through + * {@link org.apache.calcite.rel.type.RelDataTypeFactoryImpl#canonize(RelDataType)} which interns the type. + */ + public static RelDataType makeComplexType(RelDataTypeFactory typeFactory, ColumnType columnType, boolean isNullable) + { + return typeFactory.createTypeWithNullability( + new ComplexSqlType(SqlTypeName.OTHER, columnType, isNullable), + isNullable + ); + } + + /** + * Calcite {@link RelDataType} for Druid complex columns, to preserve complex type information. + * + * If using with other operations of a {@link RelDataTypeFactory}, consider wrapping the creation of this type in + * {@link RelDataTypeFactory#createTypeWithNullability(RelDataType, boolean) to ensure that if the type factory is a + * {@link org.apache.calcite.rel.type.RelDataTypeFactoryImpl} that the type is passed through + * {@link org.apache.calcite.rel.type.RelDataTypeFactoryImpl#canonize(RelDataType)} which interns the type. + * + * If {@link SqlTypeName} is going to be {@link SqlTypeName#OTHER} and a {@link RelDataTypeFactory} is available, + * consider using {@link #makeComplexType(RelDataTypeFactory, ColumnType, boolean)}. + * + * This type does not work well with {@link org.apache.calcite.sql.type.ReturnTypes#explicit(RelDataType)}, which + * will create new {@link RelDataType} using {@link SqlTypeName} during return type inference, so implementors of + * {@link org.apache.druid.sql.calcite.expression.SqlOperatorConversion} should implement the + * {@link org.apache.calcite.sql.type.SqlReturnTypeInference} directly for best results. */ public static final class ComplexSqlType extends AbstractSqlType { diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java index 8faee4fdf60..bcd33dad138 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java @@ -34,8 +34,10 @@ import org.apache.druid.hll.VersionOneHyperLogLogCollector; import org.apache.druid.jackson.DefaultObjectMapper; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.Intervals; +import org.apache.druid.java.util.common.Pair; import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.java.util.common.granularity.Granularity; +import org.apache.druid.java.util.common.guava.Sequence; import org.apache.druid.java.util.common.io.Closer; import org.apache.druid.java.util.common.logger.Logger; import org.apache.druid.math.expr.ExprMacroTable; @@ -73,6 +75,7 @@ import org.apache.druid.query.timeseries.TimeseriesQuery; import org.apache.druid.query.topn.TopNQueryConfig; import org.apache.druid.segment.column.ColumnHolder; import org.apache.druid.segment.column.ColumnType; +import org.apache.druid.segment.column.RowSignature; import org.apache.druid.segment.join.JoinType; import org.apache.druid.segment.virtual.ExpressionVirtualColumn; import org.apache.druid.server.QueryStackTests; @@ -652,7 +655,27 @@ public class BaseCalciteQueryTest extends CalciteTestBase sql, CalciteTests.REGULAR_USER_AUTH_RESULT, expectedQueries, - expectedResults + expectedResults, + null + ); + } + + public void testQuery( + final String sql, + final List expectedQueries, + final List expectedResults, + final RowSignature expectedResultRowSignature + ) throws Exception + { + testQuery( + PLANNER_CONFIG_DEFAULT, + QUERY_CONTEXT_DEFAULT, + DEFAULT_PARAMETERS, + sql, + CalciteTests.REGULAR_USER_AUTH_RESULT, + expectedQueries, + expectedResults, + expectedResultRowSignature ); } @@ -670,7 +693,8 @@ public class BaseCalciteQueryTest extends CalciteTestBase sql, CalciteTests.REGULAR_USER_AUTH_RESULT, expectedQueries, - expectedResults + expectedResults, + null ); } @@ -688,7 +712,8 @@ public class BaseCalciteQueryTest extends CalciteTestBase sql, CalciteTests.REGULAR_USER_AUTH_RESULT, expectedQueries, - expectedResults + expectedResults, + null ); } @@ -707,7 +732,8 @@ public class BaseCalciteQueryTest extends CalciteTestBase sql, authenticationResult, expectedQueries, - expectedResults + expectedResults, + null ); } @@ -741,7 +767,7 @@ public class BaseCalciteQueryTest extends CalciteTestBase { log.info("SQL: %s", sql); queryLogHook.clearRecordedQueries(); - final List plannerResults = + final Pair> plannerResults = getResults(plannerConfig, queryContext, DEFAULT_PARAMETERS, sql, authenticationResult); verifyResults(sql, expectedQueries, expectedResults, plannerResults); } @@ -763,7 +789,30 @@ public class BaseCalciteQueryTest extends CalciteTestBase sql, authenticationResult, expectedQueries, - new DefaultResultsVerifier(expectedResults), + expectedResults, + null + ); + } + + public void testQuery( + final PlannerConfig plannerConfig, + final Map queryContext, + final List parameters, + final String sql, + final AuthenticationResult authenticationResult, + final List expectedQueries, + final List expectedResults, + final RowSignature expectedResultSignature + ) throws Exception + { + testQuery( + plannerConfig, + queryContext, + parameters, + sql, + authenticationResult, + expectedQueries, + new DefaultResultsVerifier(expectedResults, expectedResultSignature), null ); } @@ -812,12 +861,12 @@ public class BaseCalciteQueryTest extends CalciteTestBase expectedExceptionInitializer.accept(expectedException); } - final List plannerResults = getResults(plannerConfig, theQueryContext, parameters, sql, authenticationResult); + final Pair> plannerResults = getResults(plannerConfig, theQueryContext, parameters, sql, authenticationResult); verifyResults(sql, theQueries, plannerResults, expectedResultsVerifier); } } - public List getResults( + public Pair> getResults( final PlannerConfig plannerConfig, final Map queryContext, final List parameters, @@ -838,7 +887,7 @@ public class BaseCalciteQueryTest extends CalciteTestBase ); } - public List getResults( + public Pair> getResults( final PlannerConfig plannerConfig, final Map queryContext, final List parameters, @@ -858,32 +907,43 @@ public class BaseCalciteQueryTest extends CalciteTestBase authorizerMapper, objectMapper ); + SqlLifecycle lifecycle = sqlLifecycleFactory.factorize(); - return sqlLifecycleFactory.factorize().runSimple(sql, queryContext, parameters, authenticationResult).toList(); + Pair> result = lifecycle.runSimple( + sql, + queryContext, + parameters, + authenticationResult + ); + return new Pair<>( + result.lhs, + result.rhs.toList() + ); } public void verifyResults( final String sql, final List expectedQueries, final List expectedResults, - final List results + final Pair> results ) { - verifyResults(sql, expectedQueries, results, new DefaultResultsVerifier(expectedResults)); + verifyResults(sql, expectedQueries, results, new DefaultResultsVerifier(expectedResults, null)); } public void verifyResults( final String sql, final List expectedQueries, - final List results, + final Pair> results, final ResultsVerifier expectedResultsVerifier ) { - for (int i = 0; i < results.size(); i++) { - log.info("row #%d: %s", i, Arrays.toString(results.get(i))); + for (int i = 0; i < results.rhs.size(); i++) { + log.info("row #%d: %s", i, Arrays.toString(results.rhs.get(i))); } - expectedResultsVerifier.verify(sql, results); + expectedResultsVerifier.verifyRowSignature(results.lhs); + expectedResultsVerifier.verify(sql, results.rhs); verifyQueries(sql, expectedQueries); } @@ -1222,16 +1282,32 @@ public class BaseCalciteQueryTest extends CalciteTestBase @FunctionalInterface public interface ResultsVerifier { + default void verifyRowSignature(RowSignature rowSignature) + { + // do nothing + } + void verify(String sql, List results); } public class DefaultResultsVerifier implements ResultsVerifier { protected final List expectedResults; + @Nullable + protected final RowSignature expectedResultRowSignature; - public DefaultResultsVerifier(List expectedResults) + public DefaultResultsVerifier(List expectedResults, RowSignature expectedSignature) { this.expectedResults = expectedResults; + this.expectedResultRowSignature = expectedSignature; + } + + @Override + public void verifyRowSignature(RowSignature rowSignature) + { + if (expectedResultRowSignature != null) { + Assert.assertEquals(expectedResultRowSignature, rowSignature); + } } @Override diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteIngestionDmlTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteIngestionDmlTest.java index 8200fa2dc1f..64c094923a1 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteIngestionDmlTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteIngestionDmlTest.java @@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableSet; import org.apache.druid.data.input.impl.CsvInputFormat; import org.apache.druid.data.input.impl.InlineInputSource; import org.apache.druid.java.util.common.ISE; +import org.apache.druid.java.util.common.Pair; import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.java.util.common.granularity.Granularity; import org.apache.druid.query.Query; @@ -310,7 +311,7 @@ public class CalciteIngestionDmlTest extends BaseCalciteQueryTest analyzeResources(plannerConfig, new AuthConfig(), sql, queryContext, authenticationResult) ); - final List results = + final Pair> results = getResults(plannerConfig, queryContext, Collections.emptyList(), sql, authenticationResult); verifyResults( diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java index 724f716bb91..1001604c6da 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java @@ -56,6 +56,7 @@ import org.apache.druid.segment.IndexBuilder; import org.apache.druid.segment.NestedDataDimensionSchema; import org.apache.druid.segment.QueryableIndex; import org.apache.druid.segment.column.ColumnType; +import org.apache.druid.segment.column.RowSignature; import org.apache.druid.segment.incremental.IncrementalIndexSchema; import org.apache.druid.segment.nested.NestedDataComplexTypeSerde; import org.apache.druid.segment.serde.ComplexMetrics; @@ -230,7 +231,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest new Object[]{NullHandling.defaultStringValue(), 4L}, new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -263,7 +268,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest new Object[]{NullHandling.defaultStringValue(), 4L}, new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -296,7 +305,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest new Object[]{NullHandling.defaultStringValue(), 4L}, new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -329,7 +342,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest new Object[]{NullHandling.defaultStringValue(), 5L}, new Object[]{"2", 1L}, new Object[]{"hello", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -371,7 +388,13 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest }, new Object[]{"100", "100", "100", 2L}, new Object[]{"200", "200", "200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.STRING) + .add("EXPR$2", ColumnType.STRING) + .add("EXPR$3", ColumnType.LONG) + .build() ); } @@ -413,7 +436,13 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest }, new Object[]{"100", "100", "100", 2L}, new Object[]{"200", "200", "200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.STRING) + .add("EXPR$2", ColumnType.STRING) + .add("EXPR$3", ColumnType.LONG) + .build() ); } @@ -448,7 +477,12 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest new Object[]{NullHandling.defaultStringValue(), NullHandling.defaultStringValue(), 4L}, new Object[]{"100", "100", 2L}, new Object[]{"200", "200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.STRING) + .add("EXPR$2", ColumnType.LONG) + .build() ); } @@ -483,7 +517,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest "100", 2L } - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -519,7 +557,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest "100", 2L } - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -555,7 +597,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest "100", 2L } - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -591,7 +637,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest "100", 1L } - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -622,7 +672,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest .setContext(QUERY_CONTEXT_DEFAULT) .build() ), - ImmutableList.of(new Object[]{"100", 1L}) + ImmutableList.of(new Object[]{"100", 1L}), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -656,7 +710,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 1L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -690,7 +748,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -721,7 +783,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest .setContext(QUERY_CONTEXT_DEFAULT) .build() ), - ImmutableList.of() + ImmutableList.of(), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -755,7 +821,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -788,7 +858,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -821,7 +895,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -853,7 +931,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{"100", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -887,7 +969,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -921,7 +1007,48 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() + ); + } + + @Test + public void testGroupByPathNumericBoundFilterLongNoUpperNumeric() throws Exception + { + testQuery( + "SELECT " + + "JSON_VALUE(nest, '$.x' RETURNING BIGINT)," + + "SUM(cnt) " + + "FROM druid.nested WHERE JSON_VALUE(nest, '$.x' RETURNING BIGINT) >= 100 GROUP BY 1", + ImmutableList.of( + GroupByQuery.builder() + .setDataSource(DATA_SOURCE) + .setInterval(querySegmentSpec(Filtration.eternity())) + .setGranularity(Granularities.ALL) + .setVirtualColumns( + new NestedFieldVirtualColumn("nest", "$.x", "v0", ColumnType.LONG) + ) + .setDimensions( + dimensions( + new DefaultDimensionSpec("v0", "d0", ColumnType.LONG) + ) + ) + .setDimFilter(bound("v0", "100", null, false, false, null, StringComparators.NUMERIC)) + .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) + .setContext(QUERY_CONTEXT_DEFAULT) + .build() + ), + ImmutableList.of( + new Object[]{100L, 2L}, + new Object[]{200L, 1L} + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.LONG) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -955,7 +1082,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{NullHandling.defaultStringValue(), 4L}, new Object[]{"100", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -988,7 +1119,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"2.02", 2L}, new Object[]{"3.03", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1021,7 +1156,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"2.02", 2L}, new Object[]{"3.03", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1053,7 +1192,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{"2.02", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1087,7 +1230,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"2.02", 2L}, new Object[]{"3.03", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1121,7 +1268,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"2.02", 2L}, new Object[]{"3.03", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1155,7 +1306,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{NullHandling.defaultStringValue(), 4L}, new Object[]{"2.02", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1188,7 +1343,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1222,7 +1381,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 1L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1256,7 +1419,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{NullHandling.defaultStringValue(), 4L}, new Object[]{"100", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1288,7 +1455,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{"100", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1321,7 +1492,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{"100", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1354,7 +1529,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{"100", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1387,7 +1566,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{"100", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1421,7 +1604,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1455,7 +1642,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 2L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1489,7 +1680,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"100", 1L}, new Object[]{"200", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1522,7 +1717,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{"100", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1545,7 +1744,10 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{400.0} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.DOUBLE) + .build() ); } @@ -1581,7 +1783,10 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{200.0} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.DOUBLE) + .build() ); } @@ -1615,7 +1820,10 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{100.0} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.DOUBLE) + .build() ); } @@ -1640,7 +1848,10 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{2.1} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.DOUBLE) + .build() ); } @@ -1677,7 +1888,10 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{2.1} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.DOUBLE) + .build() ); } @@ -1710,7 +1924,10 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{1.1} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.DOUBLE) + .build() ); } @@ -1733,7 +1950,10 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{400L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.LONG) + .build() ); } @@ -1757,7 +1977,10 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{700L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.LONG) + .build() ); } @@ -1780,7 +2003,10 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{400L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.LONG) + .build() ); } @@ -1804,7 +2030,10 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ), ImmutableList.of( new Object[]{700L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.LONG) + .build() ); } @@ -1842,7 +2071,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{null, 5L}, new Object[]{"[\"array\",\"n\"]", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING_ARRAY) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1880,7 +2113,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{null, 5L}, new Object[]{"[\"array\",\"n\"]", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING_ARRAY) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1919,7 +2156,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest new Object[]{null, 4L}, new Object[]{"[\"x\",\"y\",\"z\",\"mixed\",\"mixed2\"]", 2L}, new Object[]{"[\"x\",\"y\",\"z\",\"mixed2\"]", 1L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING_ARRAY) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1957,7 +2198,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{"[\"$\"]", 5L}, new Object[]{"[\"$.n.x\",\"$.array[0]\",\"$.array[1]\"]", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING_ARRAY) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -1989,7 +2234,11 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest ImmutableList.of( new Object[]{NullHandling.defaultStringValue(), 5L}, new Object[]{"b", 2L} - ) + ), + RowSignature.builder() + .add("EXPR$0", ColumnType.STRING) + .add("EXPR$1", ColumnType.LONG) + .build() ); } @@ -2052,7 +2301,12 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest new Object[]{null, null}, new Object[]{"{\"x\":1}", "{\"array\":[\"a\",\"b\"],\"n\":{\"x\":1}}"}, new Object[]{null, "2"} - ) + ), + RowSignature.builder() + .add("EXPR$0", NestedDataComplexTypeSerde.TYPE) + .add("EXPR$1", NestedDataComplexTypeSerde.TYPE) + .build() + ); } @@ -2097,7 +2351,10 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest new Object[]{"{\"x\":null,\"n\":null}"}, new Object[]{"{\"x\":\"100\",\"n\":{\"x\":1}}"}, new Object[]{"{\"x\":null,\"n\":null}"} - ) + ), + RowSignature.builder() + .add("EXPR$0", NestedDataComplexTypeSerde.TYPE) + .build() ); } @@ -2156,7 +2413,14 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest new Object[]{"eee", "\"eee\"", "\"eee\"", "{\"foo\":1}", null}, new Object[]{"aaa", "\"aaa\"", "\"aaa\"", "{\"foo\":1}", "{\"array\":[\"a\",\"b\"],\"n\":{\"x\":1}}"}, new Object[]{"ddd", "\"ddd\"", "\"ddd\"", "{\"foo\":1}", "2"} - ) + ), + RowSignature.builder() + .add("string", ColumnType.STRING) + .add("EXPR$1", NestedDataComplexTypeSerde.TYPE) + .add("EXPR$2", NestedDataComplexTypeSerde.TYPE) + .add("EXPR$3", NestedDataComplexTypeSerde.TYPE) + .add("EXPR$4", NestedDataComplexTypeSerde.TYPE) + .build() ); } } diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/planner/DruidRexExecutorTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/planner/DruidRexExecutorTest.java index c8464329797..492287b84de 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/planner/DruidRexExecutorTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/planner/DruidRexExecutorTest.java @@ -34,7 +34,6 @@ import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.type.ArraySqlType; import org.apache.calcite.sql.type.BasicSqlType; -import org.apache.calcite.sql.type.ReturnTypes; import org.apache.calcite.sql.type.SqlTypeFactoryImpl; import org.apache.calcite.sql.type.SqlTypeFamily; import org.apache.calcite.sql.type.SqlTypeName; @@ -72,8 +71,10 @@ public class DruidRexExecutorTest extends InitializedNullHandlingTest .operandTypes(SqlTypeFamily.ANY) .requiredOperands(0) .returnTypeInference( - ReturnTypes.explicit( - new RowSignatures.ComplexSqlType(SqlTypeName.OTHER, ColumnType.ofComplex("hyperUnique"), true) + opBinding -> RowSignatures.makeComplexType( + opBinding.getTypeFactory(), + ColumnType.ofComplex("hyperUnique"), + true ) ) .functionCategory(SqlFunctionCategory.USER_DEFINED_FUNCTION)