/
QueryModelTreeToGenericPlanNode.java
74 lines (60 loc) · 2.62 KB
/
QueryModelTreeToGenericPlanNode.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*******************************************************************************
* Copyright (c) 2020 Eclipse RDF4J contributors.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.helpers;
import java.util.ArrayDeque;
import org.eclipse.rdf4j.common.annotation.Experimental;
import org.eclipse.rdf4j.common.annotation.InternalUseOnly;
import org.eclipse.rdf4j.query.algebra.BinaryTupleOperator;
import org.eclipse.rdf4j.query.algebra.QueryModelNode;
import org.eclipse.rdf4j.query.algebra.VariableScopeChange;
import org.eclipse.rdf4j.query.explanation.GenericPlanNode;
/**
* Convert TupleExpr (QueryModelNode) to GenericPlanNode for the Query.explain(...) feature.
*/
@Experimental
@InternalUseOnly
public class QueryModelTreeToGenericPlanNode extends AbstractQueryModelVisitor<RuntimeException> {
GenericPlanNode top = null;
QueryModelNode topTupleExpr;
ArrayDeque<GenericPlanNode> deque = new ArrayDeque<>();
public QueryModelTreeToGenericPlanNode(QueryModelNode topTupleExpr) {
this.topTupleExpr = topTupleExpr;
}
public GenericPlanNode getGenericPlanNode() {
return top;
}
// node.getParentNode() is not reliable because nodes are reused and parent is not maintained! This is why we use a
// queue to maintain the effective parent stack.
@Override
protected void meetNode(QueryModelNode node) {
GenericPlanNode genericPlanNode = new GenericPlanNode(node.getSignature());
genericPlanNode.setCostEstimate(node.getCostEstimate());
genericPlanNode.setResultSizeEstimate(node.getResultSizeEstimate());
genericPlanNode.setResultSizeActual(node.getResultSizeActual());
if (node instanceof VariableScopeChange) {
boolean newScope = ((VariableScopeChange) node).isVariableScopeChange();
genericPlanNode.setNewScope(newScope);
}
if (node instanceof BinaryTupleOperator) {
String algorithmName = ((BinaryTupleOperator) node).getAlgorithmName();
genericPlanNode.setAlgorithm(algorithmName);
}
// convert from nanoseconds to milliseconds
genericPlanNode.setTotalTimeActual(node.getTotalTimeNanosActual() / 1_000_000.0);
if (node == topTupleExpr) {
top = genericPlanNode;
}
if (!deque.isEmpty()) {
GenericPlanNode genericParentNode = deque.getLast();
genericParentNode.addPlans(genericPlanNode);
}
deque.addLast(genericPlanNode);
super.meetNode(node);
deque.removeLast();
}
}