Jackie-Jiang commented on code in PR #11330:
URL: https://github.com/apache/pinot/pull/11330#discussion_r1294995248


##########
pinot-common/src/main/java/org/apache/pinot/common/utils/request/RequestUtils.java:
##########
@@ -290,4 +303,151 @@ public static Map<String, String> 
getOptionsFromJson(JsonNode request, String op
   public static Map<String, String> getOptionsFromString(String optionStr) {
     return 
Splitter.on(';').omitEmptyStrings().trimResults().withKeyValueSeparator('=').split(optionStr);
   }
+
+  /**
+   * Returns all the table names from a given {@link SqlNode}.
+   * <pre>
+   * 1. FROM Clause (FromNode): The main location where the table name is 
specified.
+   * </pre>
+   * {@code
+   *     SELECT * FROM table_name;
+   * }
+   * <pre>
+   * 2. JOIN Clauses (JoinNode): Table names will be part of INNER JOIN, LEFT 
JOIN, RIGHT JOIN, FULL JOIN, etc.
+   * </pre>
+   * {@code
+   *     SELECT * FROM table_name1 JOIN table_name2 ON table_name1.column_name 
= table_name2.column_name;
+   * }
+   * <pre>
+   * 3. SubQueries in FROM Clause (SubQueryNode): Subqueries in the FROM 
clause might contain additional table names.
+   * </pre>
+   * {@code
+   *     SELECT * FROM (SELECT * FROM table_name) WHERE column_name = value;
+   * }
+   * <pre>
+   * 4. WITH Clause (WithNode): Common Table Expressions (CTEs) may contain 
table names.
+   * </pre>
+   * {@code
+   *     WITH table_name1 AS (SELECT * FROM table_name2) SELECT * FROM 
table_name1;
+   * }
+   * <pre>
+   * 5. LATERAL or APPLY Operators (LateralNode, ApplyNode): These operators 
allow you to reference columns of
+   *    preceding tables in FROM clause sub-queries.
+   * </pre>
+   * {@code
+   *     SELECT * FROM table_name1, LATERAL (SELECT * FROM table_name2) AS 
table_name2;
+   * }
+   * <pre>
+   * 6. UNION, INTERSECT, EXCEPT Clauses (SetOperationNode): These set 
operations between multiple SELECT statements
+   *    can also contain table names.
+   * </pre>
+   * {@code
+   *     SELECT * FROM table_name1 UNION SELECT * FROM table_name2;
+   * }
+   * <pre>
+   * 7. WHERE Clause (WhereNode): WHERE clause can contain table names in 
subqueries.
+   * </pre>
+   * {@code
+   *     SELECT * FROM table_name WHERE column_name IN (SELECT * FROM 
table_name2);
+   * }
+   * @param sqlNode Sql Query Node
+   * @return Set of table names
+   */
+  public static Set<String> getTableNames(SqlNode sqlNode) {
+    Set<String> tableNames = new HashSet<>();
+    Set<String> tableNameAlias = new HashSet<>();
+    extractTableNames(sqlNode, tableNames, tableNameAlias);
+    tableNames.removeAll(tableNameAlias);
+    return tableNames;
+  }
+
+  public static void extractTableNames(SqlNode sqlNode, Set<String> 
tableNames, Set<String> tableNameAlias) {
+    if (sqlNode instanceof SqlSelect) {
+      // Handle SqlSelect query
+      SqlNode fromNode = ((SqlSelect) sqlNode).getFrom();
+      if ((fromNode instanceof SqlBasicCall)
+          && (((SqlBasicCall) fromNode).getOperator() instanceof 
SqlAsOperator)) {
+        extractTableNames(fromNode, tableNames, tableNameAlias);
+      } else if (fromNode instanceof SqlIdentifier) {
+        tableNames.add(getTableName((SqlIdentifier) fromNode));
+      } else {
+        extractTableNames(fromNode, tableNames, tableNameAlias);
+      }
+      extractTableNames(((SqlSelect) sqlNode).getWhere(), tableNames, 
tableNameAlias);
+    } else if (sqlNode instanceof SqlJoin) {
+      // Handle SqlJoin query
+      SqlNode left = ((SqlJoin) sqlNode).getLeft();
+      SqlNode right = ((SqlJoin) sqlNode).getRight();
+      if (left instanceof SqlIdentifier) {
+        tableNames.add(getTableName(((SqlIdentifier) left)));
+      } else {
+        extractTableNames(left, tableNames, tableNameAlias);
+      }
+      if (right instanceof SqlIdentifier) {
+        tableNames.add(getTableName(((SqlIdentifier) right)));
+      } else {
+        extractTableNames(right, tableNames, tableNameAlias);
+      }
+    } else if (sqlNode instanceof SqlOrderBy) {
+      // Handle SqlOrderBy query
+      // tableNames.addAll(getTableNames(((SqlOrderBy) sqlNode).query));
+      for (SqlNode node : ((SqlOrderBy) sqlNode).getOperandList()) {
+        extractTableNames(node, tableNames, tableNameAlias);
+      }
+    } else if (sqlNode instanceof SqlBasicCall) {
+      // Handle SqlBasicCall query
+      if (((SqlBasicCall) sqlNode).getOperator() instanceof SqlAsOperator) {
+        SqlNode firstOperand = ((SqlBasicCall) 
sqlNode).getOperandList().get(0);
+        if (firstOperand instanceof SqlIdentifier) {
+          tableNames.add(getTableName((SqlIdentifier) firstOperand));
+        } else {
+          extractTableNames(firstOperand, tableNames, tableNameAlias);
+        }
+        SqlNode secondOperand = ((SqlBasicCall) 
sqlNode).getOperandList().get(1);
+        if (secondOperand instanceof SqlIdentifier) {
+          tableNameAlias.add(getTableName((SqlIdentifier) secondOperand));
+        }
+      } else {
+        for (SqlNode node : ((SqlBasicCall) sqlNode).getOperandList()) {
+          extractTableNames(node, tableNames, tableNameAlias);
+        }
+      }
+    } else if (sqlNode instanceof SqlWith) {
+      // Handle SqlWith query
+      SqlWith sqlWith = (SqlWith) sqlNode;
+      List<SqlNode> withList = sqlWith.withList;
+      // Table names from body, it may contains table alias from WITH clause
+      extractTableNames(sqlWith.body, tableNames, tableNameAlias);
+      // Table alias from WITH clause, should be removed from the final results
+      withList.forEach(
+          sqlWithItem -> tableNames.remove(getTableName(((SqlWithItem) 
sqlWithItem).name)));

Review Comment:
   Should we add them into `tableNameAlias`?



-- 
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