This is an automated email from the ASF dual-hosted git repository.

jackie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new e9beb340ec Add tests for PredicateComparisonRewriter (#14166)
e9beb340ec is described below

commit e9beb340ec05ebe2937bcec4633c64f4424e3336
Author: Yash Mayya <[email protected]>
AuthorDate: Tue Oct 8 06:40:20 2024 +0530

    Add tests for PredicateComparisonRewriter (#14166)
---
 .../apache/pinot/sql/parsers/CalciteSqlParser.java |  14 +-
 .../rewriter/PredicateComparisonRewriterTest.java  | 182 +++++++++++++++++++++
 2 files changed, 195 insertions(+), 1 deletion(-)

diff --git 
a/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java 
b/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java
index 88eea1b027..7ef6151e6e 100644
--- 
a/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java
+++ 
b/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java
@@ -161,6 +161,13 @@ public class CalciteSqlParser {
     return compileToPinotQuery(compileToSqlNodeAndOptions(sql));
   }
 
+  /**
+   * Should only be used for testing query rewriters.
+   */
+  public static PinotQuery compileToPinotQueryWithoutRewrites(String sql) {
+    return compileWithoutRewrite(compileToSqlNodeAndOptions(sql).getSqlNode());
+  }
+
   public static PinotQuery compileToPinotQuery(SqlNodeAndOptions 
sqlNodeAndOptions) {
     // Compile SqlNode into PinotQuery
     PinotQuery pinotQuery = 
compileSqlNodeToPinotQuery(sqlNodeAndOptions.getSqlNode());
@@ -416,6 +423,12 @@ public class CalciteSqlParser {
   }
 
   public static PinotQuery compileSqlNodeToPinotQuery(SqlNode sqlNode) {
+    PinotQuery pinotQuery = compileWithoutRewrite(sqlNode);
+    queryRewrite(pinotQuery);
+    return pinotQuery;
+  }
+
+  private static PinotQuery compileWithoutRewrite(SqlNode sqlNode) {
     PinotQuery pinotQuery = new PinotQuery();
     if (sqlNode instanceof SqlExplain) {
       // Extract sql node for the query
@@ -482,7 +495,6 @@ public class CalciteSqlParser {
       pinotQuery.setOffset(((SqlNumericLiteral) offsetNode).intValue(false));
     }
 
-    queryRewrite(pinotQuery);
     return pinotQuery;
   }
 
diff --git 
a/pinot-common/src/test/java/org/apache/pinot/sql/parsers/rewriter/PredicateComparisonRewriterTest.java
 
b/pinot-common/src/test/java/org/apache/pinot/sql/parsers/rewriter/PredicateComparisonRewriterTest.java
new file mode 100644
index 0000000000..9503b9a336
--- /dev/null
+++ 
b/pinot-common/src/test/java/org/apache/pinot/sql/parsers/rewriter/PredicateComparisonRewriterTest.java
@@ -0,0 +1,182 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pinot.sql.parsers.rewriter;
+
+import org.apache.pinot.common.request.PinotQuery;
+import org.apache.pinot.sql.parsers.CalciteSqlParser;
+import org.apache.pinot.sql.parsers.SqlCompilationException;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertThrows;
+import static org.testng.AssertJUnit.assertTrue;
+
+
+public class PredicateComparisonRewriterTest {
+  PredicateComparisonRewriter _predicateComparisonRewriter = new 
PredicateComparisonRewriter();
+
+  @Test
+  public void testIdentifierPredicateRewrite() {
+    // A query like "select * from table where col1" should be rewritten to 
"select * from table where col1 = true"
+
+    PinotQuery pinotQuery = 
CalciteSqlParser.compileToPinotQueryWithoutRewrites("SELECT * FROM mytable 
WHERE col1");
+    assertTrue(pinotQuery.getFilterExpression().isSetIdentifier());
+
+    PinotQuery rewrittenQuery = 
_predicateComparisonRewriter.rewrite(pinotQuery);
+    
assertEquals(rewrittenQuery.getFilterExpression().getFunctionCall().getOperator(),
 "EQUALS");
+    
assertEquals(rewrittenQuery.getFilterExpression().getFunctionCall().getOperands().size(),
 2);
+    
assertEquals(rewrittenQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getIdentifier().getName(),
+        "col1");
+    Assert.assertTrue(
+        
rewrittenQuery.getFilterExpression().getFunctionCall().getOperands().get(1).getLiteral().getBoolValue());
+    
assertTrue(rewrittenQuery.getFilterExpression().getFunctionCall().getOperands().get(1).getLiteral().getBoolValue());
+  }
+
+  @Test
+  public void testFunctionPredicateRewrite() {
+    // A query like "select col1 from table where startsWith(col1, 'myStr') 
AND col2 > 10" should be rewritten to
+    // "select col1 from table where startsWith(col1, 'myStr') = true AND col2 
> 10"
+
+    PinotQuery pinotQuery = 
CalciteSqlParser.compileToPinotQueryWithoutRewrites(
+        "SELECT col1 FROM mytable WHERE startsWith(col1, 'myStr') AND col2 > 
10;");
+    
assertEquals(pinotQuery.getFilterExpression().getFunctionCall().getOperator(), 
"AND");
+    
assertEquals(pinotQuery.getFilterExpression().getFunctionCall().getOperands().size(),
 2);
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperator(),
+        "startswith");
+
+    PinotQuery rewrittenQuery = 
_predicateComparisonRewriter.rewrite(pinotQuery);
+    
assertEquals(rewrittenQuery.getFilterExpression().getFunctionCall().getOperator(),
 "AND");
+    
assertEquals(rewrittenQuery.getFilterExpression().getFunctionCall().getOperands().size(),
 2);
+    assertEquals(
+        
rewrittenQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperator(),
+        "EQUALS");
+    assertEquals(
+        
rewrittenQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands()
+            .size(), 2);
+    assertEquals(
+        
rewrittenQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands()
+            .get(0).getFunctionCall().getOperator(), "startswith");
+    assertTrue(
+        
rewrittenQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands()
+            .get(1).getLiteral().getBoolValue());
+  }
+
+  @Test
+  public void testFilterPredicateLiteralIdentifierSwap() {
+    // Filters like '10 = col1' should be rewritten to 'col1 = 10'
+
+    PinotQuery pinotQuery =
+        CalciteSqlParser.compileToPinotQueryWithoutRewrites("SELECT * FROM 
mytable WHERE 10 = col1 OR 10 < col2;");
+    
assertEquals(pinotQuery.getFilterExpression().getFunctionCall().getOperator(), 
"OR");
+    
assertEquals(pinotQuery.getFilterExpression().getFunctionCall().getOperands().size(),
 2);
+    
assertTrue(pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).isSetFunctionCall());
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperator(),
+        "EQUALS");
+    assertTrue(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands().get(0)
+            .isSetLiteral());
+    assertTrue(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands().get(1)
+            .isSetIdentifier());
+
+    PinotQuery rewrittenQuery = 
_predicateComparisonRewriter.rewrite(pinotQuery);
+    
assertEquals(rewrittenQuery.getFilterExpression().getFunctionCall().getOperator(),
 "OR");
+    
assertEquals(rewrittenQuery.getFilterExpression().getFunctionCall().getOperands().size(),
 2);
+
+    assertTrue(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands().get(0)
+            .isSetIdentifier());
+    assertTrue(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands().get(1)
+            .isSetLiteral());
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperator(),
+        "EQUALS");
+    assertTrue(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(1).getFunctionCall().getOperands().get(0)
+            .isSetIdentifier());
+    assertTrue(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(1).getFunctionCall().getOperands().get(1)
+            .isSetLiteral());
+    // Operator should be flipped
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(1).getFunctionCall().getOperator(),
+        "GREATER_THAN");
+  }
+
+  @Test
+  public void testFilterPredicateColumnComparisonRewrite() {
+    // Filters like 'col1 = col2' should be rewritten to 'col1 - col2 = 0'
+
+    PinotQuery pinotQuery =
+        CalciteSqlParser.compileToPinotQueryWithoutRewrites("SELECT * FROM 
mytable WHERE col1 = col2 AND col3 < col4;");
+    
assertEquals(pinotQuery.getFilterExpression().getFunctionCall().getOperator(), 
"AND");
+    
assertEquals(pinotQuery.getFilterExpression().getFunctionCall().getOperands().size(),
 2);
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperator(),
+        "EQUALS");
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands().get(0)
+            .getIdentifier().getName(), "col1");
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands().get(1)
+            .getIdentifier().getName(), "col2");
+
+    PinotQuery rewrittenQuery = 
_predicateComparisonRewriter.rewrite(pinotQuery);
+    
assertEquals(rewrittenQuery.getFilterExpression().getFunctionCall().getOperator(),
 "AND");
+    
assertEquals(rewrittenQuery.getFilterExpression().getFunctionCall().getOperands().size(),
 2);
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperator(),
+        "EQUALS");
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands().get(0)
+            .getFunctionCall().getOperator(), "minus");
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands().get(0)
+            .getFunctionCall().getOperands().get(0).getIdentifier().getName(), 
"col1");
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(0).getFunctionCall().getOperands().get(0)
+            .getFunctionCall().getOperands().get(1).getIdentifier().getName(), 
"col2");
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(1).getFunctionCall().getOperands().get(1)
+            .getLiteral().getIntValue(), 0);
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(1).getFunctionCall().getOperator(),
+        "LESS_THAN");
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(1).getFunctionCall().getOperands().get(0)
+            .getFunctionCall().getOperator(), "minus");
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(1).getFunctionCall().getOperands().get(0)
+            .getFunctionCall().getOperands().get(0).getIdentifier().getName(), 
"col3");
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(1).getFunctionCall().getOperands().get(0)
+            .getFunctionCall().getOperands().get(1).getIdentifier().getName(), 
"col4");
+    assertEquals(
+        
pinotQuery.getFilterExpression().getFunctionCall().getOperands().get(1).getFunctionCall().getOperands().get(1)
+            .getLiteral().getIntValue(), 0);
+
+    PinotQuery betweenQuery =
+        CalciteSqlParser.compileToPinotQueryWithoutRewrites("SELECT * FROM 
mytable WHERE col1 BETWEEN col2 AND col3");
+    assertThrows(SqlCompilationException.class, () -> 
_predicateComparisonRewriter.rewrite(betweenQuery));
+  }
+}


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

Reply via email to