zachjsh commented on code in PR #14441:
URL: https://github.com/apache/druid/pull/14441#discussion_r1239261868


##########
sql/src/main/java/org/apache/druid/sql/calcite/parser/DruidSqlParserUtils.java:
##########
@@ -302,6 +309,82 @@ public static SqlOrderBy convertClusterByToOrderBy(SqlNode 
query, SqlNodeList cl
     );
   }
 
+  /**
+   * Return resolved clustered by columns specified to output columns.
+   * For example,
+   * EXPLAIN PLAN FOR
+   * INSERT INTO w000
+   * SELECT
+   *  TIME_PARSE("timestamp") AS __time,
+   *  page AS page_alias,
+   *  FLOOR("cost"),
+   *  country,
+   *  citName
+   * FROM ...
+   * PARTITIONED BY DAY
+   * CLUSTERED BY 1, 2, 3, cityName
+   *
+   * The above SQL will return the following clusteredBy columns: ["__time", 
"page_alias", "FLOOR(\"cost\")", cityName"]
+   * Any ordinal and expression specified in the CLUSTERED BY clause will 
resolve to the final output column name.
+   * @param clusteredByNodes  List of {@link SqlNode}s representing columns to 
be clustered by.
+   * @param sourceNode The select or order by source node.
+   */
+  @Nullable
+  public static List<String> 
resolveClusteredByColumnsToOutputColumns(SqlNodeList clusteredByNodes, SqlNode 
sourceNode)
+  {
+    // CLUSTERED BY is an optional clause
+    if (clusteredByNodes == null) {
+      return null;
+    }
+
+    Preconditions.checkArgument(sourceNode instanceof SqlOrderBy || sourceNode 
instanceof SqlSelect,
+                                "Source node must be either SqlOrderBy or 
SqlSelect");
+
+    final SqlSelect selectNode = (sourceNode instanceof SqlSelect) ? 
(SqlSelect) sourceNode
+                                                                   : 
(SqlSelect) ((SqlOrderBy) sourceNode).query;
+    final List<SqlNode> selectList = selectNode.getSelectList().getList();
+    final List<String> retClusteredByNames = new ArrayList<>();
+
+    for (SqlNode clusteredByNode : clusteredByNodes) {
+
+      // Verify that 'operand' is a literal number.
+      if (SqlUtil.isLiteral(clusteredByNode)) {
+        // An ordinal is specified in CLUSTERED BY clause, so lookup the 
ordinal in the SELECT clause
+        int ordinal = ((SqlNumericLiteral) 
clusteredByNode).getValueAs(Integer.class);
+        SqlNode node = selectList.get(ordinal - 1);
+
+        if (node instanceof SqlBasicCall) {
+          retClusteredByNames.add(getColumnNameFromSqlCall(node));
+        } else {
+          Preconditions.checkArgument(node instanceof SqlIdentifier, "Argument 
must be a SqlIdentifier");
+          SqlIdentifier n = ((SqlIdentifier) node);
+          retClusteredByNames.add(n.isSimple() ? n.getSimple() : 
n.names.get(1));
+        }
+      } else if (clusteredByNode instanceof SqlBasicCall) {
+        retClusteredByNames.add(getColumnNameFromSqlCall(clusteredByNode));
+      } else {
+        retClusteredByNames.add(clusteredByNode.toString());

Review Comment:
   Are we assuming a certain type of the clusteredByNode here, if so should we 
add a checkArgument call as we are doing in other places? Do we know that this 
instance types toString method will produce the name of column?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to