blob: f0b2da647126b661a3ade133d2dd50065e945f09 [file] [log] [blame]
package edu.uci.ics.asterix.aql.rewrites;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import edu.uci.ics.asterix.aql.base.Clause;
import edu.uci.ics.asterix.aql.base.Expression;
import edu.uci.ics.asterix.aql.base.IAqlExpression;
import edu.uci.ics.asterix.aql.base.Expression.Kind;
import edu.uci.ics.asterix.aql.expression.BeginFeedStatement;
import edu.uci.ics.asterix.aql.expression.CallExpr;
import edu.uci.ics.asterix.aql.expression.ControlFeedStatement;
import edu.uci.ics.asterix.aql.expression.CreateDataverseStatement;
import edu.uci.ics.asterix.aql.expression.CreateFunctionStatement;
import edu.uci.ics.asterix.aql.expression.CreateIndexStatement;
import edu.uci.ics.asterix.aql.expression.DatasetDecl;
import edu.uci.ics.asterix.aql.expression.DataverseDecl;
import edu.uci.ics.asterix.aql.expression.DataverseDropStatement;
import edu.uci.ics.asterix.aql.expression.DeleteStatement;
import edu.uci.ics.asterix.aql.expression.DieClause;
import edu.uci.ics.asterix.aql.expression.DistinctClause;
import edu.uci.ics.asterix.aql.expression.DropStatement;
import edu.uci.ics.asterix.aql.expression.FLWOGRExpression;
import edu.uci.ics.asterix.aql.expression.FieldAccessor;
import edu.uci.ics.asterix.aql.expression.FieldBinding;
import edu.uci.ics.asterix.aql.expression.ForClause;
import edu.uci.ics.asterix.aql.expression.FunctionDecl;
import edu.uci.ics.asterix.aql.expression.FunctionDropStatement;
import edu.uci.ics.asterix.aql.expression.GbyVariableExpressionPair;
import edu.uci.ics.asterix.aql.expression.GroupbyClause;
import edu.uci.ics.asterix.aql.expression.IfExpr;
import edu.uci.ics.asterix.aql.expression.IndexAccessor;
import edu.uci.ics.asterix.aql.expression.IndexDropStatement;
import edu.uci.ics.asterix.aql.expression.InsertStatement;
import edu.uci.ics.asterix.aql.expression.LetClause;
import edu.uci.ics.asterix.aql.expression.LimitClause;
import edu.uci.ics.asterix.aql.expression.ListConstructor;
import edu.uci.ics.asterix.aql.expression.LiteralExpr;
import edu.uci.ics.asterix.aql.expression.LoadFromFileStatement;
import edu.uci.ics.asterix.aql.expression.NodeGroupDropStatement;
import edu.uci.ics.asterix.aql.expression.NodegroupDecl;
import edu.uci.ics.asterix.aql.expression.OperatorExpr;
import edu.uci.ics.asterix.aql.expression.OrderbyClause;
import edu.uci.ics.asterix.aql.expression.OrderedListTypeDefinition;
import edu.uci.ics.asterix.aql.expression.QuantifiedExpression;
import edu.uci.ics.asterix.aql.expression.QuantifiedPair;
import edu.uci.ics.asterix.aql.expression.Query;
import edu.uci.ics.asterix.aql.expression.RecordConstructor;
import edu.uci.ics.asterix.aql.expression.RecordTypeDefinition;
import edu.uci.ics.asterix.aql.expression.SetStatement;
import edu.uci.ics.asterix.aql.expression.TypeDecl;
import edu.uci.ics.asterix.aql.expression.TypeDropStatement;
import edu.uci.ics.asterix.aql.expression.TypeReferenceExpression;
import edu.uci.ics.asterix.aql.expression.UnaryExpr;
import edu.uci.ics.asterix.aql.expression.UnionExpr;
import edu.uci.ics.asterix.aql.expression.UnorderedListTypeDefinition;
import edu.uci.ics.asterix.aql.expression.UpdateClause;
import edu.uci.ics.asterix.aql.expression.UpdateStatement;
import edu.uci.ics.asterix.aql.expression.VarIdentifier;
import edu.uci.ics.asterix.aql.expression.VariableExpr;
import edu.uci.ics.asterix.aql.expression.WhereClause;
import edu.uci.ics.asterix.aql.expression.WriteFromQueryResultStatement;
import edu.uci.ics.asterix.aql.expression.WriteStatement;
import edu.uci.ics.asterix.aql.expression.visitor.IAqlExpressionVisitor;
import edu.uci.ics.asterix.common.exceptions.AsterixException;
import edu.uci.ics.asterix.om.functions.AsterixFunction;
import edu.uci.ics.hyracks.algebricks.core.utils.Pair;
public class InlineUdfsVisitor implements IAqlExpressionVisitor<Boolean, List<FunctionDecl>> {
private final AqlRewritingContext context;
private final CloneAndSubstituteVariablesVisitor cloneVisitor;
public InlineUdfsVisitor(AqlRewritingContext context) {
this.context = context;
this.cloneVisitor = new CloneAndSubstituteVariablesVisitor(context);
}
@Override
public Boolean visitQuery(Query q, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, Expression> p = inlineUdfsInExpr(q.getBody(), arg);
q.setBody(p.second);
return p.first;
}
@Override
public Boolean visitFunctionDecl(FunctionDecl fd, List<FunctionDecl> arg) throws AsterixException {
// Careful, we should only do this after analyzing the graph of function
// calls.
Pair<Boolean, Expression> p = inlineUdfsInExpr(fd.getFuncBody(), arg);
fd.setFuncBody(p.second);
return p.first;
}
@Override
public Boolean visitListConstructor(ListConstructor lc, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, ArrayList<Expression>> p = newExprList(lc.getExprList(), arg);
lc.setExprList(p.second);
return p.first;
}
@Override
public Boolean visitRecordConstructor(RecordConstructor rc, List<FunctionDecl> arg) throws AsterixException {
boolean changed = false;
for (FieldBinding b : rc.getFbList()) {
if (b.getLeftExpr().accept(this, arg)) {
changed = true;
}
if (b.getRightExpr().accept(this, arg)) {
changed = true;
}
}
return changed;
}
@Override
public Boolean visitCallExpr(CallExpr pf, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, ArrayList<Expression>> p = newExprList(pf.getExprList(), arg);
pf.setExprList(p.second);
return p.first;
}
@Override
public Boolean visitOperatorExpr(OperatorExpr ifbo, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, ArrayList<Expression>> p = newExprList(ifbo.getExprList(), arg);
ifbo.setExprList(p.second);
return p.first;
}
@Override
public Boolean visitFieldAccessor(FieldAccessor fa, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, Expression> p = inlineUdfsInExpr(fa.getExpr(), arg);
fa.setExpr(p.second);
return p.first;
}
@Override
public Boolean visitIndexAccessor(IndexAccessor fa, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, Expression> p = inlineUdfsInExpr(fa.getExpr(), arg);
fa.setExpr(p.second);
return p.first;
}
@Override
public Boolean visitIfExpr(IfExpr ifexpr, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, Expression> p1 = inlineUdfsInExpr(ifexpr.getCondExpr(), arg);
ifexpr.setCondExpr(p1.second);
Pair<Boolean, Expression> p2 = inlineUdfsInExpr(ifexpr.getThenExpr(), arg);
ifexpr.setThenExpr(p2.second);
Pair<Boolean, Expression> p3 = inlineUdfsInExpr(ifexpr.getElseExpr(), arg);
ifexpr.setElseExpr(p3.second);
return p1.first || p2.first || p3.first;
}
@Override
public Boolean visitFlworExpression(FLWOGRExpression flwor, List<FunctionDecl> arg) throws AsterixException {
boolean changed = false;
for (Clause c : flwor.getClauseList()) {
if (c.accept(this, arg)) {
changed = true;
}
}
Pair<Boolean, Expression> p = inlineUdfsInExpr(flwor.getReturnExpr(), arg);
flwor.setReturnExpr(p.second);
return changed || p.first;
}
@Override
public Boolean visitQuantifiedExpression(QuantifiedExpression qe, List<FunctionDecl> arg) throws AsterixException {
boolean changed = false;
for (QuantifiedPair t : qe.getQuantifiedList()) {
Pair<Boolean, Expression> p = inlineUdfsInExpr(t.getExpr(), arg);
t.setExpr(p.second);
if (p.first) {
changed = true;
}
}
Pair<Boolean, Expression> p2 = inlineUdfsInExpr(qe.getSatisfiesExpr(), arg);
qe.setSatisfiesExpr(p2.second);
return changed || p2.first;
}
@Override
public Boolean visitForClause(ForClause fc, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, Expression> p = inlineUdfsInExpr(fc.getInExpr(), arg);
fc.setInExpr(p.second);
return p.first;
}
@Override
public Boolean visitLetClause(LetClause lc, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, Expression> p = inlineUdfsInExpr(lc.getBindingExpr(), arg);
lc.setBindingExpr(p.second);
return p.first;
}
@Override
public Boolean visitWhereClause(WhereClause wc, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, Expression> p = inlineUdfsInExpr(wc.getWhereExpr(), arg);
wc.setWhereExpr(p.second);
return p.first;
}
@Override
public Boolean visitOrderbyClause(OrderbyClause oc, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, ArrayList<Expression>> p = newExprList(oc.getOrderbyList(), arg);
oc.setOrderbyList(p.second);
return p.first;
}
@Override
public Boolean visitGroupbyClause(GroupbyClause gc, List<FunctionDecl> arg) throws AsterixException {
boolean changed = false;
for (GbyVariableExpressionPair p : gc.getGbyPairList()) {
Pair<Boolean, Expression> be = inlineUdfsInExpr(p.getExpr(), arg);
p.setExpr(be.second);
if (be.first) {
changed = true;
}
}
for (GbyVariableExpressionPair p : gc.getDecorPairList()) {
Pair<Boolean, Expression> be = inlineUdfsInExpr(p.getExpr(), arg);
p.setExpr(be.second);
if (be.first) {
changed = true;
}
}
return changed;
}
@Override
public Boolean visitLimitClause(LimitClause lc, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, Expression> p1 = inlineUdfsInExpr(lc.getLimitExpr(), arg);
lc.setLimitExpr(p1.second);
boolean changed = p1.first;
if (lc.getOffset() != null) {
Pair<Boolean, Expression> p2 = inlineUdfsInExpr(lc.getOffset(), arg);
lc.setOffset(p2.second);
changed = changed || p2.first;
}
return changed;
}
@Override
public Boolean visitDieClause(DieClause lc, List<FunctionDecl> arg) throws AsterixException {
Pair<Boolean, Expression> p1 = inlineUdfsInExpr(lc.getDieExpr(), arg);
lc.setDieExpr(p1.second);
return p1.first;
}
@Override
public Boolean visitUnaryExpr(UnaryExpr u, List<FunctionDecl> arg) throws AsterixException {
return u.getExpr().accept(this, arg);
}
@Override
public Boolean visitUnionExpr(UnionExpr u, List<FunctionDecl> fds) throws AsterixException {
Pair<Boolean, ArrayList<Expression>> p = newExprList(u.getExprs(), fds);
u.setExprs(p.second);
return p.first;
}
@Override
public Boolean visitDistinctClause(DistinctClause dc, List<FunctionDecl> arg) throws AsterixException {
boolean changed = false;
for (Expression expr : dc.getDistinctByExpr()) {
changed = expr.accept(this, arg);
}
return changed;
}
@Override
public Boolean visitVariableExpr(VariableExpr v, List<FunctionDecl> arg) throws AsterixException {
return false;
}
@Override
public Boolean visitLiteralExpr(LiteralExpr l, List<FunctionDecl> arg) throws AsterixException {
return false;
}
private Pair<Boolean, Expression> inlineUdfsInExpr(Expression expr, List<FunctionDecl> arg) throws AsterixException {
if (expr.getKind() != Kind.CALL_EXPRESSION) {
boolean r = expr.accept(this, arg);
return new Pair<Boolean, Expression>(r, expr);
} else {
CallExpr f = (CallExpr) expr;
FunctionDecl implem = findFuncDeclaration(f.getIdent(), arg);
if (implem == null) {
boolean r = expr.accept(this, arg);
return new Pair<Boolean, Expression>(r, expr);
} else { // it's one of the functions we want to inline
List<Clause> clauses = new ArrayList<Clause>();
Iterator<VarIdentifier> paramIter = implem.getParamList().iterator();
// List<VariableExpr> effectiveArgs = new
// ArrayList<VariableExpr>(f.getExprList().size());
List<VariableSubstitution> subts = new ArrayList<VariableSubstitution>(f.getExprList().size());
for (Expression e : f.getExprList()) {
VarIdentifier param = paramIter.next();
// Obs: we could do smth about passing also literals, or let
// variable inlining to take care of this.
if (e.getKind() == Kind.VARIABLE_EXPRESSION) {
subts.add(new VariableSubstitution(param, ((VariableExpr) e).getVar()));
} else {
VarIdentifier newV = context.newVariable();
Pair<IAqlExpression, List<VariableSubstitution>> p1 = e.accept(cloneVisitor,
new ArrayList<VariableSubstitution>());
LetClause c = new LetClause(new VariableExpr(newV), (Expression) p1.first);
clauses.add(c);
subts.add(new VariableSubstitution(param, newV));
}
}
Pair<IAqlExpression, List<VariableSubstitution>> p2 = implem.getFuncBody().accept(cloneVisitor, subts);
Expression resExpr;
if (clauses.isEmpty()) {
resExpr = (Expression) p2.first;
} else {
resExpr = new FLWOGRExpression(clauses, (Expression) p2.first);
}
return new Pair<Boolean, Expression>(true, resExpr);
}
}
}
private Pair<Boolean, ArrayList<Expression>> newExprList(List<Expression> exprList, List<FunctionDecl> fds)
throws AsterixException {
ArrayList<Expression> newList = new ArrayList<Expression>();
boolean changed = false;
for (Expression e : exprList) {
Pair<Boolean, Expression> p = inlineUdfsInExpr(e, fds);
newList.add(p.second);
if (p.first) {
changed = true;
}
}
return new Pair<Boolean, ArrayList<Expression>>(changed, newList);
}
private static FunctionDecl findFuncDeclaration(AsterixFunction fid, List<FunctionDecl> sequence) {
for (FunctionDecl f : sequence) {
if (f.getIdent().equals(fid)) {
return f;
}
}
return null;
}
@Override
public Boolean visitCreateIndexStatement(CreateIndexStatement cis, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitDataverseDecl(DataverseDecl dv, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitDeleteStatement(DeleteStatement del, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitDropStatement(DropStatement del, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitDatasetDecl(DatasetDecl dd, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitInsertStatement(InsertStatement insert, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitLoadFromFileStatement(LoadFromFileStatement stmtLoad, List<FunctionDecl> arg)
throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitNodegroupDecl(NodegroupDecl ngd, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitOrderedListTypeDefiniton(OrderedListTypeDefinition olte, List<FunctionDecl> arg)
throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitRecordTypeDefiniton(RecordTypeDefinition tre, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitSetStatement(SetStatement ss, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitTypeDecl(TypeDecl td, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitTypeReferenceExpression(TypeReferenceExpression tre, List<FunctionDecl> arg)
throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitUnorderedListTypeDefiniton(UnorderedListTypeDefinition ulte, List<FunctionDecl> arg)
throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitUpdateClause(UpdateClause del, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitUpdateStatement(UpdateStatement update, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitWriteFromQueryResultStatement(WriteFromQueryResultStatement stmtLoad, List<FunctionDecl> arg)
throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitWriteStatement(WriteStatement ws, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitLoadFromQueryResultStatement(WriteFromQueryResultStatement stmtLoad, List<FunctionDecl> arg)
throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitCreateDataverseStatement(CreateDataverseStatement del, List<FunctionDecl> arg)
throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitIndexDropStatement(IndexDropStatement del, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitNodeGroupDropStatement(NodeGroupDropStatement del, List<FunctionDecl> arg)
throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitDataverseDropStatement(DataverseDropStatement del, List<FunctionDecl> arg)
throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitTypeDropStatement(TypeDropStatement del, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitControlFeedStatement(ControlFeedStatement del, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visit(CreateFunctionStatement cfs, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitFunctionDropStatement(FunctionDropStatement del, List<FunctionDecl> arg)
throws AsterixException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean visitBeginFeedStatement(BeginFeedStatement bf, List<FunctionDecl> arg) throws AsterixException {
// TODO Auto-generated method stub
return null;
}
}