Taewoo Kim has submitted this change and it was merged.

Change subject: AQLPlus Refactoring 1: add a new rule controller
......................................................................


AQLPlus Refactoring 1: add a new rule controller

 - Add a new rule controller that is to be used for FuzzyJoinRuleCollection.
   If the first rule is not fired in the first iteration, no additional rules
   in the given collection will be checked. If the first rule is fired, then
   it behaves like SequentialFixpointRuleController - run rules sequentially
   until one iteration over all rules produces no change.
 - This rule controller is added to make sure that fuzzy-join framework does
   not interfere with non-fuzzy-join queries.

Change-Id: I2742e891339e5aba37a00f77d7f18cb3c09bcfe2
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1432
Reviewed-by: Yingyi Bu <[email protected]>
Sonar-Qube: Jenkins <[email protected]>
Tested-by: Jenkins <[email protected]>
BAD: Jenkins <[email protected]>
Integration-Tests: Jenkins <[email protected]>
---
M 
hyracks-fullstack/algebricks/algebricks-common/src/main/java/org/apache/hyracks/algebricks/common/exceptions/AlgebricksException.java
M hyracks-fullstack/algebricks/algebricks-compiler/pom.xml
A 
hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/rewriter/rulecontrollers/SequentialFirstRuleCheckFixpointRuleController.java
A 
hyracks-fullstack/algebricks/algebricks-compiler/src/test/java/org/apache/hyracks/algebricks/compiler/rewriter/rulecontrollers/SequentialFirstRuleCheckFixpointRuleControllerTest.java
M 
hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
M 
hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
6 files changed, 247 insertions(+), 5 deletions(-)

Approvals:
  Yingyi Bu: Looks good to me, approved
  Jenkins: Verified; No violations found; No violations found; Verified



diff --git 
a/hyracks-fullstack/algebricks/algebricks-common/src/main/java/org/apache/hyracks/algebricks/common/exceptions/AlgebricksException.java
 
b/hyracks-fullstack/algebricks/algebricks-common/src/main/java/org/apache/hyracks/algebricks/common/exceptions/AlgebricksException.java
index 6e53e2a..92bc076 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-common/src/main/java/org/apache/hyracks/algebricks/common/exceptions/AlgebricksException.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-common/src/main/java/org/apache/hyracks/algebricks/common/exceptions/AlgebricksException.java
@@ -20,6 +20,7 @@
 
 import java.io.Serializable;
 
+import org.apache.hyracks.api.exceptions.ErrorCode;
 import org.apache.hyracks.api.util.ErrorMessageUtil;
 
 public class AlgebricksException extends Exception {
@@ -41,6 +42,10 @@
         this.params = params;
     }
 
+    public static AlgebricksException create(int errorCode, Serializable... 
params) {
+        return new AlgebricksException(ErrorCode.HYRACKS, errorCode, 
ErrorCode.getErrorMessage(errorCode), params);
+    }
+
     public AlgebricksException(String message) {
         this(ErrorMessageUtil.NONE, UNKNOWN, message, null, null);
     }
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/pom.xml 
b/hyracks-fullstack/algebricks/algebricks-compiler/pom.xml
index 951fe0f..505b268 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/pom.xml
+++ b/hyracks-fullstack/algebricks/algebricks-compiler/pom.xml
@@ -66,5 +66,34 @@
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <version>1.10.19</version>
+      <scope>test</scope>
+    </dependency>
+   <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+      <version>1.6.6</version>
+      <scope>test</scope>
+   </dependency>
+   <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-core</artifactId>
+      <version>1.6.6</version>
+      <scope>test</scope>
+   </dependency>
+   <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+      <version>1.6.6</version>
+      <scope>test</scope>
+   </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
diff --git 
a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/rewriter/rulecontrollers/SequentialFirstRuleCheckFixpointRuleController.java
 
b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/rewriter/rulecontrollers/SequentialFirstRuleCheckFixpointRuleController.java
new file mode 100644
index 0000000..9446756
--- /dev/null
+++ 
b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/rewriter/rulecontrollers/SequentialFirstRuleCheckFixpointRuleController.java
@@ -0,0 +1,91 @@
+/*
+ * 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.hyracks.algebricks.compiler.rewriter.rulecontrollers;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.rewriter.base.AbstractRuleController;
+import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
+import org.apache.hyracks.api.exceptions.ErrorCode;
+
+/**
+ * If the first rule in the given collection is fired during the first 
iteration, it also runs the other rules
+ * sequentially (round-robin) until one iteration over all rules produces no 
change. Except the case where the first
+ * rule in the first iteration fails, all rules will be checked for each 
iteration.
+ * An example scenario:
+ * Suppose there are three rules - R1, R2, and R3.
+ * During the first iteration, if R1, the first rule, is not fired, then R2 
and R3 will not be checked.
+ * If R1, the first rule, is fired, then R2 and R3 will be checked. Since the 
first iteration returns at least one true
+ * (the first rule), there will be an another iteration. In the second 
iteration, we don't care whether R1 is fired or
+ * not. This enforcement of 'first rule returns true' check is only executed 
in the first iteration.
+ * So, if any of rules in the collection (R1, R2, and R3) is fired, then there 
will be another iteration(s) until
+ * an iteration doesn't produce any change (no true from all rules).
+ */
+public class SequentialFirstRuleCheckFixpointRuleController extends 
AbstractRuleController {
+
+    private boolean fullDfs;
+
+    public SequentialFirstRuleCheckFixpointRuleController(boolean fullDfs) {
+        super();
+        this.fullDfs = fullDfs;
+    }
+
+    @Override
+    public boolean rewriteWithRuleCollection(Mutable<ILogicalOperator> root,
+            Collection<IAlgebraicRewriteRule> ruleCollection) throws 
AlgebricksException {
+        List<IAlgebraicRewriteRule> rules;
+
+        // This rule controller can only be applied for a list since it needs 
to enforce the "first" rule check.
+        if (ruleCollection instanceof List) {
+            rules = (List<IAlgebraicRewriteRule>) ruleCollection;
+        } else {
+            throw 
AlgebricksException.create(ErrorCode.COMPILATION_RULECOLLECTION_NOT_INSTANCE_OF_LIST,
+                    this.getClass().getName());
+        }
+
+        if (rules.isEmpty()) {
+            return false;
+        }
+
+        boolean anyRuleFired = false;
+        boolean anyChange;
+        boolean firstRuleChecked = false;
+        do {
+            anyChange = false;
+            for (int i = 0; i < rules.size(); i++) {
+                boolean ruleFired = rewriteOperatorRef(root, rules.get(i), 
true, fullDfs);
+                // If the first rule returns false in the first iteration, 
stops applying the rules at all.
+                if (!firstRuleChecked && i == 0 && !ruleFired) {
+                    return ruleFired;
+                }
+                if (ruleFired) {
+                    anyChange = true;
+                    anyRuleFired = true;
+                }
+            }
+            firstRuleChecked = true;
+        } while (anyChange);
+
+        return anyRuleFired;
+    }
+}
diff --git 
a/hyracks-fullstack/algebricks/algebricks-compiler/src/test/java/org/apache/hyracks/algebricks/compiler/rewriter/rulecontrollers/SequentialFirstRuleCheckFixpointRuleControllerTest.java
 
b/hyracks-fullstack/algebricks/algebricks-compiler/src/test/java/org/apache/hyracks/algebricks/compiler/rewriter/rulecontrollers/SequentialFirstRuleCheckFixpointRuleControllerTest.java
new file mode 100644
index 0000000..339cb15
--- /dev/null
+++ 
b/hyracks-fullstack/algebricks/algebricks-compiler/src/test/java/org/apache/hyracks/algebricks/compiler/rewriter/rulecontrollers/SequentialFirstRuleCheckFixpointRuleControllerTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.hyracks.algebricks.compiler.rewriter.rulecontrollers;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
+import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ SequentialFirstRuleCheckFixpointRuleController.class, 
AbstractLogicalOperator.class })
+public class SequentialFirstRuleCheckFixpointRuleControllerTest {
+
+    @Test
+    public void testRewriteWithRuleCollection() throws Exception {
+        SequentialFirstRuleCheckFixpointRuleController ruleController =
+                new SequentialFirstRuleCheckFixpointRuleController(true);
+
+        // Specifies three rules - R1, R2, and R3.
+        IAlgebraicRewriteRule firstRule = mock(IAlgebraicRewriteRule.class);
+        IAlgebraicRewriteRule secondRule = mock(IAlgebraicRewriteRule.class);
+        IAlgebraicRewriteRule thirdRule = mock(IAlgebraicRewriteRule.class);
+        List<IAlgebraicRewriteRule> ruleList = new LinkedList<>();
+        ruleList.add(firstRule);
+        ruleList.add(secondRule);
+        ruleList.add(thirdRule);
+
+        @SuppressWarnings("unchecked")
+        Mutable<ILogicalOperator> root = PowerMockito.mock(Mutable.class);
+        AbstractLogicalOperator rootOp = 
PowerMockito.mock(AbstractLogicalOperator.class);
+        List<Mutable<ILogicalOperator>> emptyList = new ArrayList<>();
+        PowerMockito.when(root.getValue()).thenReturn(rootOp);
+        PowerMockito.when(rootOp.getInputs()).thenReturn(emptyList);
+
+        // Case 1: the first rule returns true in the first iteration.
+        //  Iteration1: R1 true, R2 false, R3 false
+        //  Iteration2: R1 false, R2 false, R3 false
+        PowerMockito.when(firstRule.rewritePre(any(), 
any())).thenReturn(true).thenReturn(false);
+        PowerMockito.when(secondRule.rewritePre(any(), 
any())).thenReturn(false);
+        PowerMockito.when(thirdRule.rewritePre(any(), 
any())).thenReturn(false);
+        ruleController.rewriteWithRuleCollection(root, ruleList);
+        // The count should be two for all rules.
+        verify(firstRule, times(2)).rewritePre(any(), any());
+        verify(secondRule, times(2)).rewritePre(any(), any());
+        verify(thirdRule, times(2)).rewritePre(any(), any());
+
+        // Case 2: the first rule returns false in the first iteration.
+        //  Iteration1: R1 false (R2 and R3 should not be invoked.)
+        reset(firstRule);
+        reset(secondRule);
+        reset(thirdRule);
+        PowerMockito.when(firstRule.rewritePre(any(), 
any())).thenReturn(false);
+        PowerMockito.when(secondRule.rewritePre(any(), 
any())).thenReturn(true);
+        PowerMockito.when(thirdRule.rewritePre(any(), any())).thenReturn(true);
+        ruleController.rewriteWithRuleCollection(root, ruleList);
+        // The count should be one for the first rule.
+        verify(firstRule, times(1)).rewritePre(any(), any());
+        verify(secondRule, times(0)).rewritePre(any(), any());
+        verify(thirdRule, times(0)).rewritePre(any(), any());
+
+        // Case 3: a mixture of returning true/false.
+        //  Iteration1: R1 true, R2 true, R3 false
+        //  Iteration2: R1 false, R2 true, R3 false
+        //  Iteration3: R1 false, R2 false, R3 false
+        // So, the iteration should be stopped after the iteration 3.
+        reset(firstRule);
+        reset(secondRule);
+        reset(thirdRule);
+        PowerMockito.when(firstRule.rewritePre(any(), 
any())).thenReturn(true).thenReturn(false);
+        PowerMockito.when(secondRule.rewritePre(any(), 
any())).thenReturn(true).thenReturn(true).thenReturn(false);
+        PowerMockito.when(thirdRule.rewritePre(any(), 
any())).thenReturn(false);
+        ruleController.rewriteWithRuleCollection(root, ruleList);
+        // The count should be three for all rules.
+        verify(firstRule, times(3)).rewritePre(any(), any());
+        verify(secondRule, times(3)).rewritePre(any(), any());
+        verify(thirdRule, times(3)).rewritePre(any(), any());
+    }
+
+}
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
index 888f82a..5a67188 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/exceptions/ErrorCode.java
@@ -25,7 +25,10 @@
 import org.apache.hyracks.api.util.ErrorMessageUtil;
 
 /**
- * A registry of runtime error codes
+ * A registry of runtime/compile error codes
+ * Error code:
+ * 0 --- 999: runtime errors
+ * 1000 ---- 1999: compilation errors
  */
 public class ErrorCode {
     private static final String RESOURCE_PATH = "errormsg" + File.separator + 
"en.properties";
@@ -36,6 +39,7 @@
     public static final int FAILURE_ON_NODE = 3;
     public static final int 
RUNTIME_FILE_WITH_ABSOULTE_PATH_NOT_WITHIN_ANY_IO_DEVICE = 4;
     public static final int RUNTIME_FULLTEXT_PHRASE_FOUND = 5;
+    public static final int COMPILATION_RULECOLLECTION_NOT_INSTANCE_OF_LIST = 
1001;
 
     // Loads the map that maps error codes to error message templates.
     private static Map<Integer, String> errorMessageMap = null;
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
index 8ebafef..52367ee 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/resources/errormsg/en.properties
@@ -17,7 +17,9 @@
 # under the License.
 #
 
-1=Unsupported operation %1$s in %2$s operator
-2=Error in processing tuple %1$s in a frame
-4=The file with absolute path %1$s is not within any of the current IO devices
-5=Phrase search in Full-text is not supported. An expression should include 
only one word
\ No newline at end of file
+1 = Unsupported operation %1$s in %2$s operator
+2 = Error in processing tuple %1$s in a frame
+4 = The file with absolute path %1$s is not within any of the current IO 
devices
+5 = Phrase search in Full-text is not supported. An expression should include 
only one word
+
+1001 = The given rule collection %1$s is not an instance of the List class.
\ No newline at end of file

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/1432
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I2742e891339e5aba37a00f77d7f18cb3c09bcfe2
Gerrit-PatchSet: 13
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Taewoo Kim <[email protected]>
Gerrit-Reviewer: Jenkins <[email protected]>
Gerrit-Reviewer: Taewoo Kim <[email protected]>
Gerrit-Reviewer: Yingyi Bu <[email protected]>

Reply via email to