Wail Alkowaileet has uploaded a new change for review.
https://asterix-gerrit.ics.uci.edu/2322
Change subject: [ASTERIXDB-2233][COMP] Factor out common conjunct from disjunct
......................................................................
[ASTERIXDB-2233][COMP] Factor out common conjunct from disjunct
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
- Add a rule to factor out common conjunct from disjunct.
- Additional needed rules:
-- Remove redundant boolean expression
e.g and(a, a)
-- Inline same boolean expressions
e.g and(a, and(b, c))
Change-Id: I97fe7d94276f9206c076ca94814b2fa794107859
---
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
A
asterixdb/asterix-app/src/test/resources/optimizerts/queries/tpch/q19_discounted_revenue.sqlpp
A
asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q19_discounted_revenue.plan
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.1.ddl.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.2.update.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.3.query.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.1.ddl.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.2.update.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.3.query.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.1.ddl.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.2.update.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.3.query.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.1.ddl.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.2.update.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.3.query.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/factor-common-conjunct/factor-common-conjunct.1.adm
A
asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/minimum-disjunct/minimum-disjunct.1.adm
A
asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/redundant-conjunct-expression/redundant-conjunct-expression.1.adm
A
asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/redundant-disjunct-expression/redundant-disjunct-expression.1.adm
M asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
A
hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractConditionExpressionRewriteRule.java
A
hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/FactorCommonConjunctionFromDisjunctionRule.java
A
hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/InlineAndRemoveRedundantBooleanExpressionsRule.java
23 files changed, 948 insertions(+), 0 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/22/2322/1
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
index bd67ed4..6fa746b 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
@@ -97,8 +97,10 @@
import org.apache.hyracks.algebricks.rewriter.rules.ExtractCommonOperatorsRule;
import org.apache.hyracks.algebricks.rewriter.rules.ExtractGbyExpressionsRule;
import
org.apache.hyracks.algebricks.rewriter.rules.ExtractGroupByDecorVariablesRule;
+import
org.apache.hyracks.algebricks.rewriter.rules.FactorCommonConjunctionFromDisjunctionRule;
import
org.apache.hyracks.algebricks.rewriter.rules.FactorRedundantGroupAndDecorVarsRule;
import org.apache.hyracks.algebricks.rewriter.rules.InferTypesRule;
+import
org.apache.hyracks.algebricks.rewriter.rules.InlineAndRemoveRedundantBooleanExpressionsRule;
import
org.apache.hyracks.algebricks.rewriter.rules.InlineAssignIntoAggregateRule;
import
org.apache.hyracks.algebricks.rewriter.rules.InlineSingleReferenceVariablesRule;
import
org.apache.hyracks.algebricks.rewriter.rules.InsertProjectBeforeUnionRule;
@@ -233,6 +235,8 @@
// The following rule should be fired after
PushAggregateIntoNestedSubplanRule because
// pulling invariants out of a subplan will make
PushAggregateIntoGroupby harder.
condPushDownAndJoinInference.add(new
AsterixMoveFreeVariableOperatorOutOfSubplanRule());
+ condPushDownAndJoinInference.add(new
InlineAndRemoveRedundantBooleanExpressionsRule());
+ condPushDownAndJoinInference.add(new
FactorCommonConjunctionFromDisjunctionRule());
return condPushDownAndJoinInference;
}
@@ -306,6 +310,7 @@
planCleanupRules.add(new RemoveCartesianProductWithEmptyBranchRule());
planCleanupRules.add(new InjectTypeCastForSwitchCaseRule());
planCleanupRules.add(new InjectTypeCastForUnionRule());
+ planCleanupRules.add(new
InlineAndRemoveRedundantBooleanExpressionsRule());
// Needs to invoke ByNameToByIndexFieldAccessRule as the last logical
optimization rule because
// some rules can push a FieldAccessByName to a place where the name
it tries to access is in the closed part.
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/tpch/q19_discounted_revenue.sqlpp
b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/tpch/q19_discounted_revenue.sqlpp
new file mode 100644
index 0000000..9cb9951
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/tpch/q19_discounted_revenue.sqlpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright by The Regents of the University of California
+ * Licensed 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 from
+ *
+ * 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.
+ */
+
+drop dataverse tpch if exists;
+create dataverse tpch;
+use tpch;
+
+create type LineItemType as {
+ l_orderkey: int64,
+ l_partkey: int64,
+ l_suppkey: int64,
+ l_linenumber: int32,
+ l_quantity: int32,
+ l_extendedprice: double,
+ l_discount: double,
+ l_tax: double,
+ l_returnflag: string,
+ l_linestatus: string,
+ l_shipdate: string,
+ l_commitdate: string,
+ l_receiptdate: string,
+ l_shipinstruct: string,
+ l_shipmode: string,
+ l_comment: string
+};
+
+create type OrderType as {
+ o_orderkey: int64,
+ o_custkey: int64,
+ o_orderstatus: string,
+ o_totalprice: double,
+ o_orderdate: string,
+ o_orderpriority: string,
+ o_clerk: string,
+ o_shippriority: int32,
+ o_comment: string
+};
+
+create type CustomerType as {
+ c_custkey: int64,
+ c_name: string,
+ c_address: string,
+ c_nationkey: int32,
+ c_phone: string,
+ c_acctbal: double,
+ c_mktsegment: string,
+ c_comment: string
+};
+
+create type PartType as {
+ p_partkey: int64,
+ p_name: string,
+ p_mfgr: string,
+ p_brand: string,
+ p_type: string,
+ p_size: int32,
+ p_container: string,
+ p_retailprice: double,
+ p_comment: string
+};
+
+create type PartSuppType as {
+ ps_partkey: int64,
+ ps_suppkey: int64,
+ ps_availqty: int32,
+ ps_supplycost: double,
+ ps_comment: string
+};
+
+create type SupplierType as {
+ s_suppkey: int64,
+ s_name: string,
+ s_address: string,
+ s_nationkey: int32,
+ s_phone: string,
+ s_acctbal: double,
+ s_comment: string
+};
+
+create type NationType as {
+ n_nationkey: int32,
+ n_name: string,
+ n_regionkey: int32,
+ n_comment: string
+};
+
+create type RegionType as {
+ r_regionkey: int32,
+ r_name: string,
+ r_comment: string
+};
+
+create dataset LineItem(LineItemType) primary key l_orderkey, l_linenumber;
+create dataset Orders(OrderType) primary key o_orderkey;
+create dataset Customer(CustomerType) primary key c_custkey;
+create dataset Part(PartType) primary key p_partkey;
+create dataset Partsupp(PartSuppType) primary key ps_partkey, ps_suppkey;
+create dataset Supplier(SupplierType) primary key s_suppkey;
+create dataset Region(RegionType) primary key r_regionkey;
+create dataset Nation(NationType) primary key n_nationkey;
+
+SELECT VALUE SUM(l.l_extendedprice * (1 - l.l_discount))
+FROM LineItem l
+JOIN Part p
+ON p.p_partkey = l.l_partkey
+ WHERE
+ (
+ p.p_brand = 'Brand#12'
+ AND regexp_contains(p.p_container, 'SM CASE|SM BOX|SM PACK|SM PKG')
+ AND l.l_quantity >= 1 and l.l_quantity <= 11
+ AND p.p_size >= 1 and p.p_size <= 5
+ AND (l.l_shipmode = 'AIR' or l.l_shipmode = 'AIR REG')
+ AND l.l_shipinstruct = 'DELIVER IN PERSON'
+ )
+ OR
+ (
+ p.p_brand = 'Brand#23'
+ AND regexp_contains(p.p_container, 'MED BAG|MED BOX|MED PKG|MED PACK')
+ AND l.l_quantity >= 10 and l.l_quantity <= 20
+ AND p.p_size >= 1 and p.p_size <= 10
+ AND (l.l_shipmode = 'AIR' or l.l_shipmode = 'AIR REG')
+ AND l.l_shipinstruct = 'DELIVER IN PERSON'
+ )
+ OR
+ (
+ p.p_brand = 'Brand#34'
+ AND regexp_contains(p.p_container, 'LG CASE|LG BOX|LG PACK|LG PKG')
+ AND l.l_quantity >= 20 and l.l_quantity <= 30
+ AND p.p_size >= 1 and p.p_size <= 15
+ AND (l.l_shipmode = 'AIR' or l.l_shipmode = 'AIR REG')
+ AND l.l_shipinstruct = 'DELIVER IN PERSON'
+ );
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q19_discounted_revenue.plan
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q19_discounted_revenue.plan
new file mode 100644
index 0000000..78e65be
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q19_discounted_revenue.plan
@@ -0,0 +1,36 @@
+-- DISTRIBUTE_RESULT |UNPARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
+ -- AGGREGATE |UNPARTITIONED|
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- HYBRID_HASH_JOIN [$$105][$$119] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- HYBRID_HASH_JOIN [$$114][$$111] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$114]
|PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE
|PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE
|PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE
|PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE
|PARTITIONED|
+ -- BROADCAST_EXCHANGE |PARTITIONED|
+ -- UNNEST |UNPARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |UNPARTITIONED|
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.1.ddl.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.1.ddl.sqlpp
new file mode 100644
index 0000000..e47dbdc
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.1.ddl.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Factor out common conjunct from disjunct
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
+
+drop dataverse test if exists;
+create dataverse test;
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.2.update.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.2.update.sqlpp
new file mode 100644
index 0000000..b2d7dca
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.2.update.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Factor out common conjunct from disjunct
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.3.query.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.3.query.sqlpp
new file mode 100644
index 0000000..819634a
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/factor-common-conjunct/factor-common-conjunct.3.query.sqlpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Factor out common conjunct from disjunct
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
+
+use test;
+select a, b, c
+from [
+ {"a" : false, "b":false, "c":false},
+ {"a" : false, "b":false, "c":true},
+ {"a" : false, "b":true, "c":false},
+ {"a" : false, "b":true, "c":true},
+ {"a" : true, "b":false, "c":false},
+ {"a" : true, "b":false, "c":true},
+ {"a" : true, "b":true, "c":false},
+ {"a" : true, "b":true, "c":true}
+] as arrayBoolean
+where (a = b and b = c) or (a = b and c);
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.1.ddl.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.1.ddl.sqlpp
new file mode 100644
index 0000000..5097d41
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.1.ddl.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Compute minimum conjunct of disjunct expression
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
+
+drop dataverse test if exists;
+create dataverse test;
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.2.update.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.2.update.sqlpp
new file mode 100644
index 0000000..5c270e1
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.2.update.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Compute minimum conjunct of disjunct expression
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.3.query.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.3.query.sqlpp
new file mode 100644
index 0000000..9361b01
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/minimum-disjunct/minimum-disjunct.3.query.sqlpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Compute minimum conjunct of disjunct expression
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
+
+use test;
+select a, b, c
+from [
+ {"a" : false, "b":false, "c":false},
+ {"a" : false, "b":false, "c":true},
+ {"a" : false, "b":true, "c":false},
+ {"a" : false, "b":true, "c":true},
+ {"a" : true, "b":false, "c":false},
+ {"a" : true, "b":false, "c":true},
+ {"a" : true, "b":true, "c":false},
+ {"a" : true, "b":true, "c":true}
+] as arrayBoolean
+where (a and b) or (a and b and c);
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.1.ddl.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.1.ddl.sqlpp
new file mode 100644
index 0000000..3a81a27
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.1.ddl.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Remove redundant boolean expression
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
+
+drop dataverse test if exists;
+create dataverse test;
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.2.update.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.2.update.sqlpp
new file mode 100644
index 0000000..448b47d
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.2.update.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Remove redundant boolean expression
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.3.query.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.3.query.sqlpp
new file mode 100644
index 0000000..ca143f5
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-conjunct-expression/redundant-conjunct-expression.3.query.sqlpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Remove redundant boolean expression
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
+
+use test;
+select a, b, c
+from [
+ {"a" : false, "b":false, "c":false},
+ {"a" : false, "b":false, "c":true},
+ {"a" : false, "b":true, "c":false},
+ {"a" : false, "b":true, "c":true},
+ {"a" : true, "b":false, "c":false},
+ {"a" : true, "b":false, "c":true},
+ {"a" : true, "b":true, "c":false},
+ {"a" : true, "b":true, "c":true}
+] as arrayBoolean
+where a and a;
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.1.ddl.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.1.ddl.sqlpp
new file mode 100644
index 0000000..3a81a27
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.1.ddl.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Remove redundant boolean expression
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
+
+drop dataverse test if exists;
+create dataverse test;
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.2.update.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.2.update.sqlpp
new file mode 100644
index 0000000..448b47d
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.2.update.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Remove redundant boolean expression
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.3.query.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.3.query.sqlpp
new file mode 100644
index 0000000..2cab64f
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/condition/redundant-disjunct-expression/redundant-disjunct-expression.3.query.sqlpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+/*
+ * Description : Remove redundant boolean expression
+ * Expected Res : Success
+ * Date : 23 Jan 2017
+ */
+
+use test;
+select a, b, c
+from [
+ {"a" : false, "b":false, "c":false},
+ {"a" : false, "b":false, "c":true},
+ {"a" : false, "b":true, "c":false},
+ {"a" : false, "b":true, "c":true},
+ {"a" : true, "b":false, "c":false},
+ {"a" : true, "b":false, "c":true},
+ {"a" : true, "b":true, "c":false},
+ {"a" : true, "b":true, "c":true}
+] as arrayBoolean
+where a or a;
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/factor-common-conjunct/factor-common-conjunct.1.adm
b/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/factor-common-conjunct/factor-common-conjunct.1.adm
new file mode 100644
index 0000000..8268539
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/factor-common-conjunct/factor-common-conjunct.1.adm
@@ -0,0 +1,3 @@
+{ "a": false, "b": false, "c": false }
+{ "a": false, "b": false, "c": true }
+{ "a": true, "b": true, "c": true }
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/minimum-disjunct/minimum-disjunct.1.adm
b/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/minimum-disjunct/minimum-disjunct.1.adm
new file mode 100644
index 0000000..93ee626
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/minimum-disjunct/minimum-disjunct.1.adm
@@ -0,0 +1,2 @@
+{ "a": true, "b": true, "c": false }
+{ "a": true, "b": true, "c": true }
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/redundant-conjunct-expression/redundant-conjunct-expression.1.adm
b/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/redundant-conjunct-expression/redundant-conjunct-expression.1.adm
new file mode 100644
index 0000000..7333e35
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/redundant-conjunct-expression/redundant-conjunct-expression.1.adm
@@ -0,0 +1,4 @@
+{ "a": true, "b": false, "c": false }
+{ "a": true, "b": false, "c": true }
+{ "a": true, "b": true, "c": false }
+{ "a": true, "b": true, "c": true }
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/redundant-disjunct-expression/redundant-disjunct-expression.1.adm
b/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/redundant-disjunct-expression/redundant-disjunct-expression.1.adm
new file mode 100644
index 0000000..7333e35
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/results/condititon/redundant-disjunct-expression/redundant-disjunct-expression.1.adm
@@ -0,0 +1,4 @@
+{ "a": true, "b": false, "c": false }
+{ "a": true, "b": false, "c": true }
+{ "a": true, "b": true, "c": false }
+{ "a": true, "b": true, "c": true }
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 16fa334..9ec7392 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -9438,4 +9438,26 @@
</compilation-unit>
</test-case>
</test-group>
+ <test-group name="condititon">
+ <test-case FilePath="condititon">
+ <compilation-unit name="factor-common-conjunct">
+ <output-dir compare="Text">factor-common-conjunct</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="condititon">
+ <compilation-unit name="minimum-disjunct">
+ <output-dir compare="Text">minimum-disjunct</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="condititon">
+ <compilation-unit name="redundant-conjunct-expression">
+ <output-dir compare="Text">redundant-conjunct-expression</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="condititon">
+ <compilation-unit name="minimum-disjunct">
+ <output-dir compare="Text">redundant-disjunct-expression</output-dir>
+ </compilation-unit>
+ </test-case>
+ </test-group>
</test-suite>
diff --git
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractConditionExpressionRewriteRule.java
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractConditionExpressionRewriteRule.java
new file mode 100644
index 0000000..29b2cd4
--- /dev/null
+++
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractConditionExpressionRewriteRule.java
@@ -0,0 +1,105 @@
+/*
+ * 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.rewriter.rules;
+
+import java.util.ArrayList;
+import java.util.Collections;
+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.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import
org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
+import
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
+import
org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
+import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
+
+public abstract class AbstractConditionExpressionRewriteRule implements
IAlgebraicRewriteRule {
+ private static final List<Mutable<ILogicalExpression>>
EMPTY_EXPRESSION_LIST =
+ Collections.unmodifiableList(new ArrayList<>());
+ private IOptimizationContext context;
+
+ @Override
+ public boolean rewritePost(Mutable<ILogicalOperator> opRef,
IOptimizationContext context)
+ throws AlgebricksException {
+ final ILogicalOperator op = opRef.getValue();
+ final Mutable<ILogicalExpression> condRef;
+ switch (op.getOperatorTag()) {
+ case SELECT:
+ final SelectOperator select = (SelectOperator) op;
+ condRef = select.getCondition();
+ break;
+ case INNERJOIN:
+ case LEFTOUTERJOIN:
+ final AbstractBinaryJoinOperator join =
(AbstractBinaryJoinOperator) op;
+ condRef = join.getCondition();
+ break;
+ default:
+ return false;
+ }
+
+ this.context = context;
+
+ boolean changed = transform(condRef);
+ if (changed) {
+ context.computeAndSetTypeEnvironmentForOperator(op);
+ }
+
+ return changed;
+ }
+
+ protected final AbstractFunctionCallExpression
getFunctionExpression(ILogicalExpression expression) {
+ if (expression.getExpressionTag() !=
LogicalExpressionTag.FUNCTION_CALL) {
+ return null;
+ }
+
+ return (AbstractFunctionCallExpression) expression;
+ }
+
+ protected final List<Mutable<ILogicalExpression>>
getDisjunctiveExpressions(Mutable<ILogicalExpression> exprRef) {
+
+ final AbstractFunctionCallExpression function =
getFunctionExpression(exprRef.getValue());
+ if (function == null ||
!AlgebricksBuiltinFunctions.OR.equals(function.getFunctionIdentifier())) {
+ return EMPTY_EXPRESSION_LIST;
+ }
+
+ return function.getArguments();
+ }
+
+ protected final IFunctionInfo getFunctionInfo(FunctionIdentifier fid) {
+ return context.getMetadataProvider().lookupFunction(fid);
+ }
+
+ /**
+ * Transform condition expression
+ *
+ * @param condRef
+ * SELECT or join condition reference
+ * @return
+ * {@code <code>true</code>} condition has been modified
+ * {@code <code>false</code>} otherwise.
+ */
+ protected abstract boolean transform(Mutable<ILogicalExpression> condRef);
+}
diff --git
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/FactorCommonConjunctionFromDisjunctionRule.java
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/FactorCommonConjunctionFromDisjunctionRule.java
new file mode 100644
index 0000000..3ef86bc
--- /dev/null
+++
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/FactorCommonConjunctionFromDisjunctionRule.java
@@ -0,0 +1,168 @@
+/*
+ * 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.rewriter.rules;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
+import
org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
+
+/**
+ * Factor out common conjuncts from disjuncts.
+ * Example:
+ * (a and b and c) or c -> c
+ * (a and b and c) or (a and b and d) -> a and b and (c or d)
+ */
+public class FactorCommonConjunctionFromDisjunctionRule extends
AbstractConditionExpressionRewriteRule {
+
+ @Override
+ protected boolean transform(Mutable<ILogicalExpression> condRef) {
+
+ final List<Mutable<ILogicalExpression>> disjunctExprs =
getDisjunctiveExpressions(condRef);
+ boolean changed = false;
+ if (!disjunctExprs.isEmpty()) {
+ changed |= computeMinimumDisjunct(disjunctExprs);
+ changed |= factorOutCommonConjunct(disjunctExprs);
+ }
+
+ //Special case: disjuncts have been factored out into a single
expression
+ if (changed && disjunctExprs.size() == 1) {
+ condRef.setValue(disjunctExprs.get(0).getValue());
+ }
+
+ final AbstractFunctionCallExpression function =
getFunctionExpression(condRef.getValue());
+ if (function != null) {
+ for (Mutable<ILogicalExpression> argRef : function.getArguments())
{
+ changed |= transform(argRef);
+ }
+ }
+
+ return changed;
+ }
+
+ private boolean computeMinimumDisjunct(List<Mutable<ILogicalExpression>>
disjunctExprs) {
+ final int originalSize = disjunctExprs.size();
+ int i = 0;
+ while (i < disjunctExprs.size()) {
+ int j = i + 1;
+ while (j < disjunctExprs.size()) {
+ if (containsAll(disjunctExprs.get(i), disjunctExprs.get(j))) {
+ disjunctExprs.remove(i);
+ } else if (containsAll(disjunctExprs.get(j),
disjunctExprs.get(i))) {
+ disjunctExprs.remove(j);
+ } else {
+ j++;
+ }
+ }
+ i++;
+ }
+
+ return disjunctExprs.size() != originalSize;
+ }
+
+ private boolean factorOutCommonConjunct(List<Mutable<ILogicalExpression>>
disjunctExprs) {
+ final int originalSize = disjunctExprs.size();
+ int i = 0;
+ while (i < disjunctExprs.size()) {
+ int j = i + 1;
+ while (j < disjunctExprs.size()) {
+ final ILogicalExpression expr1 =
disjunctExprs.get(i).getValue();
+ final ILogicalExpression expr2 =
disjunctExprs.get(j).getValue();
+ final Mutable<ILogicalExpression> combinedExprs =
extractCommonConjunct(expr1, expr2);
+ if (combinedExprs != null) {
+ disjunctExprs.set(i, combinedExprs);
+ disjunctExprs.remove(j);
+ } else {
+ j++;
+ }
+ }
+ i++;
+ }
+
+ return originalSize != disjunctExprs.size();
+ }
+
+ private boolean containsAll(Mutable<ILogicalExpression> exprRef1,
Mutable<ILogicalExpression> exprRef2) {
+ final AbstractFunctionCallExpression function1 =
getFunctionExpression(exprRef1.getValue());
+
+ if (function1 == null ||
!AlgebricksBuiltinFunctions.AND.equals(function1.getFunctionIdentifier())) {
+ return false;
+ }
+
+ final AbstractFunctionCallExpression function2 =
getFunctionExpression(exprRef2.getValue());
+
+ if (function2 != null &&
AlgebricksBuiltinFunctions.AND.equals(function2.getFunctionIdentifier())) {
+ return
function1.getArguments().containsAll(function2.getArguments());
+ }
+
+ return function1.getArguments().contains(exprRef2);
+ }
+
+ private Mutable<ILogicalExpression>
extractCommonConjunct(ILogicalExpression expr1, ILogicalExpression expr2) {
+ final AbstractFunctionCallExpression function1 =
getFunctionExpression(expr1);
+ final AbstractFunctionCallExpression function2 =
getFunctionExpression(expr2);
+ if (function1 == null || function2 == null
+ ||
!AlgebricksBuiltinFunctions.AND.equals(function1.getFunctionIdentifier())
+ ||
!AlgebricksBuiltinFunctions.AND.equals(function2.getFunctionIdentifier())) {
+ return null;
+ }
+
+ final List<Mutable<ILogicalExpression>> conjList1 =
function1.getArguments();
+ final List<Mutable<ILogicalExpression>> conjList2 =
function2.getArguments();
+ final List<Mutable<ILogicalExpression>> commonConj = new ArrayList<>();
+
+ for (Mutable<ILogicalExpression> conj : conjList1) {
+ if (conjList2.contains(conj)) {
+ commonConj.add(conj);
+ }
+ }
+
+ if (commonConj.isEmpty()) {
+ return null;
+ }
+
+ conjList1.removeAll(commonConj);
+ conjList2.removeAll(commonConj);
+
+ final AbstractFunctionCallExpression innerDisjunct =
+ new
ScalarFunctionCallExpression(getFunctionInfo(AlgebricksBuiltinFunctions.OR));
+ innerDisjunct.getArguments().add(wrapInConjunct(conjList1));
+ innerDisjunct.getArguments().add(wrapInConjunct(conjList2));
+
+ commonConj.add(new MutableObject<>(innerDisjunct));
+ return wrapInConjunct(commonConj);
+ }
+
+ private Mutable<ILogicalExpression>
wrapInConjunct(List<Mutable<ILogicalExpression>> exprs) {
+ if (exprs.size() == 1) {
+ return exprs.get(0);
+ }
+ final AbstractFunctionCallExpression conj =
+ new
ScalarFunctionCallExpression(getFunctionInfo(AlgebricksBuiltinFunctions.AND));
+ conj.getArguments().addAll(exprs);
+
+ return new MutableObject<>(conj);
+ }
+
+}
diff --git
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/InlineAndRemoveRedundantBooleanExpressionsRule.java
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/InlineAndRemoveRedundantBooleanExpressionsRule.java
new file mode 100644
index 0000000..5819041
--- /dev/null
+++
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/InlineAndRemoveRedundantBooleanExpressionsRule.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.rewriter.rules;
+
+import java.util.List;
+
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import
org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+
+/**
+ * Inline and remove redundant boolean expressions
+ *
+ * Inline Example:
+ * and(x, and(y, and(z, w))) -> and(x, y, z, w)
+ *
+ * Remove redundant example:
+ * or(x, y, y) -> or(x, y)
+ */
+public class InlineAndRemoveRedundantBooleanExpressionsRule extends
AbstractConditionExpressionRewriteRule {
+
+ @Override
+ protected boolean transform(Mutable<ILogicalExpression> condRef) {
+ AbstractFunctionCallExpression function =
getFunctionExpression(condRef.getValue());
+ if (function == null) {
+ return false;
+ }
+
+ boolean changed = false;
+ final FunctionIdentifier fid = function.getFunctionIdentifier();
+ if (AlgebricksBuiltinFunctions.AND.equals(fid) ||
AlgebricksBuiltinFunctions.OR.equals(fid)) {
+ changed |= inlineCondititon(function);
+ changed |= removeRedundantExpressions(function.getArguments());
+ }
+
+ if (changed && function.getArguments().size() == 1) {
+ final ILogicalExpression newCond =
function.getArguments().get(0).getValue();
+ condRef.setValue(newCond);
+ transform(condRef);
+ return true;
+ }
+
+ for (Mutable<ILogicalExpression> argRef : function.getArguments()) {
+ changed |= transform(argRef);
+ }
+ return changed;
+ }
+
+ private boolean inlineCondititon(AbstractFunctionCallExpression function) {
+ final FunctionIdentifier fid = function.getFunctionIdentifier();
+ final List<Mutable<ILogicalExpression>> args = function.getArguments();
+
+ int i = 0;
+ boolean changed = false;
+ while (i < args.size()) {
+ final AbstractFunctionCallExpression argFunction =
getFunctionExpression(args.get(i).getValue());
+ if (argFunction != null &&
fid.equals(argFunction.getFunctionIdentifier())) {
+ args.remove(i);
+ args.addAll(i, argFunction.getArguments());
+ changed = true;
+ } else {
+ i++;
+ }
+ }
+
+ return changed;
+ }
+
+ /**
+ * remove redundant boolean expressions
+ *
+ * Example:
+ * and(x, y, y) -> and(x, y)
+ */
+ private boolean
removeRedundantExpressions(List<Mutable<ILogicalExpression>> exprs) {
+ final int originalSize = exprs.size();
+ int i = 0;
+ while (i < exprs.size()) {
+ int j = i + 1;
+ while (j < exprs.size()) {
+ if (exprs.get(i).equals(exprs.get(j))) {
+ exprs.remove(j);
+ } else {
+ j++;
+ }
+ }
+ i++;
+ }
+
+ return exprs.size() != originalSize;
+ }
+
+}
--
To view, visit https://asterix-gerrit.ics.uci.edu/2322
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I97fe7d94276f9206c076ca94814b2fa794107859
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Wail Alkowaileet <[email protected]>