@Override public EvalNode visitUnaryEval(LogicalPlanner.PlanContext context, UnaryEval unaryEval, Stack<EvalNode> stack) { stack.push(unaryEval); if (unaryEval.getChild().getType() == EvalType.FIELD) { FieldEval fieldEval = (FieldEval) unaryEval.getChild(); if (context.getQueryBlock().isConstReference(fieldEval.getName())) { unaryEval.setChild(context.getQueryBlock().getConstByReference(fieldEval.getName())); stack.pop(); return unaryEval; } } visit(context, unaryEval.getChild(), stack); stack.pop(); return unaryEval; }
@Override public EvalNode visitUnaryEval(LogicalPlanner.PlanContext context, UnaryEval unaryEval, Stack<EvalNode> stack) { stack.push(unaryEval); if (unaryEval.getChild().getType() == EvalType.FIELD) { FieldEval fieldEval = (FieldEval) unaryEval.getChild(); if (context.getQueryBlock().isConstReference(fieldEval.getName())) { unaryEval.setChild(context.getQueryBlock().getConstByReference(fieldEval.getName())); stack.pop(); return unaryEval; } } visit(context, unaryEval.getChild(), stack); stack.pop(); return unaryEval; }
@Override public EvalNode visitBinaryEval(LogicalPlanner.PlanContext context, Stack<EvalNode> stack, BinaryEval binaryEval) { stack.push(binaryEval); for (int i = 0; i < 2; i++) { if (binaryEval.getChild(i).getType() == EvalType.FIELD) { FieldEval fieldEval = (FieldEval) binaryEval.getChild(i); if (context.getQueryBlock().isConstReference(fieldEval.getName())) { binaryEval.setChild(i, context.getQueryBlock().getConstByReference(fieldEval.getName())); continue; } } visit(context, binaryEval.getChild(i), stack); } stack.pop(); return binaryEval; }
@Override public LogicalNode visitRelation(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Relation relation) throws TajoException { String actualRelationName; if (CatalogUtil.isFQTableName(relation.getName())) { actualRelationName = relation.getName(); } else { actualRelationName = CatalogUtil.buildFQName(ctx.getQueryContext().get(SessionVars.CURRENT_DATABASE), relation.getName()); } TableDesc desc = catalog.getTableDesc(actualRelationName); ScanNode scanNode = ctx.getPlan().createNode(ScanNode.class); if (relation.hasAlias()) { scanNode.init(desc, relation.getAlias()); } else { scanNode.init(desc); } TablePropertyUtil.setTableProperty(ctx.getQueryContext(), scanNode); ctx.getQueryBlock().addRelation(scanNode); return scanNode; }
@Override public LogicalNode visitRelation(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Relation relation) throws TajoException { String actualRelationName; if (IdentifierUtil.isFQTableName(relation.getName())) { actualRelationName = relation.getName(); } else { actualRelationName = IdentifierUtil.buildFQName(ctx.getQueryContext().get(SessionVars.CURRENT_DATABASE), relation.getName()); } TableDesc desc = catalog.getTableDesc(actualRelationName); ScanNode scanNode = ctx.getPlan().createNode(ScanNode.class); if (relation.hasAlias()) { scanNode.init(desc, relation.getAlias()); } else { scanNode.init(desc); } TablePropertyUtil.setTableProperty(ctx.getQueryContext(), scanNode); ctx.getQueryBlock().addRelation(scanNode); return scanNode; }
@Override public EvalNode visitFuncCall(LogicalPlanner.PlanContext context, FunctionEval function, Stack<EvalNode> stack) { stack.push(function); for (int i = 0; i < function.getArgs().length; i++) { if (function.getArgs()[i].getType() == EvalType.FIELD) { FieldEval fieldEval = (FieldEval) function.getArgs()[i]; if (context.getQueryBlock().isConstReference(fieldEval.getName())) { function.setArg(i, context.getQueryBlock().getConstByReference(fieldEval.getName())); continue; } } visit(context, function.getArgs()[i], stack); } stack.pop(); return function; } }
@Override public LogicalNode visitTableSubQuery(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, TablePrimarySubQuery expr) throws TajoException { LogicalPlanner.PlanContext newContext; // Note: TableSubQuery always has a table name. // SELECT .... FROM (SELECT ...) TB_NAME <- QueryBlock queryBlock = ctx.getPlan().newQueryBlock(); newContext = new LogicalPlanner.PlanContext(ctx, queryBlock); LogicalNode child = super.visitTableSubQuery(newContext, stack, expr); queryBlock.setRoot(child); // a table subquery should be dealt as a relation. TableSubQueryNode node = ctx.getPlan().createNode(TableSubQueryNode.class); node.init(CatalogUtil.buildFQName(ctx.getQueryContext().get(SessionVars.CURRENT_DATABASE), expr.getName()), child); ctx.getQueryBlock().addRelation(node); return node; }
@Override public LogicalNode visitTableSubQuery(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, TablePrimarySubQuery expr) throws TajoException { LogicalPlanner.PlanContext newContext; // Note: TableSubQuery always has a table name. // SELECT .... FROM (SELECT ...) TB_NAME <- QueryBlock queryBlock = ctx.getPlan().newQueryBlock(); newContext = new LogicalPlanner.PlanContext(ctx, queryBlock); LogicalNode child = super.visitTableSubQuery(newContext, stack, expr); queryBlock.setRoot(child); // a table subquery should be dealt as a relation. TableSubQueryNode node = ctx.getPlan().createNode(TableSubQueryNode.class); node.init(IdentifierUtil.buildFQName(ctx.getQueryContext().get(SessionVars.CURRENT_DATABASE), expr.getName()), child); ctx.getQueryBlock().addRelation(node); return node; }
@Override public EvalNode visitFuncCall(LogicalPlanner.PlanContext context, FunctionEval function, Stack<EvalNode> stack) { stack.push(function); for (int i = 0; i < function.getArgs().length; i++) { if (function.getArgs()[i].getType() == EvalType.FIELD) { FieldEval fieldEval = (FieldEval) function.getArgs()[i]; if (context.getQueryBlock().isConstReference(fieldEval.getName())) { function.setArg(i, context.getQueryBlock().getConstByReference(fieldEval.getName())); continue; } } visit(context, function.getArgs()[i], stack); } stack.pop(); return function; } }
@Override public EvalNode visitBinaryEval(LogicalPlanner.PlanContext context, Stack<EvalNode> stack, BinaryEval binaryEval) { stack.push(binaryEval); for (int i = 0; i < 2; i++) { if (binaryEval.getChild(i).getType() == EvalType.FIELD) { FieldEval fieldEval = (FieldEval) binaryEval.getChild(i); if (context.getQueryBlock().isConstReference(fieldEval.getName())) { binaryEval.setChild(i, context.getQueryBlock().getConstByReference(fieldEval.getName())); continue; } } visit(context, binaryEval.getChild(i), stack); } stack.pop(); return binaryEval; }
@Override public EvalNode optimize(LogicalPlanner.PlanContext context, EvalNode evalNode) { if (evalNode.getType() == EvalType.FIELD) { FieldEval fieldEval = (FieldEval) evalNode; // if a reference points to a const value if (context.getQueryBlock().isConstReference(fieldEval.getName())) { return context.getQueryBlock().getConstByReference(fieldEval.getName()); } else { return evalNode; // otherwise, it just returns. } } else { return visit(context, evalNode, new Stack<EvalNode>()); } }
@Override public LogicalNode visitJoin(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Join expr) throws TajoException { stack.push(expr); LogicalNode left = visit(ctx, stack, expr.getLeft()); LogicalNode right = visit(ctx, stack, expr.getRight()); stack.pop(); JoinNode joinNode = ctx.getPlan().createNode(JoinNode.class); joinNode.setJoinType(expr.getJoinType()); Schema merged = SchemaUtil.merge(left.getOutSchema(), right.getOutSchema()); joinNode.setInSchema(merged); joinNode.setOutSchema(merged); ctx.getQueryBlock().addJoinType(expr.getJoinType()); return joinNode; }
@Override public LogicalNode visitJoin(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Join expr) throws TajoException { stack.push(expr); LogicalNode left = visit(ctx, stack, expr.getLeft()); LogicalNode right = visit(ctx, stack, expr.getRight()); stack.pop(); JoinNode joinNode = ctx.getPlan().createNode(JoinNode.class); joinNode.setJoinType(expr.getJoinType()); Schema merged = SchemaUtil.merge(left.getOutSchema(), right.getOutSchema()); joinNode.setInSchema(merged); joinNode.setOutSchema(merged); ctx.getQueryBlock().addJoinType(expr.getJoinType()); return joinNode; }
@Override public EvalNode optimize(LogicalPlanner.PlanContext context, EvalNode evalNode) { if (evalNode.getType() == EvalType.FIELD) { FieldEval fieldEval = (FieldEval) evalNode; // if a reference points to a const value if (context.getQueryBlock().isConstReference(fieldEval.getName())) { return context.getQueryBlock().getConstByReference(fieldEval.getName()); } else { return evalNode; // otherwise, it just returns. } } else { return visit(context, evalNode, new Stack<>()); } }
@Override public LogicalNode postHook(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Expr expr, LogicalNode result) throws TajoException { // If non-from statement, result can be null. It avoids that case. if (result != null) { // setNode method registers each node to corresponding block and plan. ctx.getQueryBlock().registerNode(result); // It makes a map between an expr and a logical node. ctx.getQueryBlock().registerExprWithNode(expr, result); } return result; }
@Override public void preHook(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Expr expr) throws TajoException { ctx.getQueryBlock().setAlgebraicExpr(expr); ctx.getPlan().mapExprToBlock(expr, ctx.getQueryBlock().getName()); }
@Override public void preHook(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Expr expr) throws TajoException { ctx.getQueryBlock().setAlgebraicExpr(expr); ctx.getPlan().mapExprToBlock(expr, ctx.getQueryBlock().getName()); }
@Override public LogicalNode postHook(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Expr expr, LogicalNode result) throws TajoException { // If non-from statement, result can be null. It avoids that case. if (result != null) { // setNode method registers each node to corresponding block and plan. ctx.getQueryBlock().registerNode(result); // It makes a map between an expr and a logical node. ctx.getQueryBlock().registerExprWithNode(expr, result); } return result; }
@Override public Expr visitColumnReference(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, ColumnReferenceExpr expr) throws TajoException { String normalized = NameResolver.resolve(ctx.getPlan(), ctx.getQueryBlock(), expr, NameResolvingMode.RELS_ONLY, true).getQualifiedName(); expr.setName(normalized); return expr; } }
@Override public Expr visitColumnReference(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, ColumnReferenceExpr expr) throws TajoException { String normalized = NameResolver.resolve(ctx.getPlan(), ctx.getQueryBlock(), expr, NameResolvingMode.RELS_ONLY, true).getQualifiedName(); expr.setName(normalized); return expr; } }