Skip to content

Commit d0d5137

Browse files
authored
add rbo rules (#478)
1 parent 24b3831 commit d0d5137

File tree

11 files changed

+388
-10
lines changed

11 files changed

+388
-10
lines changed

geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/com/antgroup/geaflow/dsl/optimize/OptimizeRules.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
import com.antgroup.geaflow.dsl.optimize.rule.GQLAggregateProjectMergeRule;
2626
import com.antgroup.geaflow.dsl.optimize.rule.GQLMatchUnionMergeRule;
2727
import com.antgroup.geaflow.dsl.optimize.rule.GQLProjectRemoveRule;
28+
import com.antgroup.geaflow.dsl.optimize.rule.MatchEdgeLabelFilterRemoveRule;
2829
import com.antgroup.geaflow.dsl.optimize.rule.MatchFilterMergeRule;
30+
import com.antgroup.geaflow.dsl.optimize.rule.MatchIdFilterSimplifyRule;
2931
import com.antgroup.geaflow.dsl.optimize.rule.MatchJoinMatchMergeRule;
3032
import com.antgroup.geaflow.dsl.optimize.rule.MatchJoinTableToGraphMatchRule;
3133
import com.antgroup.geaflow.dsl.optimize.rule.MatchSortToLogicalSortRule;
@@ -102,7 +104,9 @@ public class OptimizeRules {
102104
FilterToMatchRule.INSTANCE,
103105
FilterMatchNodeTransposeRule.INSTANCE,
104106
MatchFilterMergeRule.INSTANCE,
105-
TableScanToGraphRule.INSTANCE
107+
TableScanToGraphRule.INSTANCE,
108+
MatchIdFilterSimplifyRule.INSTANCE,
109+
MatchEdgeLabelFilterRemoveRule.INSTANCE
106110
);
107111

108112
private static final List<RelOptRule> POST_OPTIMIZE_RULES = ImmutableList.of(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package com.antgroup.geaflow.dsl.optimize.rule;
21+
22+
import com.antgroup.geaflow.dsl.calcite.MetaFieldType;
23+
import com.antgroup.geaflow.dsl.calcite.MetaFieldType.MetaField;
24+
import com.antgroup.geaflow.dsl.rel.match.EdgeMatch;
25+
import com.antgroup.geaflow.dsl.rel.match.MatchFilter;
26+
import com.antgroup.geaflow.dsl.rex.PathInputRef;
27+
import java.util.HashSet;
28+
import java.util.List;
29+
import java.util.Set;
30+
import org.apache.calcite.plan.RelOptRule;
31+
import org.apache.calcite.plan.RelOptRuleCall;
32+
import org.apache.calcite.rel.type.RelDataTypeField;
33+
import org.apache.calcite.rex.RexCall;
34+
import org.apache.calcite.rex.RexFieldAccess;
35+
import org.apache.calcite.rex.RexInputRef;
36+
import org.apache.calcite.rex.RexLiteral;
37+
import org.apache.calcite.rex.RexNode;
38+
import org.apache.calcite.sql.SqlKind;
39+
40+
public class MatchEdgeLabelFilterRemoveRule extends RelOptRule {
41+
42+
public static final MatchEdgeLabelFilterRemoveRule INSTANCE = new MatchEdgeLabelFilterRemoveRule();
43+
44+
private MatchEdgeLabelFilterRemoveRule() {
45+
super(operand(MatchFilter.class,
46+
operand(EdgeMatch.class, any())));
47+
}
48+
49+
@Override
50+
public void onMatch(RelOptRuleCall call) {
51+
MatchFilter matchFilter = call.rel(0);
52+
EdgeMatch edgeMatch = call.rel(1);
53+
54+
if (!(matchFilter.getCondition() instanceof RexCall)) {
55+
return;
56+
}
57+
Set<String> labelSetInFilter = new HashSet<>();
58+
RexCall condition = (RexCall) matchFilter.getCondition();
59+
boolean onlyHasLabelFilter = findLabelFilter(labelSetInFilter, condition, edgeMatch);
60+
if (!onlyHasLabelFilter) {
61+
return;
62+
}
63+
64+
Set<String> edgeTypes = edgeMatch.getTypes();
65+
// If all labels in EdgeMatch are included in MatchFilter, we can remove it.
66+
for (String label : edgeTypes) {
67+
if (!labelSetInFilter.contains(label)) {
68+
return;
69+
}
70+
}
71+
72+
call.transformTo(edgeMatch);
73+
}
74+
75+
private boolean findLabelFilter(Set<String> labelSet, RexCall condition, EdgeMatch edgeMatch) {
76+
SqlKind kind = condition.getKind();
77+
if (kind == SqlKind.EQUALS) {
78+
List<RexNode> operands = condition.getOperands();
79+
RexFieldAccess fieldAccess = null;
80+
RexLiteral labelLiteral = null;
81+
if (operands.get(0) instanceof RexFieldAccess && operands.get(1) instanceof RexLiteral) {
82+
fieldAccess = (RexFieldAccess) operands.get(0);
83+
labelLiteral = (RexLiteral) operands.get(1);
84+
} else if (operands.get(1) instanceof RexFieldAccess && operands.get(0) instanceof RexLiteral) {
85+
fieldAccess = (RexFieldAccess) operands.get(1);
86+
labelLiteral = (RexLiteral) operands.get(0);
87+
} else {
88+
return false;
89+
}
90+
RexNode referenceExpr = fieldAccess.getReferenceExpr();
91+
RelDataTypeField field = fieldAccess.getField();
92+
boolean isRefInputEdge = (referenceExpr instanceof PathInputRef
93+
&& ((PathInputRef) referenceExpr).getLabel().equals(edgeMatch.getLabel()))
94+
|| referenceExpr instanceof RexInputRef;
95+
if (isRefInputEdge
96+
&& field.getType() instanceof MetaFieldType
97+
&& ((MetaFieldType) field.getType()).getMetaField() == MetaField.EDGE_TYPE) {
98+
labelSet.add(RexLiteral.stringValue(labelLiteral));
99+
return true;
100+
}
101+
return false;
102+
} else if (kind == SqlKind.OR) {
103+
boolean onlyHasIdFilter = true;
104+
List<RexNode> operands = condition.getOperands();
105+
for (RexNode operand : operands) {
106+
if (operand instanceof RexCall) {
107+
onlyHasIdFilter = onlyHasIdFilter && findLabelFilter(labelSet, (RexCall) operand,
108+
edgeMatch);
109+
} else {
110+
// Has other filter
111+
return false;
112+
}
113+
}
114+
return onlyHasIdFilter;
115+
}
116+
return false;
117+
}
118+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package com.antgroup.geaflow.dsl.optimize.rule;
21+
22+
import com.antgroup.geaflow.common.type.IType;
23+
import com.antgroup.geaflow.dsl.calcite.MetaFieldType;
24+
import com.antgroup.geaflow.dsl.calcite.MetaFieldType.MetaField;
25+
import com.antgroup.geaflow.dsl.common.util.TypeCastUtil;
26+
import com.antgroup.geaflow.dsl.rel.match.MatchFilter;
27+
import com.antgroup.geaflow.dsl.rel.match.VertexMatch;
28+
import com.antgroup.geaflow.dsl.rex.PathInputRef;
29+
import com.antgroup.geaflow.dsl.util.SqlTypeUtil;
30+
import java.util.HashSet;
31+
import java.util.List;
32+
import java.util.Set;
33+
import org.apache.calcite.plan.RelOptRule;
34+
import org.apache.calcite.plan.RelOptRuleCall;
35+
import org.apache.calcite.rel.type.RelDataType;
36+
import org.apache.calcite.rel.type.RelDataTypeField;
37+
import org.apache.calcite.rex.RexCall;
38+
import org.apache.calcite.rex.RexFieldAccess;
39+
import org.apache.calcite.rex.RexInputRef;
40+
import org.apache.calcite.rex.RexLiteral;
41+
import org.apache.calcite.rex.RexNode;
42+
import org.apache.calcite.sql.SqlKind;
43+
44+
public class MatchIdFilterSimplifyRule extends RelOptRule {
45+
46+
public static final MatchIdFilterSimplifyRule INSTANCE = new MatchIdFilterSimplifyRule();
47+
48+
private MatchIdFilterSimplifyRule() {
49+
super(operand(MatchFilter.class,
50+
operand(VertexMatch.class, any())));
51+
}
52+
53+
@Override
54+
public void onMatch(RelOptRuleCall call) {
55+
MatchFilter matchFilter = call.rel(0);
56+
VertexMatch vertexMatch = call.rel(1);
57+
58+
if (!(matchFilter.getCondition() instanceof RexCall)) {
59+
return;
60+
}
61+
RexCall condition = (RexCall) matchFilter.getCondition();
62+
Set<Object> idSet = new HashSet<>();
63+
boolean onLyHasIdFilter = findIdFilter(idSet, condition, vertexMatch);
64+
65+
if (!onLyHasIdFilter) {
66+
return;
67+
}
68+
69+
VertexMatch newVertexMatch = vertexMatch.copy(idSet);
70+
call.transformTo(newVertexMatch);
71+
}
72+
73+
private boolean findIdFilter(Set<Object> idSet, RexCall condition, VertexMatch vertexMatch) {
74+
SqlKind kind = condition.getKind();
75+
if (kind == SqlKind.EQUALS) {
76+
List<RexNode> operands = condition.getOperands();
77+
RexFieldAccess fieldAccess = null;
78+
RexLiteral idLiteral = null;
79+
if (operands.get(0) instanceof RexFieldAccess && operands.get(1) instanceof RexLiteral) {
80+
fieldAccess = (RexFieldAccess) operands.get(0);
81+
idLiteral = (RexLiteral) operands.get(1);
82+
} else if (operands.get(1) instanceof RexFieldAccess && operands.get(0) instanceof RexLiteral) {
83+
fieldAccess = (RexFieldAccess) operands.get(1);
84+
idLiteral = (RexLiteral) operands.get(0);
85+
} else {
86+
return false;
87+
}
88+
RexNode referenceExpr = fieldAccess.getReferenceExpr();
89+
RelDataTypeField field = fieldAccess.getField();
90+
boolean isRefInputVertex = (referenceExpr instanceof PathInputRef
91+
&& ((PathInputRef) referenceExpr).getLabel().equals(vertexMatch.getLabel()))
92+
|| referenceExpr instanceof RexInputRef;
93+
if (isRefInputVertex
94+
&& field.getType() instanceof MetaFieldType
95+
&& ((MetaFieldType) field.getType()).getMetaField() == MetaField.VERTEX_ID) {
96+
RelDataType dataType = ((MetaFieldType) field.getType()).getType();
97+
IType<?> idType = SqlTypeUtil.convertType(dataType);
98+
idSet.add(TypeCastUtil.cast(idLiteral.getValue(), idType));
99+
return true;
100+
}
101+
return false;
102+
} else if (kind == SqlKind.OR) {
103+
boolean onlyHasIdFilter = true;
104+
List<RexNode> operands = condition.getOperands();
105+
for (RexNode operand : operands) {
106+
if (operand instanceof RexCall) {
107+
onlyHasIdFilter = onlyHasIdFilter && findIdFilter(idSet, (RexCall) operand,
108+
vertexMatch);
109+
} else {
110+
// Has other filter
111+
return false;
112+
}
113+
}
114+
return onlyHasIdFilter;
115+
}
116+
return false;
117+
}
118+
}

geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/com/antgroup/geaflow/dsl/rel/match/VertexMatch.java

+25-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.common.collect.ImmutableSet;
3030
import java.util.Collection;
3131
import java.util.Collections;
32+
import java.util.HashSet;
3233
import java.util.List;
3334
import java.util.Objects;
3435
import java.util.Set;
@@ -59,6 +60,8 @@ public class VertexMatch extends AbstractRelNode implements SingleMatchNode, IMa
5960
*/
6061
private RexNode pushDownFilter;
6162

63+
private Set<Object> idSet;
64+
6265
public VertexMatch(RelOptCluster cluster, RelTraitSet traitSet, RelNode input,
6366
String label, Collection<String> vertexTypes, RelDataType nodeType,
6467
PathRecordType pathType) {
@@ -68,6 +71,13 @@ public VertexMatch(RelOptCluster cluster, RelTraitSet traitSet, RelNode input,
6871
public VertexMatch(RelOptCluster cluster, RelTraitSet traitSet, RelNode input,
6972
String label, Collection<String> vertexTypes, RelDataType nodeType,
7073
PathRecordType pathType, RexNode pushDownFilter) {
74+
this(cluster, traitSet, input, label, vertexTypes, nodeType, pathType, pushDownFilter,
75+
new HashSet<>());
76+
}
77+
78+
public VertexMatch(RelOptCluster cluster, RelTraitSet traitSet, RelNode input,
79+
String label, Collection<String> vertexTypes, RelDataType nodeType,
80+
PathRecordType pathType, RexNode pushDownFilter, Set<Object> idSet) {
7181
super(cluster, traitSet);
7282
this.input = input;
7383
this.label = label;
@@ -82,6 +92,7 @@ && match(input).getNodeType().getSqlTypeName() != SqlTypeName.EDGE) {
8292
this.pathType = Objects.requireNonNull(pathType);
8393
this.nodeType = Objects.requireNonNull(nodeType);
8494
this.pushDownFilter = pushDownFilter;
95+
this.idSet = idSet;
8596
}
8697

8798
@Override
@@ -111,32 +122,42 @@ public RexNode getPushDownFilter() {
111122
return pushDownFilter;
112123
}
113124

125+
public Set<Object> getIdSet() {
126+
return idSet;
127+
}
128+
114129
@Override
115130
public SingleMatchNode copy(List<RelNode> inputs, PathRecordType pathSchema) {
116131
assert inputs.size() <= 1;
117132
RelNode input = inputs.isEmpty() ? null : inputs.get(0);
118133
return new VertexMatch(getCluster(), traitSet, input, label,
119-
vertexTypes, nodeType, pathSchema, pushDownFilter);
134+
vertexTypes, nodeType, pathSchema, pushDownFilter, idSet);
120135
}
121136

122137
@Override
123138
public VertexMatch copy(RelTraitSet traitSet, List<RelNode> inputs) {
124139
RelNode input = GQLRelUtil.oneInput(inputs);
125140
return new VertexMatch(getCluster(), getTraitSet(), input,
126-
label, vertexTypes, nodeType, pathType, pushDownFilter);
141+
label, vertexTypes, nodeType, pathType, pushDownFilter, idSet);
127142
}
128143

129144
public VertexMatch copy(RexNode pushDownFilter) {
130145
return new VertexMatch(getCluster(), getTraitSet(), input,
131-
label, vertexTypes, nodeType, pathType, pushDownFilter);
146+
label, vertexTypes, nodeType, pathType, pushDownFilter, idSet);
147+
}
148+
149+
public VertexMatch copy(Set<Object> idSet) {
150+
return new VertexMatch(getCluster(), getTraitSet(), input,
151+
label, vertexTypes, nodeType, pathType, pushDownFilter, idSet);
132152
}
133153

134154
@Override
135155
public RelWriter explainTerms(RelWriter pw) {
136156
return super.explainTerms(pw)
137157
.item("input", input)
138158
.item("label", label)
139-
.item("vertexTypes", vertexTypes);
159+
.item("vertexTypes", vertexTypes)
160+
.item("idSet", idSet);
140161
}
141162

142163
@Override

0 commit comments

Comments
 (0)