/** * If a given expression is join condition, it returns TRUE. Otherwise, it returns FALSE. * * If three conditions are satisfied, we can recognize the expression as a equi join condition. * <ol> * <li>An expression is an equal comparison expression.</li> * <li>Both terms in an expression are column references.</li> * <li>Both column references point come from different tables</li> * </ol> * * For theta join condition, we will use "an expression is a predicate including column references which come * from different two tables" instead of the first rule. * * @param expr EvalNode to be evaluated * @param includeThetaJoin If true, it will return equi as well as non-equi join conditions. * Otherwise, it only returns equi-join conditions. * @return True if it is join condition. */ public static boolean isJoinQual(EvalNode expr, boolean includeThetaJoin) { return isJoinQual(null, null, null, expr, includeThetaJoin); }
/** * If a given expression is join condition, it returns TRUE. Otherwise, it returns FALSE. * * If three conditions are satisfied, we can recognize the expression as a equi join condition. * <ol> * <li>An expression is an equal comparison expression.</li> * <li>Both terms in an expression are column references.</li> * <li>Both column references point come from different tables</li> * </ol> * * For theta join condition, we will use "an expression is a predicate including column references which come * from different two tables" instead of the first rule. * * @param expr EvalNode to be evaluated * @param includeThetaJoin If true, it will return equi as well as non-equi join conditions. * Otherwise, it only returns equi-join conditions. * @return True if it is join condition. */ public static boolean isJoinQual(EvalNode expr, boolean includeThetaJoin) { return isJoinQual(null, null, null, expr, includeThetaJoin); }
/** * Find join conditions which can be evaluated at the given join edge. The result depends on the isOnPredicate flag * which represents the given set of predicates is from the on clause of not. * * @param candidates set of predicates * @param edge join edge * @param isOnPredicates flag to represent the candidates from the on clause of not * @return predicates which can be evaluated at the given join edge */ public static Set<EvalNode> findJoinConditionForJoinVertex(Set<EvalNode> candidates, JoinEdge edge, boolean isOnPredicates) { Set<EvalNode> conditionsForThisJoin = new HashSet<>(); for (EvalNode predicate : candidates) { if (EvalTreeUtil.isJoinQual(predicate, false) && checkIfEvaluatedAtEdge(predicate, edge, isOnPredicates)) { conditionsForThisJoin.add(predicate); } } return conditionsForThisJoin; }
/** * Find join conditions which can be evaluated at the given join edge. The result depends on the isOnPredicate flag * which represents the given set of predicates is from the on clause of not. * * @param candidates set of predicates * @param edge join edge * @param isOnPredicates flag to represent the candidates from the on clause of not * @return predicates which can be evaluated at the given join edge */ public static Set<EvalNode> findJoinConditionForJoinVertex(Set<EvalNode> candidates, JoinEdge edge, boolean isOnPredicates) { Set<EvalNode> conditionsForThisJoin = TUtil.newHashSet(); for (EvalNode predicate : candidates) { if (EvalTreeUtil.isJoinQual(predicate, false) && checkIfEvaluatedAtEdge(predicate, edge, isOnPredicates)) { conditionsForThisJoin.add(predicate); } } return conditionsForThisJoin; }
@Override public LogicalNode visitFilter(JoinGraphContext context, LogicalPlan plan, LogicalPlan.QueryBlock block, SelectionNode node, Stack<LogicalNode> stack) throws TajoException { // all join predicate candidates must be collected before building the join tree except non-equality conditions // TODO: non-equality conditions should also be considered as join conditions after TAJO-1554 List<EvalNode> candidateJoinQuals = new ArrayList<>(); for (EvalNode eachEval : AlgebraicUtil.toConjunctiveNormalFormArray(node.getQual())) { if (EvalTreeUtil.isJoinQual(eachEval, false)) { candidateJoinQuals.add(eachEval); } } context.addCandidateJoinFilters(candidateJoinQuals); super.visitFilter(context, plan, block, node, stack); return node; }
@Override public void visit(EvalNode node) { if (EvalTreeUtil.isJoinQual(null, schemas[0], schemas[1], node, includeThetaJoin)) { BinaryEval binaryEval = (BinaryEval) node; Column[] pair = new Column[2]; for (int i = 0; i <= 1; i++) { // access left, right sub expression Column column = EvalTreeUtil.findAllColumnRefs(binaryEval.getChild(i)).get(0); for (int j = 0; j < schemas.length; j++) { // check whether the column is for either outer or inner // 0 is outer, and 1 is inner if (schemas[j].contains(column.getQualifiedName())) { pair[j] = column; } } } if (pair[0] == null || pair[1] == null) { throw new IllegalStateException("Wrong join key: " + node); } pairs.add(pair); } }
@Override public void visit(EvalNode node) { if (EvalTreeUtil.isJoinQual(null, schemas[0], schemas[1], node, includeThetaJoin)) { BinaryEval binaryEval = (BinaryEval) node; Column[] pair = new Column[2]; for (int i = 0; i <= 1; i++) { // access left, right sub expression Column column = EvalTreeUtil.findAllColumnRefs(binaryEval.getChild(i)).get(0); for (int j = 0; j < schemas.length; j++) { // check whether the column is for either outer or inner // 0 is outer, and 1 is inner if (schemas[j].contains(column.getQualifiedName())) { pair[j] = column; } } } if (pair[0] == null || pair[1] == null) { throw new IllegalStateException("Wrong join key: " + node); } pairs.add(pair); } }
@Override public LogicalNode visitFilter(JoinGraphContext context, LogicalPlan plan, LogicalPlan.QueryBlock block, SelectionNode node, Stack<LogicalNode> stack) throws TajoException { // all join predicate candidates must be collected before building the join tree except non-equality conditions // TODO: non-equality conditions should also be considered as join conditions after TAJO-1554 List<EvalNode> candidateJoinQuals = TUtil.newList(); for (EvalNode eachEval : AlgebraicUtil.toConjunctiveNormalFormArray(node.getQual())) { if (EvalTreeUtil.isJoinQual(eachEval, false)) { candidateJoinQuals.add(eachEval); } } context.addCandidateJoinFilters(candidateJoinQuals); super.visitFilter(context, plan, block, node, stack); return node; }
public static boolean isNonEquiThetaJoinQual(final LogicalPlan.QueryBlock block, final JoinNode joinNode, final EvalNode evalNode) { if (EvalTreeUtil.isJoinQual(block, joinNode.getLeftChild().getOutSchema(), joinNode.getRightChild().getOutSchema(), evalNode, true) && evalNode.getType() != EvalType.EQUAL) { return true; } else { return false; } }
private static boolean isNonEquiThetaJoinQual(final LogicalPlan.QueryBlock block, final JoinNode joinNode, final EvalNode evalNode) { if (EvalTreeUtil.isJoinQual(block, joinNode.getLeftChild().getOutSchema(), joinNode.getRightChild().getOutSchema(), evalNode, true) && evalNode.getType() != EvalType.EQUAL) { return true; } else { return false; } }
public static boolean isNonEquiThetaJoinQual(final LogicalPlan.QueryBlock block, final JoinNode joinNode, final EvalNode evalNode) { if (EvalTreeUtil.isJoinQual(block, joinNode.getLeftChild().getOutSchema(), joinNode.getRightChild().getOutSchema(), evalNode, true) && evalNode.getType() != EvalType.EQUAL) { return true; } else { return false; } }
private static boolean isNonEquiThetaJoinQual(final LogicalPlan.QueryBlock block, final JoinNode joinNode, final EvalNode evalNode) { if (EvalTreeUtil.isJoinQual(block, joinNode.getLeftChild().getOutSchema(), joinNode.getRightChild().getOutSchema(), evalNode, true) && evalNode.getType() != EvalType.EQUAL) { return true; } else { return false; } }
@Test public final void testIsJoinQual() throws TajoException { EvalNode evalNode = getRootSelection("select score from people where people.score > people.age"); assertFalse(EvalTreeUtil.isJoinQual(evalNode, true)); }
@Test public final void testIsJoinQual2() throws TajoException { EvalNode evalNode = getRootSelection( "select score from people where substr(people.score::text,1,1) > substr(people.age::text,1,1)"); assertFalse(EvalTreeUtil.isJoinQual(evalNode, true)); } }
public static boolean isEvaluatableJoinQual(QueryBlock block, EvalNode evalNode, JoinNode node, boolean isOnPredicate, boolean isTopMostJoin) { if (checkIfBeEvaluatedAtJoin(block, evalNode, node, isTopMostJoin)) { if (isNonEquiThetaJoinQual(block, node, evalNode)) { return false; } if (PlannerUtil.isOuterJoinType(node.getJoinType())) { /* * For outer joins, only predicates which are specified at the on clause can be evaluated during processing join. * Other predicates from the where clause must be evaluated after the join. * The below code will be modified after improving join operators to keep join filters by themselves (TAJO-1310). */ if (!isOnPredicate) { return false; } } else { /* * Only join predicates should be evaluated at join if the join type is inner or cross. (TAJO-1445) */ if (!EvalTreeUtil.isJoinQual(block, node.getLeftChild().getOutSchema(), node.getRightChild().getOutSchema(), evalNode, false)) { return false; } } return true; } return false; }
public static boolean isEvaluatableJoinQual(QueryBlock block, EvalNode evalNode, JoinNode node, boolean isOnPredicate, boolean isTopMostJoin) { if (checkIfBeEvaluatedAtJoin(block, evalNode, node, isTopMostJoin)) { if (isNonEquiThetaJoinQual(block, node, evalNode)) { return false; } if (PlannerUtil.isOuterJoinType(node.getJoinType())) { /* * For outer joins, only predicates which are specified at the on clause can be evaluated during processing join. * Other predicates from the where clause must be evaluated after the join. * The below code will be modified after improving join operators to keep join filters by themselves (TAJO-1310). */ if (!isOnPredicate) { return false; } } else { /* * Only join predicates should be evaluated at join if the join type is inner or cross. (TAJO-1445) */ if (!EvalTreeUtil.isJoinQual(block, node.getLeftChild().getOutSchema(), node.getRightChild().getOutSchema(), evalNode, false)) { return false; } } return true; } return false; }
Set<EvalNode> originPredicates = joinNode.getJoinSpec().getPredicates(); for (EvalNode predicate : joinNode.getJoinSpec().getPredicates()) { if (EvalTreeUtil.isJoinQual(block, leftVertex.getSchema(), rightVertex.getSchema(), predicate, false)) { if (JoinOrderingUtil.checkIfEvaluatedAtEdge(predicate, edge, true)) { joinConditions.add(predicate);
Set<EvalNode> originPredicates = joinNode.getJoinSpec().getPredicates(); for (EvalNode predicate : joinNode.getJoinSpec().getPredicates()) { if (EvalTreeUtil.isJoinQual(block, leftVertex.getSchema(), rightVertex.getSchema(), predicate, false)) { if (JoinOrderingUtil.checkIfEvaluatedAtEdge(predicate, edge, true)) { joinConditions.add(predicate);
@Test public final void testIsJoinQual() { FieldEval f1 = new FieldEval("part.p_partkey", CatalogUtil.newSimpleDataType(Type.INT4)); FieldEval f2 = new FieldEval("partsupp.ps_partkey", CatalogUtil.newSimpleDataType(Type.INT4)); BinaryEval [] joinQuals = new BinaryEval[5]; int idx = 0; joinQuals[idx++] = new BinaryEval(EvalType.EQUAL, f1, f2); joinQuals[idx++] = new BinaryEval(EvalType.LEQ, f1, f2); joinQuals[idx++] = new BinaryEval(EvalType.LTH, f1, f2); joinQuals[idx++] = new BinaryEval(EvalType.GEQ, f1, f2); joinQuals[idx] = new BinaryEval(EvalType.GTH, f1, f2); for (int i = 0; i < idx; i++) { assertTrue(EvalTreeUtil.isJoinQual(joinQuals[idx], true)); } BinaryEval [] wrongJoinQuals = new BinaryEval[5]; idx = 0; wrongJoinQuals[idx++] = new BinaryEval(EvalType.OR, f1, f2); wrongJoinQuals[idx++] = new BinaryEval(EvalType.PLUS, f1, f2); wrongJoinQuals[idx++] = new BinaryEval(EvalType.LIKE, f1, f2); ConstEval f3 = new ConstEval(DatumFactory.createInt4(1)); wrongJoinQuals[idx] = new BinaryEval(EvalType.EQUAL, f1, f3); for (int i = 0; i < idx; i++) { assertFalse(EvalTreeUtil.isJoinQual(wrongJoinQuals[idx], true)); } }