deniskuzZ commented on code in PR #5614:
URL: https://github.com/apache/hive/pull/5614#discussion_r1947839147


##########
standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/parser/PartFilterVisitor.java:
##########
@@ -262,4 +262,163 @@ public String 
visitQuotedIdentifier(PartitionFilterParser.QuotedIdentifierContex
     return StringUtils.replace(ctx.getText().substring(1, 
ctx.getText().length() -1 ), "``", "`");
   }
 
+  @Override
+  public TreeNode 
visitConditionIsBoolean(PartitionFilterParser.ConditionIsBooleanContext ctx) {
+    TreeNode exprNode = (TreeNode) visit(ctx.expression());
+    boolean isNegated = ctx.NOT() != null;  // Check for negation (NOT)
+
+    // Retrieve the boolean literal (TRUE/FALSE) and handle negation
+    String booleanLiteral = ctx.booleanLiteral().getText();
+    switch (booleanLiteral.toUpperCase()) {
+      case "TRUE":
+        // For TRUE: return expression directly if not negated, otherwise 
negate it
+        return isNegated ? negateTreeNode(exprNode) : exprNode;
+      case "FALSE":
+        // For FALSE: return negated expression if not negated, otherwise 
return as is
+        return isNegated ? exprNode : negateTreeNode(exprNode);
+      default:
+        throw new ParseCancellationException("Unexpected boolean literal: " + 
booleanLiteral);
+    }
+  }
+
+  private TreeNode negateTreeNode(TreeNode node) {
+    if (node == null) {
+      throw new IllegalArgumentException("TreeNode cannot be null.");
+    }
+
+    if (node instanceof LeafNode) {
+      // If the node is a leaf, negate the operator
+      LeafNode leaf = (LeafNode) node;
+      leaf.operator = invertOperator(leaf.operator);
+      return leaf;
+    } else {
+      // Negate logical operators (AND/OR)
+      LogicalOperator newOperator = (node.getAndOr() == LogicalOperator.AND)
+              ? LogicalOperator.OR
+              : LogicalOperator.AND;
+      TreeNode leftNegated = negateTreeNode(node.getLhs());
+      TreeNode rightNegated = negateTreeNode(node.getRhs());
+      return new TreeNode(leftNegated, newOperator, rightNegated);
+    }
+  }
+
+  private Operator invertOperator(Operator operator) {
+    switch (operator) {
+      case EQUALS:
+        return Operator.NOTEQUALS;
+      case NOTEQUALS:
+      case NOTEQUALS2:
+        return Operator.EQUALS;
+      case GREATERTHAN:
+        return Operator.LESSTHANOREQUALTO;
+      case LESSTHAN:
+        return Operator.GREATERTHANOREQUALTO;
+      case GREATERTHANOREQUALTO:
+        return Operator.LESSTHAN;
+      case LESSTHANOREQUALTO:
+        return Operator.GREATERTHAN;
+      case LIKE:
+        throw new UnsupportedOperationException("LIKE operator inversion is 
not supported.");
+      default:
+        throw new IllegalArgumentException("Unsupported operator for 
inversion: " + operator.getOp());
+    }
+  }
+
+  @Override
+  public TreeNode 
visitWrappedExpressionIsBoolean(PartitionFilterParser.WrappedExpressionIsBooleanContext
 ctx) {
+    // Visit the inner expression and check if "NOT" is used
+    TreeNode innerNode = (TreeNode) visit(ctx.orExpression());
+    boolean isNot = ctx.NOT() != null;
+
+    // Determine the expected boolean value (TRUE/FALSE) and negate if 
necessary
+    boolean expectedValue = 
ctx.booleanLiteral().getText().equalsIgnoreCase("TRUE");
+    if (isNot) expectedValue = !expectedValue;
+
+    // Return the node based on the expected boolean value (negated or not)
+    return expectedValue ? innerNode : negateTree(innerNode);
+  }
+
+  private TreeNode negateTree(TreeNode node) {
+    if (node instanceof LeafNode) {
+      // Negate leaf nodes directly
+      return negateLeafNode((LeafNode) node);
+    } else if (node != null) {
+      // Negate logical nodes (AND/OR) recursively
+      TreeNode negatedLeft = negateTree(node.getLhs());
+      TreeNode negatedRight = negateTree(node.getRhs());
+      LogicalOperator negatedOperator = (node.getAndOr() == 
LogicalOperator.AND)
+              ? LogicalOperator.OR
+              : LogicalOperator.AND;
+      return combineNodes(negatedLeft, negatedOperator, negatedRight);
+    }
+    throw new IllegalArgumentException("Unknown TreeNode type");
+  }
+
+  private LeafNode negateLeafNode(LeafNode leaf) {
+    LeafNode negatedLeaf = new LeafNode();
+    negatedLeaf.keyName = leaf.keyName;
+
+    // Invert the operator for the leaf node
+    negatedLeaf.operator = invertOperator(leaf.operator);
+    negatedLeaf.value = leaf.value;
+    return negatedLeaf;
+  }
+
+  private TreeNode combineNodes(TreeNode lhs, LogicalOperator operator, 
TreeNode rhs) {
+    // Create a logical node combining two child nodes
+    return new TreeNode(lhs, operator, rhs);
+  }
+
+  @Override
+  public TreeNode 
visitInConditionWithBoolean(PartitionFilterParser.InConditionWithBooleanContext 
ctx) {
+    // Extract the values from the constant sequence
+    List<Object> values = visitConstantSeq(ctx.constantSeq());
+
+    // Determine if the condition is a NOT IN by checking the presence of the 
NOT keyword
+    boolean isNotIn = ctx.NOT() != null;
+
+    // Extract the key name (identifier)
+    String keyName = (String) visit(ctx.key);
+
+    // Extract the boolean literal (TRUE or FALSE)
+    boolean isTrue = ctx.booleanLiteral().getText().equalsIgnoreCase("TRUE");
+
+    // If the boolean literal is TRUE, the condition should be IN, otherwise 
NOT IN
+    if (isTrue) {
+      return buildInCondition(keyName, values, isNotIn);
+    } else {
+      return buildInCondition(keyName, values, !isNotIn); // Flip isNotIn for 
FALSE
+    }
+  }
+
+  private TreeNode buildInCondition(String keyName, List<Object> values, 
boolean isNotIn) {
+    // Create nodes based on the values and operator (EQUALS or NOTEQUALS)
+    List<LeafNode> nodes = values.stream()
+            .map(value -> {
+              LeafNode leafNode = new LeafNode();
+              leafNode.keyName = keyName;
+              leafNode.value = value;
+              // Set operator based on whether it is NOT IN or IN
+              leafNode.operator = isNotIn ? Operator.NOTEQUALS : 
Operator.EQUALS;
+              return leafNode;
+            })
+            .collect(Collectors.toList());
+
+    // Combine the nodes using AND for NOT IN and OR for IN
+    return buildInTreeFromNodes(nodes, isNotIn ? LogicalOperator.AND : 
LogicalOperator.OR);
+  }
+
+  private TreeNode buildInTreeFromNodes(List<LeafNode> nodes, LogicalOperator 
operator) {

Review Comment:
   how is that different from `buildTreeFromNodes`?



-- 
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: gitbox-unsubscr...@hive.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: gitbox-unsubscr...@hive.apache.org
For additional commands, e-mail: gitbox-h...@hive.apache.org

Reply via email to