use of org.apache.atlas.groovy.GroovyExpression in project incubator-atlas by apache.
the class ExpandOrsOptimization method apply.
@Override
public GroovyExpression apply(GroovyExpression expr, OptimizationContext context) {
setupRangeOptimization(expr, context);
GroovyExpression traveralExpression = moveTransformationsToResultExpression(expr, context);
FunctionGenerator functionGenerator = new FunctionGenerator(factory, context);
GremlinQueryOptimizer.visitCallHierarchy(traveralExpression, functionGenerator);
traveralExpression = functionGenerator.getNewRootExpression();
List<GroovyExpression> bodyExpressions = expandOrs(traveralExpression, context);
//Adds a statement to define the result variable 'v' in the
//groovy script. The variable is declared as a Set. The type
//of the objects in the Set depend on the number of aliases in the Groovy
// expression:
// - 0 or 1 alias : Vertex
// - multiple aliases: Map<String,Vertex>
StatementListExpression result = new StatementListExpression();
context.prependStatement(context.getDefineResultVariableStmt());
for (GroovyExpression bodyExpression : bodyExpressions) {
result.addStatement(bodyExpression);
}
result.addStatement(context.getResultExpression());
return result;
}
use of org.apache.atlas.groovy.GroovyExpression in project incubator-atlas by apache.
the class FunctionGenerator method createFunctionIfNeeded.
/**
* Creates a function whose body goes from the child of parentExpr
* up to (and including) the functionBodyEndExpr.
* @param parentExpr
*/
private void createFunctionIfNeeded(AbstractFunctionExpression parentExpr) {
GroovyExpression potentialFunctionBody = parentExpr.getCaller();
if (creatingFunctionShortensGremlin(potentialFunctionBody)) {
GroovyExpression functionCall = null;
if (nextFunctionBodyStart instanceof AbstractFunctionExpression) {
//The function body start is a a function call. In this
//case, we generate a function that takes one argument, which
//is a graph traversal. We have an expression tree that
//looks kind of like the following:
//
// parentExpr
// /
// / caller
// |/_
// potentialFunctionBody
// /
// / caller
// |/_
// ...
// /
// / caller
// |/_
// nextFunctionBodyStart
// /
// / caller
// |/_
// oldCaller
//
//
// Note that potentialFunctionBody and nextFunctionBodyStart
// could be the same expression. Let's say that the next
// function name is f1
//
// We reshuffle these expressions to the following:
//
// parentExpr
// /
// / caller
// |/_
// f1(oldCaller)
//
//
// potentialFunctionBody <- body of new function "f1(GraphTraversal x)"
// /
// / caller
// |/_
// ...
// /
// / caller
// |/_
// nextFunctionBodyStart
// /
// / caller
// |/_
// x
//
// As an example, suppose parentExpr is g.V().or(x,y).has(a).has(b).has(c)
// where has(a) is nextFunctionBodyStart.
//
// We generate a function f1 = { GraphTraversal x -> x.has(a).has(b) }
// parentExpr would become : f1(g.V().or(x,y)).has(c)
AbstractFunctionExpression nextFunctionBodyStartFunction = (AbstractFunctionExpression) nextFunctionBodyStart;
String variableName = "x";
IdentifierExpression var = new IdentifierExpression(variableName);
GroovyExpression oldCaller = nextFunctionBodyStartFunction.getCaller();
nextFunctionBodyStartFunction.setCaller(var);
currentFunctionName = context.addFunctionDefinition(new VariableDeclaration(factory.getTraversalExpressionClass(), "x"), potentialFunctionBody);
functionCall = new FunctionCallExpression(potentialFunctionBody.getType(), currentFunctionName, oldCaller);
} else {
//The function body start is a not a function call. In this
//case, we generate a function that takes no arguments.
// As an example, suppose parentExpr is g.V().has(a).has(b).has(c)
// where g is nextFunctionBodyStart.
//
// We generate a function f1 = { g.V().has(a).has(b) }
// parentExpr would become : f1().has(c)
currentFunctionName = context.addFunctionDefinition(null, potentialFunctionBody);
functionCall = new FunctionCallExpression(potentialFunctionBody.getType(), currentFunctionName);
}
//functionBodyEnd is now part of a function definition, don't propagate it
nextFunctionBodyStart = null;
parentExpr.setCaller(functionCall);
}
}
use of org.apache.atlas.groovy.GroovyExpression in project incubator-atlas by apache.
the class GremlinQueryOptimizer method optimize.
/**
* Optimizes the provided groovy expression. Note that the optimization
* is a <i>destructive</i> process. The source GroovyExpression will be
* modified as part of the optimization process. This is done to avoid
* expensive copying operations where possible.
*
* @param source what to optimize
* @return the optimized query
*/
public GroovyExpression optimize(GroovyExpression source) {
LOGGER.debug("Optimizing gremlin query: " + source);
OptimizationContext context = new OptimizationContext();
GroovyExpression updatedExpression = source;
for (GremlinOptimization opt : optimizations) {
updatedExpression = optimize(updatedExpression, opt, context);
LOGGER.debug("After " + opt.getClass().getSimpleName() + ", query = " + updatedExpression);
}
StatementListExpression result = new StatementListExpression();
result.addStatements(context.getInitialStatements());
result.addStatement(updatedExpression);
LOGGER.debug("Final optimized query: " + result.toString());
return result;
}
use of org.apache.atlas.groovy.GroovyExpression in project incubator-atlas by apache.
the class Gremlin3ExpressionFactory method getRangeParameters.
@Override
public int[] getRangeParameters(AbstractFunctionExpression expr) {
if (isRangeExpression(expr)) {
FunctionCallExpression rangeExpression = (FunctionCallExpression) expr;
List<GroovyExpression> arguments = rangeExpression.getArguments();
int startIndex = (int) ((LiteralExpression) arguments.get(0)).getValue();
int endIndex = (int) ((LiteralExpression) arguments.get(1)).getValue();
return new int[] { startIndex, endIndex };
} else {
return null;
}
}
use of org.apache.atlas.groovy.GroovyExpression in project incubator-atlas by apache.
the class Gremlin3ExpressionFactory method generateSelectExpression.
@Override
public GroovyExpression generateSelectExpression(GroovyExpression parent, List<LiteralExpression> sourceNames, List<GroovyExpression> srcExprs) {
FunctionCallExpression result = new FunctionCallExpression(TraversalStepType.MAP_TO_VALUE, parent, SELECT_METHOD, sourceNames);
for (GroovyExpression expr : srcExprs) {
GroovyExpression closure = new ClosureExpression(expr);
GroovyExpression castClosure = new TypeCoersionExpression(closure, FUNCTION_CLASS);
result = new FunctionCallExpression(TraversalStepType.SIDE_EFFECT, result, BY_METHOD, castClosure);
}
return result;
}
Aggregations