From 98f2881b72b08c8277e433a402244a28693788f7 Mon Sep 17 00:00:00 2001 From: xuzifu666 <1206332514@qq.com> Date: Wed, 1 Jul 2026 14:12:49 +0800 Subject: [PATCH] [CALCITE-6344] RelToSqlConverter invalid quotation for arrays and item operator(ansi dialect) --- .../calcite/rel/rel2sql/SqlImplementor.java | 16 +++++++++++++--- .../rel/rel2sql/RelToSqlConverterTest.java | 18 +++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java index 7d579d184cc..403d7f6e2f8 100644 --- a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java +++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java @@ -713,9 +713,19 @@ public SqlNode toSql(@Nullable RexProgram program, RexNode rex) { break; case ROW: case ITEM: - final SqlNode expr = toSql(program, referencedExpr); - sqlIdentifier = new SqlIdentifier(expr.toString(), POS); - break; + // The referenced expression (e.g. an array/map ITEM access) must be + // unparsed as its own SqlNode so that the target dialect quotes each + // part correctly. Combine it with the accessed field names using the + // DOT operator instead of collapsing everything into a single + // identifier name (which would get quoted as one token). + SqlNode dotNode = toSql(program, referencedExpr); + RexFieldAccess dotAccess; + while ((dotAccess = accesses.pollLast()) != null) { + dotNode = + SqlStdOperatorTable.DOT.createCall(POS, dotNode, + new SqlIdentifier(dotAccess.getField().getName(), POS)); + } + return dotNode; default: sqlIdentifier = (SqlIdentifier) toSql(program, referencedExpr); } diff --git a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java index 4e2825bb3b6..1d3dda5af67 100644 --- a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java +++ b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java @@ -2998,14 +2998,26 @@ private SqlDialect nonOrdinalDialect() { * SqlItemOperator fails in RelToSqlConverter. */ @Test void testSqlItemOperator() { sql("SELECT foo[0].\"EXPR$1\" FROM (SELECT ARRAY[ROW('a', 'b')] AS foo)") - .ok("SELECT \"ARRAY[ROW('a', 'b')][0]\".\"EXPR$1\"\n" + .ok("SELECT ARRAY[ROW('a', 'b')][0].\"EXPR$1\"\n" + "FROM (VALUES (0)) AS \"t\" (\"ZERO\")"); sql("SELECT foo['k'].\"EXPR$1\" FROM (SELECT MAP['k', ROW('a', 'b')] AS foo)") - .ok("SELECT \"MAP['k', ROW('a', 'b')]['k']\".\"EXPR$1\"\n" + .ok("SELECT MAP['k', ROW('a', 'b')]['k'].\"EXPR$1\"\n" + "FROM (VALUES (0)) AS \"t\" (\"ZERO\")"); sql("select\"books\"[0].\"title\" from \"authors\"") .schema(CalciteAssert.SchemaSpec.BOOKSTORE) - .ok("SELECT \"`books`[0]\".\"title\"\n" + .ok("SELECT \"books\"[0].\"title\"\n" + + "FROM \"bookstore\".\"authors\""); + } + + /** Test case for + * [CALCITE-6344] + * RelToSqlConverter invalid quotation for arrays and item operator + * (ansi dialect). */ + @Test void testSqlItemOperator2() { + sql("SELECT \"books\"[0].\"title\" from \"bookstore\".\"authors\"") + .schema(CalciteAssert.SchemaSpec.BOOKSTORE) + .withPostgresql() + .ok("SELECT \"books\"[0].\"title\"\n" + "FROM \"bookstore\".\"authors\""); }