diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java index bd170172d6..54353e86f6 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/LogicalOperator.java @@ -261,10 +261,23 @@ private static LogicalOperator generateCorrelatedFieldAccess(@Nonnull Expression () -> String.format(Locale.ROOT, "join correlation can occur only on column of repeated type, not %s type", expression.getDataType())); final var explode = new ExplodeExpression(expression.getUnderlying()); final var resultingQuantifier = Quantifier.forEach(Reference.of(explode)); - final var outputAttributes = Expressions.of(convertToExpressions(resultingQuantifier)); + + Expressions outputAttributes; + if (resultingQuantifier.getFlowedObjectType().isPrimitive()) { + outputAttributes = Expressions.of(convertPrimitiveArrayToExpressions(resultingQuantifier, explode, alias)); + } else { + outputAttributes = Expressions.of(convertToExpressions(resultingQuantifier)); + } return LogicalOperator.newOperator(alias, outputAttributes, resultingQuantifier); } + @Nonnull + private static Expressions convertPrimitiveArrayToExpressions(@Nonnull Quantifier quantifier, @Nonnull ExplodeExpression explodeExpression, @Nonnull Optional alias) { + final ImmutableList.Builder attributesBuilder = ImmutableList.builder(); + attributesBuilder.add(new Expression(alias, DataTypeUtils.toRelationalType(explodeExpression.getResultValue().getResultType()), quantifier.getFlowedObjectValue())); + return Expressions.of(attributesBuilder.build()); + } + @Nonnull public static Expressions convertToExpressions(@Nonnull Quantifier quantifier) { final ImmutableList.Builder attributesBuilder = ImmutableList.builder(); diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java index 61000544f7..b105433459 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/StandardQueryTests.java @@ -157,7 +157,6 @@ void simpleSelect() throws Exception { @Test void simpleSelectWithNonNullableArrays() throws Exception { - // var ddl = Ddl.builder().database(URI.create("/TEST/QT")).relationalExtension(relationalExtension).schemaTemplate(schemaTemplateWithNonNullableArrays).build(); try (var ddl = Ddl.builder().database(URI.create("/TEST/QT")).relationalExtension(relationalExtension).schemaTemplate(schemaTemplateWithNonNullableArrays).build()) { try (var statement = ddl.setSchemaAndGetConnection().createStatement()) { var insertedRecord = insertRestaurantComplexRecord(statement); @@ -1360,6 +1359,61 @@ void unionIsNotSupported() throws Exception { } } + @Test + void structArrayContains() throws Exception { + final String schemaTemplate = "CREATE TYPE AS STRUCT A(col2 string, col3 bigint, col4 bigint) " + + "CREATE TABLE T1(col1 bigint, a A Array, col5 bigint, primary key(col1))"; + try (var ddl = Ddl.builder().database(URI.create("/TEST/QT")).relationalExtension(relationalExtension).schemaTemplate(schemaTemplate).build()) { + try (var statement = ddl.setSchemaAndGetConnection().createStatement()) { + statement.executeUpdate("insert into t1 values (42, [('Apple', 1, 100), ('Orange', 2, 200)], 142), (44, [('Grape', 3, 300), ('Pear', 4, 400)], 144)"); + Assertions.assertTrue(statement.execute("SELECT T1.col5, X.col2, X.col3 FROM T1, (SELECT col2, col3 FROM T1.A) X where X.col2 = 'Grape'")); + try (final RelationalResultSet resultSet = statement.getResultSet()) { + ResultSetAssert.assertThat(resultSet).hasNextRow() + .isRowExactly(144L, "Grape", 3L) + .hasNoNextRow(); + } + Assertions.assertTrue(statement.execute("SELECT T1.col5 FROM T1 where exists (SELECT col2 FROM T1.A where col2 = 'Grape')")); + try (final RelationalResultSet resultSet = statement.getResultSet()) { + ResultSetAssert.assertThat(resultSet).hasNextRow() + .isRowExactly(144L) + .hasNoNextRow(); + } + Assertions.assertTrue(statement.execute("SELECT T1.col5, X.col2, X.col3 FROM T1, (SELECT col2, col3 FROM T1.A) X where X.col2 in ('Grape', 'Orange')")); + try (final RelationalResultSet resultSet = statement.getResultSet()) { + ResultSetAssert.assertThat(resultSet).hasNextRow() + .isRowExactly(144L, "Grape", 3L) + .hasNextRow() + .isRowExactly(142L, "Orange", 2L) + .hasNoNextRow(); + } + } + } + } + + @Test + void primitiveArrayContains() throws Exception { + final String schemaTemplate = "CREATE TABLE T1(col1 bigint, a string Array, primary key(col1))"; + try (var ddl = Ddl.builder().database(URI.create("/TEST/QT")).relationalExtension(relationalExtension).schemaTemplate(schemaTemplate).build()) { + try (var statement = ddl.setSchemaAndGetConnection().createStatement()) { + statement.executeUpdate("insert into t1 values (42, ['Apple', 'Orange']), (44, ['Grape', 'Pear'])"); + Assertions.assertTrue(statement.execute("SELECT * FROM T1 where exists (SELECT 1 FROM T1.A r where r = 'Grape')")); + try (final RelationalResultSet resultSet = statement.getResultSet()) { + ResultSetAssert.assertThat(resultSet).hasNextRow() + .isRowExactly(44L, EmbeddedRelationalArray.newBuilder().addString("Grape").addString("Pear").build()) + .hasNoNextRow(); + } + Assertions.assertTrue(statement.execute("SELECT * FROM T1 where exists (SELECT 1 FROM T1.A r where r in ('Grape', 'Orange'))")); + try (final RelationalResultSet resultSet = statement.getResultSet()) { + ResultSetAssert.assertThat(resultSet).hasNextRow() + .isRowExactly(42L, EmbeddedRelationalArray.newBuilder().addString("Apple").addString("Orange").build()) + .hasNextRow() + .isRowExactly(44L, EmbeddedRelationalArray.newBuilder().addString("Grape").addString("Pear").build()) + .hasNoNextRow(); + } + } + } + } + @Test void cteWorksCorrectly() throws Exception { final String schemaTemplate = "CREATE TABLE T1(pk bigint, a bigint, b bigint, c bigint, PRIMARY KEY(pk))";