You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by ab...@apache.org on 2025/05/12 19:28:46 UTC
(druid) branch pivot_col_name_null_fix created (now eb74217ffa1)
This is an automated email from the ASF dual-hosted git repository.
abhishekrb pushed a change to branch pivot_col_name_null_fix
in repository https://gitbox.apache.org/repos/asf/druid.git
at eb74217ffa1 Preserve column names as-is for unnest queries in the decoupled planner mode.
This branch includes the following new commits:
new eb74217ffa1 Preserve column names as-is for unnest queries in the decoupled planner mode.
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org
(druid) 01/01: Preserve column names as-is for unnest queries in the decoupled planner mode.
Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
abhishekrb pushed a commit to branch pivot_col_name_null_fix
in repository https://gitbox.apache.org/repos/asf/druid.git
commit eb74217ffa1f257496e9e90cc6a6036f59a85bcc
Author: Abhishek Balaji Radhakrishnan <ab...@gmail.com>
AuthorDate: Mon May 12 12:22:11 2025 -0700
Preserve column names as-is for unnest queries in the decoupled planner mode.
Unnest queries in the decoupled planner mode adds a suffix "_null" for some
cases. Currently the PlannerResult is based on the built query's output type rather
than the planned output type (which shouldn't contain the "_null" suffix). This is the
same for "coupled" planner.
The planner result is used for populating things in the sql direct statement. The sql row
transformer depends on the planner result, so this PR fixes that by aligning with the planned
output type.
---
.../druid/sql/calcite/planner/QueryHandler.java | 7 +-
.../org/apache/druid/sql/http/SqlResourceTest.java | 103 +++++++++++++++++++++
2 files changed, 106 insertions(+), 4 deletions(-)
diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java b/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java
index 0f2f25ef6d3..9e608f7616a 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java
@@ -540,6 +540,8 @@ public abstract class QueryHandler extends SqlStatementHandler.BaseStatementHand
QueryValidations.validateLogicalQueryForDruid(handlerContext.plannerContext(), parameterized);
CalcitePlanner planner = handlerContext.planner();
+ final RelDataType rowType = prepareResult.getReturnedRowType();
+
if (plannerContext.getPlannerConfig()
.getNativeQuerySqlPlanningMode()
.equals(QueryContexts.NATIVE_QUERY_SQL_PLANNING_MODE_DECOUPLED)
@@ -574,7 +576,7 @@ public abstract class QueryHandler extends SqlStatementHandler.BaseStatementHand
return planExplanation(possiblyLimitedRoot, newRoot, true);
}
- return new PlannerResult(resultsSupplier, finalBaseQuery.getOutputRowType());
+ return new PlannerResult(resultsSupplier, rowType);
} else {
final DruidRel<?> druidRel = (DruidRel<?>) planner.transform(
CalciteRulesManager.DRUID_CONVENTION_RULES,
@@ -591,9 +593,6 @@ public abstract class QueryHandler extends SqlStatementHandler.BaseStatementHand
if (explain != null) {
return planExplanation(possiblyLimitedRoot, druidRel, true);
} else {
- // Compute row type.
- final RelDataType rowType = prepareResult.getReturnedRowType();
-
// sanity check
final Set<ResourceAction> readResourceActions =
plannerContext.getResourceActions()
diff --git a/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java b/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java
index 8b767de3b5a..f18873668ea 100644
--- a/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java
@@ -634,6 +634,109 @@ public class SqlResourceTest extends CalciteTestBase
);
}
+
+ @Test
+ public void testPivotRowTypePreservedInDecoupledPlanner() throws Exception
+ {
+ final List<Map<String, Object>> rows = doPost(
+ new SqlQuery(
+ "SET plannerStrategy='DECOUPLED';" +
+ " WITH t1 AS (\n" +
+ " SELECT *\n" +
+ " FROM (\n" +
+ " VALUES\n" +
+ " ('18-19', 'female', 84),\n" +
+ " ('18-19', 'male', 217),\n" +
+ " ('20-29', 'female', 321),\n" +
+ " ('20-29', 'male', 820),\n" +
+ " ('30-39', 'female', 63),\n" +
+ " ('30-39', 'male', 449),\n" +
+ " ('40-49', 'female', 10),\n" +
+ " ('40-49', 'male', 83),\n" +
+ " ('50-59', 'female', 2),\n" +
+ " ('50-59', 'male', 13)\n" +
+ " ) AS data(Age, Gender, Visitors)\n" +
+ "),\n" +
+ "t2 AS (\n" +
+ " SELECT Age, Gender, CAST(SUM(Visitors) AS double) / (SELECT SUM(Visitors) FROM t1) AS Share\n" +
+ " FROM t1\n" +
+ " GROUP BY 1, 2\n" +
+ ")\n" +
+ "SELECT *\n" +
+ "FROM t2\n" +
+ "PIVOT (MAX(Share) FOR Gender IN ('female' AS Women, 'male' AS Men));",
+ ResultFormat.OBJECT,
+ false,
+ false,
+ false,
+ null,
+ null
+ )
+ ).rhs;
+
+ Assert.assertEquals(
+ ImmutableList.of(
+ ImmutableMap.of("Age", "18-19", "Women", 0.040737148399612025, "Men", 0.1052376333656644),
+ ImmutableMap.of("Age", "20-29", "Women", 0.1556741028128031, "Men", 0.3976721629485936),
+ ImmutableMap.of("Age", "30-39", "Women", 0.030552861299709022, "Men", 0.2177497575169738),
+ ImmutableMap.of("Age", "40-49", "Women", 0.004849660523763337, "Men", 0.040252182347235696),
+ ImmutableMap.of("Age", "50-59", "Women", 0.0009699321047526673, "Men", 0.006304558680892337)
+ ),
+ rows
+ );
+ }
+
+ @Test
+ public void testPivotRowTypePreservedInCoupledPlanner() throws Exception
+ {
+ final List<Map<String, Object>> rows = doPost(
+ new SqlQuery(
+ "SET plannerStrategy='COUPLED';" +
+ " WITH t1 AS (\n" +
+ " SELECT *\n" +
+ " FROM (\n" +
+ " VALUES\n" +
+ " ('18-19', 'female', 84),\n" +
+ " ('18-19', 'male', 217),\n" +
+ " ('20-29', 'female', 321),\n" +
+ " ('20-29', 'male', 820),\n" +
+ " ('30-39', 'female', 63),\n" +
+ " ('30-39', 'male', 449),\n" +
+ " ('40-49', 'female', 10),\n" +
+ " ('40-49', 'male', 83),\n" +
+ " ('50-59', 'female', 2),\n" +
+ " ('50-59', 'male', 13)\n" +
+ " ) AS data(Age, Gender, Visitors)\n" +
+ "),\n" +
+ "t2 AS (\n" +
+ " SELECT Age, Gender, CAST(SUM(Visitors) AS double) / (SELECT SUM(Visitors) FROM t1) AS Share\n" +
+ " FROM t1\n" +
+ " GROUP BY 1, 2\n" +
+ ")\n" +
+ "SELECT *\n" +
+ "FROM t2\n" +
+ "PIVOT (MAX(Share) FOR Gender IN ('female' AS Women, 'male' AS Men));",
+ ResultFormat.OBJECT,
+ false,
+ false,
+ false,
+ null,
+ null
+ )
+ ).rhs;
+
+ Assert.assertEquals(
+ ImmutableList.of(
+ ImmutableMap.of("Age", "18-19", "Women", 0.040737148399612025, "Men", 0.1052376333656644),
+ ImmutableMap.of("Age", "20-29", "Women", 0.1556741028128031, "Men", 0.3976721629485936),
+ ImmutableMap.of("Age", "30-39", "Women", 0.030552861299709022, "Men", 0.2177497575169738),
+ ImmutableMap.of("Age", "40-49", "Women", 0.004849660523763337, "Men", 0.040252182347235696),
+ ImmutableMap.of("Age", "50-59", "Women", 0.0009699321047526673, "Men", 0.006304558680892337)
+ ),
+ rows
+ );
+ }
+
@Test
public void testArrayResultFormat() throws Exception
{
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org