use of org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep in project sqlg by pietermartin.
the class BaseStrategy method handleChooseStep.
private void handleChooseStep(int chooseStepNestedCount, ChooseStep<?, ?, ?> chooseStep, Traversal.Admin<?, ?> traversal, MutableInt pathCount) {
// The currentTreeNode here is the node that will need the left join in the sql generation
this.chooseStepStack.add(this.currentTreeNodeNode);
Preconditions.checkState(this.chooseStepStack.size() == chooseStepNestedCount);
List<? extends Traversal.Admin<?, ?>> globalChildren = chooseStep.getGlobalChildren();
Preconditions.checkState(globalChildren.size() == 2, "ChooseStep's globalChildren must have size 2, one for true and one for false");
ReplacedStep<?, ?> previousReplacedStep = this.sqlgStep.getReplacedSteps().get(this.sqlgStep.getReplacedSteps().size() - 1);
previousReplacedStep.setLeftJoin(true);
Traversal.Admin<?, ?> trueTraversal;
Traversal.Admin<?, ?> a = globalChildren.get(0);
Traversal.Admin<?, ?> b = globalChildren.get(1);
if (a.getSteps().stream().anyMatch(s -> s instanceof IdentityStep<?>)) {
trueTraversal = b;
} else {
trueTraversal = a;
}
List<Step<?, ?>> trueTraversalSteps = new ArrayList(trueTraversal.getSteps());
ListIterator<Step<?, ?>> trueTraversalStepsIterator = trueTraversalSteps.listIterator();
while (trueTraversalStepsIterator.hasNext()) {
Step internalChooseStep = trueTraversalStepsIterator.next();
if (internalChooseStep instanceof VertexStep || internalChooseStep instanceof EdgeVertexStep || internalChooseStep instanceof EdgeOtherVertexStep) {
handleVertexStep(trueTraversalStepsIterator, (AbstractStep<?, ?>) internalChooseStep, pathCount);
// I.e. there was no results for the chooseSteps traversal.
for (int i = chooseStepNestedCount; i < this.chooseStepStack.size(); i++) {
ReplacedStepTree.TreeNode treeNode = this.chooseStepStack.get(i);
this.currentReplacedStep.markAsJoinToLeftJoin();
treeNode.addReplacedStep(this.currentReplacedStep);
}
} else if (internalChooseStep instanceof ChooseStep) {
handleChooseStep(chooseStepNestedCount + 1, (ChooseStep) internalChooseStep, traversal, pathCount);
} else if (internalChooseStep instanceof ComputerAwareStep.EndStep) {
break;
} else {
throw new IllegalStateException("Unhandled step nested in ChooseStep " + internalChooseStep.getClass().getName());
}
}
// In that case it will not be a direct step of the traversal.
if (traversal.getSteps().contains(chooseStep)) {
traversal.removeStep(chooseStep);
}
}
use of org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep in project sqlg by pietermartin.
the class BaseStrategy method handleOrderGlobalSteps.
protected void handleOrderGlobalSteps(ListIterator<Step<?, ?>> iterator, MutableInt pathCount) {
// Collect the OrderGlobalSteps
while (iterator.hasNext()) {
Step<?, ?> step = iterator.next();
if (step instanceof OrderGlobalStep) {
if (optimizable((OrderGlobalStep) step)) {
// add the label if any
for (String label : step.getLabels()) {
this.currentReplacedStep.addLabel(pathCount.getValue() + BaseStrategy.PATH_LABEL_SUFFIX + label);
}
// The step might not be here. For instance if it was nested in a chooseStep where the chooseStep logic already removed the step.
if (this.traversal.getSteps().contains(step)) {
this.traversal.removeStep(step);
}
iterator.previous();
Step previousStep = iterator.previous();
if (previousStep instanceof SelectOneStep) {
SelectOneStep selectOneStep = (SelectOneStep) previousStep;
String key = (String) selectOneStep.getScopeKeys().iterator().next();
this.currentReplacedStep.getSqlgComparatorHolder().setPrecedingSelectOneLabel(key);
List<Pair<Traversal.Admin<?, ?>, Comparator<?>>> comparators = ((OrderGlobalStep) step).getComparators();
// get the step for the label
Optional<ReplacedStep<?, ?>> labeledReplacedStep = this.sqlgStep.getReplacedSteps().stream().filter(r -> {
Set<String> labels = r.getLabels();
for (String label : labels) {
String stepLabel = SqlgUtil.originalLabel(label);
if (stepLabel.equals(key)) {
return true;
} else {
return false;
}
}
return false;
}).findAny();
Preconditions.checkState(labeledReplacedStep.isPresent());
ReplacedStep<?, ?> replacedStep = labeledReplacedStep.get();
replacedStep.getSqlgComparatorHolder().setComparators(comparators);
// add a label if the step does not yet have one and is not a leaf node
if (replacedStep.getLabels().isEmpty()) {
replacedStep.addLabel(pathCount.getValue() + BaseStrategy.PATH_LABEL_SUFFIX + BaseStrategy.SQLG_PATH_ORDER_RANGE_LABEL);
}
} else if (previousStep instanceof OptionalStep) {
throw new RuntimeException("not yet implemented");
} else if (previousStep instanceof ChooseStep) {
// The order applies to the current replaced step and the previous ChooseStep
List<Pair<Traversal.Admin<?, ?>, Comparator<?>>> comparators = ((OrderGlobalStep) step).getComparators();
this.currentReplacedStep.getSqlgComparatorHolder().setComparators(comparators);
// add a label if the step does not yet have one and is not a leaf node
if (this.currentReplacedStep.getLabels().isEmpty()) {
this.currentReplacedStep.addLabel(pathCount.getValue() + BaseStrategy.PATH_LABEL_SUFFIX + BaseStrategy.SQLG_PATH_ORDER_RANGE_LABEL);
}
} else {
List<Pair<Traversal.Admin<?, ?>, Comparator<?>>> comparators = ((OrderGlobalStep) step).getComparators();
this.currentReplacedStep.getSqlgComparatorHolder().setComparators(comparators);
// add a label if the step does not yet have one and is not a leaf node
if (this.currentReplacedStep.getLabels().isEmpty()) {
this.currentReplacedStep.addLabel(pathCount.getValue() + BaseStrategy.PATH_LABEL_SUFFIX + BaseStrategy.SQLG_PATH_ORDER_RANGE_LABEL);
}
}
iterator.next();
iterator.next();
} else {
return;
}
} else {
// break on the first step that is not a OrderGlobalStep
iterator.previous();
break;
}
}
}
use of org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep in project sqlg by pietermartin.
the class BaseStrategy method unoptimizableChooseStep.
boolean unoptimizableChooseStep(ChooseStep<?, ?, ?> chooseStep) {
if (!this.chooseStepStack.isEmpty()) {
return true;
}
List<? extends Traversal.Admin<?, ?>> traversalAdmins = chooseStep.getGlobalChildren();
if (traversalAdmins.size() != 2) {
return true;
}
Traversal.Admin<?, ?> predicate = chooseStep.getLocalChildren().get(0);
List<Step> predicateSteps = new ArrayList<>(predicate.getSteps());
if (!(predicate.getSteps().get(predicate.getSteps().size() - 1) instanceof HasNextStep)) {
return true;
}
// Remove the HasNextStep
predicateSteps.remove(predicate.getSteps().size() - 1);
Traversal.Admin<?, ?> globalChildOne = chooseStep.getGlobalChildren().get(0);
List<Step> globalChildOneSteps = new ArrayList<>(globalChildOne.getSteps());
globalChildOneSteps.remove(globalChildOneSteps.size() - 1);
Traversal.Admin<?, ?> globalChildTwo = chooseStep.getGlobalChildren().get(1);
List<Step> globalChildTwoSteps = new ArrayList<>(globalChildTwo.getSteps());
globalChildTwoSteps.remove(globalChildTwoSteps.size() - 1);
boolean hasIdentity = globalChildOne.getSteps().stream().anyMatch(s -> s instanceof IdentityStep);
if (!hasIdentity) {
hasIdentity = globalChildTwo.getSteps().stream().anyMatch(s -> s instanceof IdentityStep);
if (hasIdentity) {
// Identity found check predicate and true are the same
if (!predicateSteps.equals(globalChildOneSteps)) {
return true;
}
} else {
// Identity not found
return true;
}
} else {
// Identity found check predicate and true are the same
if (!predicateSteps.equals(globalChildTwoSteps)) {
return true;
}
}
List<Step> localSteps = predicateSteps.stream().filter(p -> p.getClass().equals(LocalStep.class)).collect(Collectors.toList());
if (!localSteps.isEmpty()) {
return true;
}
List<Step> rangeGlobalSteps = predicateSteps.stream().filter(p -> p.getClass().equals(RangeGlobalStep.class)).collect(Collectors.toList());
if (rangeGlobalSteps.size() > 1) {
return true;
}
if (rangeGlobalSteps.size() > 0) {
Step rangeGlobalStep = rangeGlobalSteps.get(0);
// Only if the rangeGlobalStep is the last step can it be optimized
if (predicateSteps.get(predicateSteps.size() - 1) != rangeGlobalStep) {
return true;
}
}
Traversal.Admin<?, ?> trueTraversal;
Traversal.Admin<?, ?> a = globalChildOne;
Traversal.Admin<?, ?> b = globalChildTwo;
if (a.getSteps().stream().anyMatch(s -> s instanceof IdentityStep<?>)) {
trueTraversal = b;
} else {
trueTraversal = a;
}
List<Step<?, ?>> trueTraversalSteps = new ArrayList(trueTraversal.getSteps());
ListIterator<Step<?, ?>> trueTraversalStepsIterator = trueTraversalSteps.listIterator();
while (trueTraversalStepsIterator.hasNext()) {
Step internalChooseStep = trueTraversalStepsIterator.next();
if (!(internalChooseStep instanceof VertexStep || internalChooseStep instanceof EdgeVertexStep || internalChooseStep instanceof EdgeOtherVertexStep || internalChooseStep instanceof ComputerAwareStep.EndStep || internalChooseStep instanceof ChooseStep || internalChooseStep instanceof HasStep || internalChooseStep instanceof OrderGlobalStep || internalChooseStep instanceof RangeGlobalStep)) {
return true;
}
}
List<Step> chooseSteps = globalChildTwo.getSteps().stream().filter(p -> p.getClass().equals(ChooseStep.class)).collect(Collectors.toList());
for (Step step : chooseSteps) {
if (unoptimizableChooseStep((ChooseStep<?, ?, ?>) step)) {
return true;
}
}
return false;
}
use of org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep in project sqlg by pietermartin.
the class SqlgChooseStepStrategy method apply.
@Override
public void apply(final Traversal.Admin<?, ?> traversal) {
// noinspection OptionalGetWithoutIsPresent
if (!(traversal.getGraph().get() instanceof SqlgGraph)) {
return;
}
List<ChooseStep> chooseSteps = TraversalHelper.getStepsOfAssignableClass(ChooseStep.class, traversal);
for (ChooseStep<S, E, M> chooseStep : chooseSteps) {
Traversal.Admin<S, M> predicateTraversal = chooseStep.getLocalChildren().get(0);
// The predicate branch step is a local traversal.
// As such if it contains a ReducingBarrierStep the SqlgBranchStepBarrier will not work.
List<ReducingBarrierStep> reducingBarrierSteps = TraversalHelper.getStepsOfAssignableClass(ReducingBarrierStep.class, predicateTraversal);
if (!reducingBarrierSteps.isEmpty()) {
continue;
}
if (predicateTraversal.getSteps().get(predicateTraversal.getSteps().size() - 1) instanceof HasNextStep) {
predicateTraversal.removeStep(predicateTraversal.getSteps().get(predicateTraversal.getSteps().size() - 1));
}
SqlgBranchStepBarrier sqlgBranchStepBarrier = new SqlgChooseStepBarrier<>(traversal, predicateTraversal);
for (String label : chooseStep.getLabels()) {
sqlgBranchStepBarrier.addLabel(label);
}
try {
Field traversalOptionsField = chooseStep.getClass().getSuperclass().getDeclaredField("traversalOptions");
traversalOptionsField.setAccessible(true);
Map<M, List<Traversal.Admin<S, E>>> traversalOptions = (Map<M, List<Traversal.Admin<S, E>>>) traversalOptionsField.get(chooseStep);
for (Map.Entry<M, List<Traversal.Admin<S, E>>> entry : traversalOptions.entrySet()) {
for (Traversal.Admin<S, E> admin : entry.getValue()) {
sqlgBranchStepBarrier.addGlobalChildOption(entry.getKey(), admin);
}
}
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
TraversalHelper.replaceStep(chooseStep, sqlgBranchStepBarrier, chooseStep.getTraversal());
}
}
Aggregations