in interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/planner/GraphIOProcessor.java [203:442]
private Pattern visit(List<RelNode> sentences, boolean optional) {
RelVisitor visitor =
new RelVisitor() {
PatternVertex lastVisited = null;
@Override
public void visit(RelNode node, int ordinal, @Nullable RelNode parent) {
super.visit(node, ordinal, parent);
if (node instanceof GraphLogicalSource) {
GraphLogicalSource source = (GraphLogicalSource) node;
lastVisited = visitAndAddVertex(source);
} else if (node instanceof GraphLogicalExpand) {
Preconditions.checkArgument(
parent instanceof GraphLogicalGetV,
"there should be a getV operator after expand since edge in"
+ " patten should have two endpoints");
PatternVertex vertex = visitAndAddVertex((GraphLogicalGetV) parent);
visitAndAddEdge((GraphLogicalExpand) node, lastVisited, vertex);
lastVisited = vertex;
} else if (node instanceof GraphLogicalPathExpand) {
Preconditions.checkArgument(
parent instanceof GraphLogicalGetV,
"there should be a getV operator after path expand since"
+ " edge in patten should have two endpoints");
Preconditions.checkArgument(
((GraphLogicalPathExpand) node).getUntilCondition() == null,
"cannot apply optimization if path expand has until"
+ " conditions");
PatternVertex vertex = visitAndAddVertex((GraphLogicalGetV) parent);
visitAndAddPxdEdge(
(GraphLogicalPathExpand) node, lastVisited, vertex);
lastVisited = vertex;
}
if (parent != null
&& (node instanceof GraphLogicalSource
|| node instanceof GraphLogicalGetV)) {
DataValue value = vertexOrEdgeDetails.get(lastVisited);
if (value != null
&& (value.getAlias() == null
|| value.getAlias()
== AliasInference.DEFAULT_NAME)) {
vertexOrEdgeDetails.put(
lastVisited,
new DataValue(
generateAlias(lastVisited), value.getFilter()));
}
}
}
private String generateAlias(PatternVertex vertex) {
return "PATTERN_VERTEX$" + vertex.getId();
}
private PatternVertex visitAndAddVertex(
AbstractBindableTableScan tableScan) {
String alias = tableScan.getAliasName();
PatternVertex existVertex = aliasNameToVertex.get(alias);
RexNode filters = getFilters(tableScan);
if (existVertex == null) {
int vertexId = idGenerator.getAndIncrement();
List<Integer> typeIds =
com.alibaba.graphscope.common.ir.meta.glogue.Utils
.getVertexTypeIds(tableScan);
double selectivity = mq.getSelectivity(tableScan, filters);
existVertex =
(typeIds.size() == 1)
? new SinglePatternVertex(
typeIds.get(0),
vertexId,
new ElementDetails(selectivity))
: new FuzzyPatternVertex(
typeIds,
vertexId,
new ElementDetails(selectivity));
inputPattern.addVertex(existVertex);
if (alias != AliasInference.DEFAULT_NAME) {
aliasNameToVertex.put(alias, existVertex);
}
vertexOrEdgeDetails.put(existVertex, new DataValue(alias, filters));
} else if (filters != null) {
DataValue value = vertexOrEdgeDetails.get(existVertex);
// reset condition
RexNode newCondition =
(value.getFilter() == null)
? filters
: RexUtil.composeConjunction(
builder.getRexBuilder(),
ImmutableList.of(
filters, value.getFilter()));
vertexOrEdgeDetails.put(
existVertex,
new DataValue(
value.getAlias(),
newCondition,
value.getParentAlias()));
}
return existVertex;
}
private PatternEdge visitAndAddEdge(
GraphLogicalExpand expand,
PatternVertex left,
PatternVertex right) {
PatternVertex src, dst;
switch (expand.getOpt()) {
case OUT:
case BOTH:
src = left;
dst = right;
break;
case IN:
default:
src = right;
dst = left;
}
PatternEdge edge = visitEdge(expand, src, dst);
boolean added = inputPattern.addEdge(src, dst, edge);
if (!added) {
throw new UnsupportedOperationException(
"edge "
+ edge
+ " already exists in the pattern, and pattern with"
+ " multi-edges are not supported yet");
}
vertexOrEdgeDetails.put(
edge, new DataValue(expand.getAliasName(), getFilters(expand)));
return edge;
}
private PatternEdge visitAndAddPxdEdge(
GraphLogicalPathExpand pxd,
PatternVertex left,
PatternVertex right) {
GraphLogicalExpand expand = (GraphLogicalExpand) pxd.getExpand();
PatternVertex src, dst;
switch (expand.getOpt()) {
case OUT:
case BOTH:
src = left;
dst = right;
break;
case IN:
default:
src = right;
dst = left;
}
PatternEdge expandEdge = visitEdge(expand, src, dst);
int offset =
(pxd.getOffset() == null)
? 0
: ((RexLiteral) pxd.getOffset())
.getValueAs(Number.class)
.intValue();
int fetch =
(pxd.getFetch() == null)
? (Integer.MAX_VALUE - offset)
: ((RexLiteral) pxd.getFetch())
.getValueAs(Number.class)
.intValue();
GraphPathType pathType =
(GraphPathType)
pxd.getRowType().getFieldList().get(0).getType();
GraphLabelType labelType =
((GraphSchemaType) pathType.getComponentType().getGetVType())
.getLabelType();
List<Integer> innerGetVTypes =
labelType.getLabelsEntry().stream()
.map(k -> k.getLabelId())
.collect(Collectors.toList());
ElementDetails newDetails =
new ElementDetails(
expandEdge.getElementDetails().getSelectivity(),
new PathExpandRange(offset, fetch),
innerGetVTypes,
pxd.getResultOpt(),
pxd.getPathOpt(),
expandEdge.getElementDetails().isOptional());
expandEdge =
(expandEdge instanceof SinglePatternEdge)
? new SinglePatternEdge(
expandEdge.getSrcVertex(),
expandEdge.getDstVertex(),
expandEdge.getEdgeTypeIds().get(0),
expandEdge.getId(),
expandEdge.isBoth(),
newDetails)
: new FuzzyPatternEdge(
expandEdge.getSrcVertex(),
expandEdge.getDstVertex(),
expandEdge.getEdgeTypeIds(),
expandEdge.getId(),
expandEdge.isBoth(),
newDetails);
boolean added = inputPattern.addEdge(src, dst, expandEdge);
if (!added) {
throw new UnsupportedOperationException(
"edge "
+ expandEdge
+ " already exists in the pattern, and pattern with"
+ " multi-edges are not supported yet");
}
vertexOrEdgeDetails.put(
expandEdge,
new DataValue(pxd.getAliasName(), getFilters(expand)));
return expandEdge;
}
private PatternEdge visitEdge(
GraphLogicalExpand expand, PatternVertex src, PatternVertex dst) {
boolean isBoth = expand.getOpt() == GraphOpt.Expand.BOTH;
List<EdgeTypeId> edgeTypeIds =
com.alibaba.graphscope.common.ir.meta.glogue.Utils
.getEdgeTypeIds(expand);
int edgeId = idGenerator.getAndIncrement();
double selectivity = mq.getSelectivity(expand, getFilters(expand));
PatternEdge edge =
(edgeTypeIds.size() == 1)
? new SinglePatternEdge(
src,
dst,
edgeTypeIds.get(0),
edgeId,
isBoth,
new ElementDetails(selectivity, optional))
: new FuzzyPatternEdge(
src,
dst,
edgeTypeIds,
edgeId,
isBoth,
new ElementDetails(selectivity, optional));
return edge;
}
};
for (RelNode sentence : sentences) {
visitor.go(sentence);
}
return inputPattern;
}