From ee236e53cc87d831962e3ce58d88224f3bf85c59 Mon Sep 17 00:00:00 2001 From: Marc Handalian Date: Tue, 1 Sep 2026 22:23:40 +0000 Subject: [PATCH] Map Calcite ROW to STRUCT in convertSqlTypeNameToExprType MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit convertExprTypeToRelDataType builds STRUCT as MAP, since the v2 path only passes _source JSON through and needs no field types. So the reverse mapping only had `case MAP -> STRUCT` — a genuine Calcite ROW matched nothing, fell through to `default -> UNKNOWN`, and surfaced as "type": "unknown" in the response schema. That is reachable from the analytics engine, which materializes an `object` field as a real ROW built from typed columns. Before, `fields city` reported "unknown"; now "struct", matching what a lucene-only cluster returns for the same mapping. Signed-off-by: Marc Handalian Signed-off-by: Marc Handalian --- .../opensearch/sql/calcite/utils/OpenSearchTypeFactory.java | 5 +++++ .../sql/calcite/utils/OpenSearchTypeFactoryTest.java | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/core/src/main/java/org/opensearch/sql/calcite/utils/OpenSearchTypeFactory.java b/core/src/main/java/org/opensearch/sql/calcite/utils/OpenSearchTypeFactory.java index b8ed9b6cd7e..a048d9b303b 100644 --- a/core/src/main/java/org/opensearch/sql/calcite/utils/OpenSearchTypeFactory.java +++ b/core/src/main/java/org/opensearch/sql/calcite/utils/OpenSearchTypeFactory.java @@ -252,6 +252,11 @@ public static ExprType convertSqlTypeNameToExprType(SqlTypeName sqlTypeName) { INTERVAL; case ARRAY -> ARRAY; case MAP -> STRUCT; + // Calcite spells a struct as ROW. convertExprTypeToRelDataType builds STRUCT as + // MAP since the v2 path only passes _source JSON through, so a genuine ROW — + // from an engine that builds a struct out of typed columns — matched nothing and fell + // through to UNKNOWN. + case ROW -> STRUCT; case GEOMETRY -> GEO_POINT; case NULL, ANY, OTHER -> UNDEFINED; default -> UNKNOWN; diff --git a/core/src/test/java/org/opensearch/sql/calcite/utils/OpenSearchTypeFactoryTest.java b/core/src/test/java/org/opensearch/sql/calcite/utils/OpenSearchTypeFactoryTest.java index 7e57aaa9bf9..8ae907e9e30 100644 --- a/core/src/test/java/org/opensearch/sql/calcite/utils/OpenSearchTypeFactoryTest.java +++ b/core/src/test/java/org/opensearch/sql/calcite/utils/OpenSearchTypeFactoryTest.java @@ -286,6 +286,12 @@ public void testConvertExprTypeBinaryToNullableVarbinary() { assertTrue(result.isNullable()); } + @Test + public void testConvertRowReturnsStructExprType() { + assertEquals( + ExprCoreType.STRUCT, OpenSearchTypeFactory.convertSqlTypeNameToExprType(SqlTypeName.ROW)); + } + // ---------- convertAnalyticsEngineRelDataTypeToExprType ---------- // UDT-aware variant for the response-schema path. Must agree with the // planner-internal convertRelDataTypeToExprType on every non-UDT input.