>From Ali Alsuliman <[email protected]>:
Ali Alsuliman has uploaded this change for review. (
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19503 )
Change subject: [ASTERIXDB-3573][COMP] Do not pull predicates out of join
condition
......................................................................
[ASTERIXDB-3573][COMP] Do not pull predicates out of join condition
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
Avoid pulling predicates out of the (inner) join condition into
a separate select operator.
Ext-ref: MB-65642
Change-Id: I4343ef5246b9698c1ffb342dde43515db649b9fc
---
M
asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_started_by/interval_started_by.3.query.plan
M asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q17.plan
M
asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_ended_by/interval_ended_by.3.query.plan
A
asterixdb/asterix-app/src/test/resources/optimizerts/results/keep_pred_in_join.plan
M
hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PullSelectOutOfEqJoin.java
D
asterixdb/asterix-app/src/test/resources/optimizerts/results/pull_select_above_eq_join.plan
M
asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_ends/interval_ends.3.query.plan
M asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q19.plan
M
asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_starts/interval_starts.3.query.plan
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
R
asterixdb/asterix-app/src/test/resources/optimizerts/queries/keep_pred_in_join.sqlpp
R
asterixdb/asterix-app/src/test/resources/optimizerts/queries_sqlpp/keep_pred_in_join.sqlpp
12 files changed, 322 insertions(+), 313 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/03/19503/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 d786e9d..e8182f0 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
@@ -137,7 +137,6 @@
import org.apache.hyracks.algebricks.rewriter.rules.IntroduceProjectsRule;
import
org.apache.hyracks.algebricks.rewriter.rules.IsolateHyracksOperatorsRule;
import org.apache.hyracks.algebricks.rewriter.rules.PopulateResultMetadataRule;
-import org.apache.hyracks.algebricks.rewriter.rules.PullSelectOutOfEqJoin;
import org.apache.hyracks.algebricks.rewriter.rules.PushGroupByIntoSortRule;
import
org.apache.hyracks.algebricks.rewriter.rules.PushMapOperatorDownThroughProductRule;
import
org.apache.hyracks.algebricks.rewriter.rules.PushNestedOrderByUnderPreSortedGroupByRule;
@@ -395,7 +394,6 @@
public static List<IAlgebraicRewriteRule>
buildPhysicalRewritesAllLevelsRuleCollection(
SetAsterixPhysicalOperatorsRule.CostMethodsFactory cmf) {
List<IAlgebraicRewriteRule> physicalRewritesAllLevels = new
LinkedList<>();
- physicalRewritesAllLevels.add(new PullSelectOutOfEqJoin());
physicalRewritesAllLevels.add(new
ExtractBatchableExternalFunctionCallsRule());
//Turned off the following rule for now not to change OptimizerTest
results.
physicalRewritesAllLevels.add(new SetupCommitExtensionOpRule());
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/pull_select_above_eq_join.sqlpp
b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/keep_pred_in_join.sqlpp
similarity index 100%
rename from
asterixdb/asterix-app/src/test/resources/optimizerts/queries/pull_select_above_eq_join.sqlpp
rename to
asterixdb/asterix-app/src/test/resources/optimizerts/queries/keep_pred_in_join.sqlpp
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/queries_sqlpp/pull_select_above_eq_join.sqlpp
b/asterixdb/asterix-app/src/test/resources/optimizerts/queries_sqlpp/keep_pred_in_join.sqlpp
similarity index 100%
rename from
asterixdb/asterix-app/src/test/resources/optimizerts/queries_sqlpp/pull_select_above_eq_join.sqlpp
rename to
asterixdb/asterix-app/src/test/resources/optimizerts/queries_sqlpp/keep_pred_in_join.sqlpp
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q17.plan
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q17.plan
index 1df6122..1f8e277 100644
---
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q17.plan
+++
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q17.plan
@@ -10,103 +10,101 @@
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
aggregate [$$164] <- [agg-local-sql-sum($$141)]
-- AGGREGATE |PARTITIONED|
- select (lt($$150, $$154)) project: [$$141]
- -- STREAM_SELECT |PARTITIONED|
- project ([$$154, $$141, $$150])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$152, $$i_id))
- -- HYBRID_HASH_JOIN [$$i_id][$$152] |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- group by ([$$i_id := $$163]) decor ([]) {
- aggregate [$$154] <-
[agg-global-sql-avg($$162)]
- -- AGGREGATE |LOCAL|
- nested tuple source
- -- NESTED_TUPLE_SOURCE |LOCAL|
- }
- -- PRE_CLUSTERED_GROUP_BY[$$163] |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- group by ([$$163 := $$146]) decor ([]) {
- aggregate [$$162] <-
[agg-local-sql-avg($$122)]
- -- AGGREGATE |LOCAL|
- nested tuple source
- -- NESTED_TUPLE_SOURCE |LOCAL|
- }
- -- SORT_GROUP_BY[$$146] |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$122, $$146])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$156, $$146))
- -- HYBRID_HASH_JOIN [$$146][$$156]
|PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$146]
|PARTITIONED|
- select (like($$i.getField("i_data"),
"%b")) project: [$$146]
- -- STREAM_SELECT |PARTITIONED|
- assign [$$146] <-
[$$i.getField("i_id")]
- -- ASSIGN |PARTITIONED|
- project ([$$i])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE
|PARTITIONED|
- data-scan []<-[$$147, $$i] <-
test.item
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE
|PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE
|PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$156]
|PARTITIONED|
- assign [$$122, $$156] <-
[$$ol1.getField("ol_quantity"), $$ol1.getField("ol_i_id")] project: [$$122,
$$156]
- -- ASSIGN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- replicate
- -- REPLICATE |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE
|PARTITIONED|
- unnest $$ol1 <-
scan-collection($$158) project: [$$ol1]
- -- UNNEST |PARTITIONED|
- assign [$$158] <-
[$$o1.getField("o_orderline")] project: [$$158]
- -- ASSIGN |PARTITIONED|
- project ([$$o1])
- -- STREAM_PROJECT
|PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE
|PARTITIONED|
- data-scan []<-[$$148,
$$o1] <- test.orders
- -- DATASOURCE_SCAN
|PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE
|PARTITIONED|
- empty-tuple-source
- --
EMPTY_TUPLE_SOURCE |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$152] |PARTITIONED|
- assign [$$141, $$152, $$150] <-
[$$ol.getField("ol_amount"), $$ol.getField("ol_i_id"),
$$ol.getField("ol_quantity")] project: [$$141, $$150, $$152]
- -- ASSIGN |PARTITIONED|
- assign [$$ol] <- [$$ol1] project: [$$ol]
- -- ASSIGN |PARTITIONED|
+ project ([$$141])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (and(lt($$150, $$154), eq($$152, $$i_id)))
+ -- HYBRID_HASH_JOIN [$$i_id][$$152] |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ group by ([$$i_id := $$163]) decor ([]) {
+ aggregate [$$154] <- [agg-global-sql-avg($$162)]
+ -- AGGREGATE |LOCAL|
+ nested tuple source
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- PRE_CLUSTERED_GROUP_BY[$$163] |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ group by ([$$163 := $$146]) decor ([]) {
+ aggregate [$$162] <-
[agg-local-sql-avg($$122)]
+ -- AGGREGATE |LOCAL|
+ nested tuple source
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- SORT_GROUP_BY[$$146] |PARTITIONED|
exchange
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- replicate
- -- REPLICATE |PARTITIONED|
+ project ([$$122, $$146])
+ -- STREAM_PROJECT |PARTITIONED|
exchange
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- unnest $$ol1 <- scan-collection($$158)
project: [$$ol1]
- -- UNNEST |PARTITIONED|
- assign [$$158] <-
[$$o1.getField("o_orderline")] project: [$$158]
- -- ASSIGN |PARTITIONED|
- project ([$$o1])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$148, $$o1] <-
test.orders
- -- DATASOURCE_SCAN |PARTITIONED|
+ join (eq($$156, $$146))
+ -- HYBRID_HASH_JOIN [$$146][$$156]
|PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$146]
|PARTITIONED|
+ select (like($$i.getField("i_data"),
"%b")) project: [$$146]
+ -- STREAM_SELECT |PARTITIONED|
+ assign [$$146] <- [$$i.getField("i_id")]
+ -- ASSIGN |PARTITIONED|
+ project ([$$i])
+ -- STREAM_PROJECT |PARTITIONED|
exchange
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE
|PARTITIONED|
+ data-scan []<-[$$147, $$i] <-
test.item
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE
|PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE
|PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$156]
|PARTITIONED|
+ assign [$$122, $$156] <-
[$$ol1.getField("ol_quantity"), $$ol1.getField("ol_i_id")] project: [$$122,
$$156]
+ -- ASSIGN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ replicate
+ -- REPLICATE |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ unnest $$ol1 <-
scan-collection($$158) project: [$$ol1]
+ -- UNNEST |PARTITIONED|
+ assign [$$158] <-
[$$o1.getField("o_orderline")] project: [$$158]
+ -- ASSIGN |PARTITIONED|
+ project ([$$o1])
+ -- STREAM_PROJECT
|PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE
|PARTITIONED|
+ data-scan []<-[$$148,
$$o1] <- test.orders
+ -- DATASOURCE_SCAN
|PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE
|PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE
|PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$152] |PARTITIONED|
+ assign [$$141, $$152, $$150] <-
[$$ol.getField("ol_amount"), $$ol.getField("ol_i_id"),
$$ol.getField("ol_quantity")] project: [$$141, $$150, $$152]
+ -- ASSIGN |PARTITIONED|
+ assign [$$ol] <- [$$ol1] project: [$$ol]
+ -- ASSIGN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ replicate
+ -- REPLICATE |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ unnest $$ol1 <- scan-collection($$158) project:
[$$ol1]
+ -- UNNEST |PARTITIONED|
+ assign [$$158] <-
[$$o1.getField("o_orderline")] project: [$$158]
+ -- ASSIGN |PARTITIONED|
+ project ([$$o1])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$148, $$o1] <-
test.orders
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q19.plan
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q19.plan
index d12f3d6..79884f6 100644
---
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q19.plan
+++
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ch2/ch2_q19.plan
@@ -10,47 +10,45 @@
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
aggregate [$$133] <- [agg-local-sql-sum($$118)]
-- AGGREGATE |PARTITIONED|
- select (or(and(like($$123, "%h"), ge($$122, 7), le($$122, 17),
and($$134, le($$121, 5)), or(eq($$69, 37), eq($$69, 29), eq($$69, 70))),
and(like($$123, "%t"), ge($$122, 16), le($$122, 26), and($$134, le($$121, 10)),
or(eq($$69, 78), eq($$69, 17), eq($$69, 6))), and(like($$123, "%m"), ge($$122,
24), le($$122, 34), and($$134, $$135), or(eq($$69, 91), eq($$69, 95), eq($$69,
15))))) project: [$$118]
- -- STREAM_SELECT |PARTITIONED|
- project ([$$118, $$122, $$69, $$123, $$121, $$135, $$134])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$126, $$127))
- -- HYBRID_HASH_JOIN [$$126][$$127] |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$126] |PARTITIONED|
- assign [$$118, $$122, $$126] <-
[$$ol.getField("ol_amount"), $$ol.getField("ol_quantity"),
$$ol.getField("ol_i_id")] project: [$$118, $$122, $$69, $$126]
- -- ASSIGN |PARTITIONED|
- unnest $$ol <- scan-collection($$129) project: [$$69,
$$ol]
- -- UNNEST |PARTITIONED|
- assign [$$69, $$129] <- [$$o.getField("o_w_id"),
$$o.getField("o_orderline")] project: [$$69, $$129]
- -- ASSIGN |PARTITIONED|
- project ([$$o])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$124, $$o] <- test.orders
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$127] |PARTITIONED|
- select (and($$134, $$135))
- -- STREAM_SELECT |PARTITIONED|
- assign [$$135, $$134] <- [le($$121, 15), ge($$121, 1)]
+ project ([$$118])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (and(or(and(like($$123, "%h"), ge($$122, 7), le($$122,
17), and($$134, le($$121, 5)), or(eq($$69, 37), eq($$69, 29), eq($$69, 70))),
and(like($$123, "%t"), ge($$122, 16), le($$122, 26), and($$134, le($$121, 10)),
or(eq($$69, 78), eq($$69, 17), eq($$69, 6))), and(like($$123, "%m"), ge($$122,
24), le($$122, 34), and($$134, $$135), or(eq($$69, 91), eq($$69, 95), eq($$69,
15)))), eq($$126, $$127)))
+ -- HYBRID_HASH_JOIN [$$126][$$127] |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$126] |PARTITIONED|
+ assign [$$118, $$122, $$126] <-
[$$ol.getField("ol_amount"), $$ol.getField("ol_quantity"),
$$ol.getField("ol_i_id")] project: [$$118, $$122, $$69, $$126]
+ -- ASSIGN |PARTITIONED|
+ unnest $$ol <- scan-collection($$129) project: [$$69,
$$ol]
+ -- UNNEST |PARTITIONED|
+ assign [$$69, $$129] <- [$$o.getField("o_w_id"),
$$o.getField("o_orderline")] project: [$$69, $$129]
-- ASSIGN |PARTITIONED|
- assign [$$123, $$121, $$127] <-
[$$i.getField("i_data"), $$i.getField("i_price"), $$i.getField("i_id")]
project: [$$123, $$121, $$127]
- -- ASSIGN |PARTITIONED|
- project ([$$i])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$125, $$i] <- test.item
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ project ([$$o])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$124, $$o] <- test.orders
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$127] |PARTITIONED|
+ select (and($$134, $$135))
+ -- STREAM_SELECT |PARTITIONED|
+ assign [$$135, $$134] <- [le($$121, 15), ge($$121, 1)]
+ -- ASSIGN |PARTITIONED|
+ assign [$$123, $$121, $$127] <-
[$$i.getField("i_data"), $$i.getField("i_price"), $$i.getField("i_id")]
project: [$$123, $$121, $$127]
+ -- ASSIGN |PARTITIONED|
+ project ([$$i])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$125, $$i] <- test.item
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/keep_pred_in_join.plan
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/keep_pred_in_join.plan
new file mode 100644
index 0000000..c3c6363
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/keep_pred_in_join.plan
@@ -0,0 +1,36 @@
+distribute result [$$35]
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ assign [$$35] <- [{"uid": $$36, "vid": $$37}] project: [$$35]
+ -- ASSIGN |PARTITIONED|
+ project ([$$36, $$37])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (and(neq($$38, $$39), eq($$40, $$41)))
+ -- HYBRID_HASH_JOIN [$$40][$$41] |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$40] |PARTITIONED|
+ assign [$$40, $$38] <- [$$user.getField(1), $$user.getField(2)]
project: [$$36, $$38, $$40]
+ -- ASSIGN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$36, $$user] <-
`pull-select-above-eq-join`.Users
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$41] |PARTITIONED|
+ assign [$$41, $$39] <- [$$visitor.getField(1),
$$visitor.getField(2)] project: [$$37, $$39, $$41]
+ -- ASSIGN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$37, $$visitor] <-
`pull-select-above-eq-join`.Visitors
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/pull_select_above_eq_join.plan
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/pull_select_above_eq_join.plan
deleted file mode 100644
index d603204..0000000
---
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/pull_select_above_eq_join.plan
+++ /dev/null
@@ -1,38 +0,0 @@
-distribute result [$$35]
--- DISTRIBUTE_RESULT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- assign [$$35] <- [{"uid": $$36, "vid": $$37}] project: [$$35]
- -- ASSIGN |PARTITIONED|
- select (neq($$38, $$39)) project: [$$36, $$37]
- -- STREAM_SELECT |PARTITIONED|
- project ([$$36, $$38, $$37, $$39])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$40, $$41))
- -- HYBRID_HASH_JOIN [$$40][$$41] |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$40] |PARTITIONED|
- assign [$$40, $$38] <- [$$user.getField(1),
$$user.getField(2)] project: [$$36, $$38, $$40]
- -- ASSIGN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$36, $$user] <-
`pull-select-above-eq-join`.Users
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$41] |PARTITIONED|
- assign [$$41, $$39] <- [$$visitor.getField(1),
$$visitor.getField(2)] project: [$$37, $$39, $$41]
- -- ASSIGN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$37, $$visitor] <-
`pull-select-above-eq-join`.Visitors
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_ended_by/interval_ended_by.3.query.plan
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_ended_by/interval_ended_by.3.query.plan
index 7e091b3..a131e0a 100644
---
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_ended_by/interval_ended_by.3.query.plan
+++
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_ended_by/interval_ended_by.3.query.plan
@@ -4,39 +4,37 @@
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
assign [$$31] <- [{"staff": $$34, "student": $$35}] project: [$$31]
-- ASSIGN |PARTITIONED|
- select (le($$36, $$37)) project: [$$34, $$35]
- -- STREAM_SELECT |PARTITIONED|
- project ([$$34, $$37, $$35, $$36])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$38, $$39))
- -- HYBRID_HASH_JOIN [$$38][$$39] |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$38] |PARTITIONED|
- assign [$$38, $$37] <- [get-interval-end($$33),
get-interval-start($$33)] project: [$$34, $$37, $$38]
+ project ([$$34, $$35])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (and(le($$36, $$37), eq($$38, $$39)))
+ -- HYBRID_HASH_JOIN [$$38][$$39] |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$38] |PARTITIONED|
+ assign [$$38, $$37] <- [get-interval-end($$33),
get-interval-start($$33)] project: [$$34, $$37, $$38]
+ -- ASSIGN |PARTITIONED|
+ assign [$$33] <- [$$f.getField(2)] project: [$$34, $$33]
-- ASSIGN |PARTITIONED|
- assign [$$33] <- [$$f.getField(2)] project: [$$34, $$33]
- -- ASSIGN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$34, $$f] <- TinyCollege.Staff
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$39] |PARTITIONED|
- assign [$$39, $$36] <- [get-interval-end($$32),
get-interval-start($$32)] project: [$$35, $$36, $$39]
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$34, $$f] <- TinyCollege.Staff
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$39] |PARTITIONED|
+ assign [$$39, $$36] <- [get-interval-end($$32),
get-interval-start($$32)] project: [$$35, $$36, $$39]
+ -- ASSIGN |PARTITIONED|
+ assign [$$32] <- [$$d.getField(2)] project: [$$35, $$32]
-- ASSIGN |PARTITIONED|
- assign [$$32] <- [$$d.getField(2)] project: [$$35, $$32]
- -- ASSIGN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$35, $$d] <- TinyCollege.Students
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$35, $$d] <- TinyCollege.Students
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_ends/interval_ends.3.query.plan
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_ends/interval_ends.3.query.plan
index f14b06a..cde1b87 100644
---
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_ends/interval_ends.3.query.plan
+++
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_ends/interval_ends.3.query.plan
@@ -4,39 +4,37 @@
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
assign [$$31] <- [{"staff": $$34, "student": $$35}] project: [$$31]
-- ASSIGN |PARTITIONED|
- select (le($$36, $$37)) project: [$$34, $$35]
- -- STREAM_SELECT |PARTITIONED|
- project ([$$34, $$36, $$35, $$37])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$38, $$39))
- -- HYBRID_HASH_JOIN [$$38][$$39] |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$38] |PARTITIONED|
- assign [$$38, $$36] <- [get-interval-end($$32),
get-interval-start($$32)] project: [$$34, $$36, $$38]
+ project ([$$34, $$35])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (and(le($$36, $$37), eq($$38, $$39)))
+ -- HYBRID_HASH_JOIN [$$38][$$39] |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$38] |PARTITIONED|
+ assign [$$38, $$36] <- [get-interval-end($$32),
get-interval-start($$32)] project: [$$34, $$36, $$38]
+ -- ASSIGN |PARTITIONED|
+ assign [$$32] <- [$$f.getField(2)] project: [$$34, $$32]
-- ASSIGN |PARTITIONED|
- assign [$$32] <- [$$f.getField(2)] project: [$$34, $$32]
- -- ASSIGN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$34, $$f] <- TinyCollege.Staff
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$39] |PARTITIONED|
- assign [$$39, $$37] <- [get-interval-end($$33),
get-interval-start($$33)] project: [$$35, $$37, $$39]
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$34, $$f] <- TinyCollege.Staff
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$39] |PARTITIONED|
+ assign [$$39, $$37] <- [get-interval-end($$33),
get-interval-start($$33)] project: [$$35, $$37, $$39]
+ -- ASSIGN |PARTITIONED|
+ assign [$$33] <- [$$d.getField(2)] project: [$$35, $$33]
-- ASSIGN |PARTITIONED|
- assign [$$33] <- [$$d.getField(2)] project: [$$35, $$33]
- -- ASSIGN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$35, $$d] <- TinyCollege.Students
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$35, $$d] <- TinyCollege.Students
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_started_by/interval_started_by.3.query.plan
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_started_by/interval_started_by.3.query.plan
index 7e13e56..91fbfb6 100644
---
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_started_by/interval_started_by.3.query.plan
+++
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_started_by/interval_started_by.3.query.plan
@@ -4,39 +4,37 @@
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
assign [$$31] <- [{"staff": $$34, "student": $$35}] project: [$$31]
-- ASSIGN |PARTITIONED|
- select (le($$38, $$39)) project: [$$34, $$35]
- -- STREAM_SELECT |PARTITIONED|
- project ([$$34, $$39, $$35, $$38])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$36, $$37))
- -- HYBRID_HASH_JOIN [$$36][$$37] |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$36] |PARTITIONED|
- assign [$$39, $$36] <- [get-interval-end($$32),
get-interval-start($$32)] project: [$$34, $$36, $$39]
+ project ([$$34, $$35])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (and(eq($$36, $$37), le($$38, $$39)))
+ -- HYBRID_HASH_JOIN [$$36][$$37] |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$36] |PARTITIONED|
+ assign [$$39, $$36] <- [get-interval-end($$32),
get-interval-start($$32)] project: [$$34, $$36, $$39]
+ -- ASSIGN |PARTITIONED|
+ assign [$$32] <- [$$f.getField(2)] project: [$$34, $$32]
-- ASSIGN |PARTITIONED|
- assign [$$32] <- [$$f.getField(2)] project: [$$34, $$32]
- -- ASSIGN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$34, $$f] <- TinyCollege.Staff
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$37] |PARTITIONED|
- assign [$$38, $$37] <- [get-interval-end($$33),
get-interval-start($$33)] project: [$$35, $$37, $$38]
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$34, $$f] <- TinyCollege.Staff
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$37] |PARTITIONED|
+ assign [$$38, $$37] <- [get-interval-end($$33),
get-interval-start($$33)] project: [$$35, $$37, $$38]
+ -- ASSIGN |PARTITIONED|
+ assign [$$33] <- [$$d.getField(2)] project: [$$35, $$33]
-- ASSIGN |PARTITIONED|
- assign [$$33] <- [$$d.getField(2)] project: [$$35, $$33]
- -- ASSIGN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$35, $$d] <- TinyCollege.Students
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$35, $$d] <- TinyCollege.Students
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_starts/interval_starts.3.query.plan
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_starts/interval_starts.3.query.plan
index e0a5afa..25c3cf0 100644
---
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_starts/interval_starts.3.query.plan
+++
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/temporal/interval_joins/interval_starts/interval_starts.3.query.plan
@@ -4,39 +4,37 @@
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
assign [$$31] <- [{"staff": $$34, "student": $$35}] project: [$$31]
-- ASSIGN |PARTITIONED|
- select (le($$38, $$39)) project: [$$34, $$35]
- -- STREAM_SELECT |PARTITIONED|
- project ([$$34, $$38, $$35, $$39])
- -- STREAM_PROJECT |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$36, $$37))
- -- HYBRID_HASH_JOIN [$$36][$$37] |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$36] |PARTITIONED|
- assign [$$38, $$36] <- [get-interval-end($$32),
get-interval-start($$32)] project: [$$34, $$36, $$38]
+ project ([$$34, $$35])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (and(eq($$36, $$37), le($$38, $$39)))
+ -- HYBRID_HASH_JOIN [$$36][$$37] |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$36] |PARTITIONED|
+ assign [$$38, $$36] <- [get-interval-end($$32),
get-interval-start($$32)] project: [$$34, $$36, $$38]
+ -- ASSIGN |PARTITIONED|
+ assign [$$32] <- [$$f.getField(2)] project: [$$34, $$32]
-- ASSIGN |PARTITIONED|
- assign [$$32] <- [$$f.getField(2)] project: [$$34, $$32]
- -- ASSIGN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$34, $$f] <- TinyCollege.Staff
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
- exchange
- -- HASH_PARTITION_EXCHANGE [$$37] |PARTITIONED|
- assign [$$39, $$37] <- [get-interval-end($$33),
get-interval-start($$33)] project: [$$35, $$37, $$39]
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$34, $$f] <- TinyCollege.Staff
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$37] |PARTITIONED|
+ assign [$$39, $$37] <- [get-interval-end($$33),
get-interval-start($$33)] project: [$$35, $$37, $$39]
+ -- ASSIGN |PARTITIONED|
+ assign [$$33] <- [$$d.getField(2)] project: [$$35, $$33]
-- ASSIGN |PARTITIONED|
- assign [$$33] <- [$$d.getField(2)] project: [$$35, $$33]
- -- ASSIGN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$35, $$d] <- TinyCollege.Students
- -- DATASOURCE_SCAN |PARTITIONED|
- exchange
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- empty-tuple-source
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$35, $$d] <- TinyCollege.Students
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PullSelectOutOfEqJoin.java
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PullSelectOutOfEqJoin.java
index 410b2ec..ab2cea7 100644
---
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PullSelectOutOfEqJoin.java
+++
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PullSelectOutOfEqJoin.java
@@ -38,7 +38,14 @@
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
+import org.apache.hyracks.algebricks.rewriter.util.JoinUtils;
+/**
+ * NOTE: This rule is not used (and not needed).
+ * The {@link
JoinUtils#setJoinAlgorithmAndExchangeAlgo(AbstractBinaryJoinOperator, boolean,
IOptimizationContext)} has
+ * been modified so that a hash-join is used even if other non-equality
predicates exist as long as the join condition
+ * contains at least one equality predicate.
+ */
public class PullSelectOutOfEqJoin implements IAlgebraicRewriteRule {
@Override
--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19503
To unsubscribe, or for help writing mail filters, visit
https://asterix-gerrit.ics.uci.edu/settings
Gerrit-Project: asterixdb
Gerrit-Branch: ionic
Gerrit-Change-Id: I4343ef5246b9698c1ffb342dde43515db649b9fc
Gerrit-Change-Number: 19503
Gerrit-PatchSet: 1
Gerrit-Owner: Ali Alsuliman <[email protected]>
Gerrit-MessageType: newchange