in src/query/src/main/java/org/apache/kylin/query/optrule/ExtensionOlapJoinRule.java [141:230]
private List<RexInputRef> isPowerBiInnerJoin(JoinInfo info, RexBuilder rexBuilder) {
if (info.isEqui()) {
return null;
}
// 1. top call is OR
RexNode root = RexUtil.composeConjunction(rexBuilder, info.nonEquiConditions);
if (!(root instanceof RexCall && root.getKind() == SqlKind.OR)) {
return null;
}
// 2. operands are ANDs
RexCall rootCall = (RexCall) root;
if (rootCall.operands.size() != 2) {
return null;
}
if (!(isOperandSqlAnd(rootCall, 0) && isOperandSqlAnd(rootCall, 1))) {
return null;
}
// 3. which operand contains two IS_NULL checks
RexCall leftCall = (RexCall) rootCall.operands.get(0);
RexCall rightCall = (RexCall) rootCall.operands.get(1);
RexCall twoNullCall, notNullCall;
if (isOperandSqlIsNull(leftCall, 0) && isOperandSqlIsNull(leftCall, 1)) {
twoNullCall = leftCall;
notNullCall = rightCall;
} else if (isOperandSqlIsNull(rightCall, 0) && isOperandSqlIsNull(rightCall, 1)) {
twoNullCall = rightCall;
notNullCall = leftCall;
} else {
return null;
}
// 4. two column refs
RexCall isNull1 = (RexCall) twoNullCall.operands.get(0);
RexCall isNull2 = (RexCall) twoNullCall.operands.get(1);
if (!(isOperandInputRef(isNull1, 0) && isOperandInputRef(isNull2, 0))) {
return null;
}
Set<RexInputRef> refs = Sets.newHashSet((RexInputRef) isNull1.operands.get(0),
(RexInputRef) isNull2.operands.get(0));
if (refs.size() != 2) {
return null;
}
// 5. equal not null
if (notNullCall.operands.size() != 3) {
return null;
}
RexCall equalCall, notNull1, notNull2;
if (isOperandSqlEq(notNullCall, 0) && isOperandSqlIsNotNull(notNullCall, 1)
&& isOperandSqlIsNotNull(notNullCall, 2)) {
equalCall = (RexCall) notNullCall.operands.get(0);
notNull1 = (RexCall) notNullCall.operands.get(1);
notNull2 = (RexCall) notNullCall.operands.get(2);
} else if (isOperandSqlEq(notNullCall, 1) && isOperandSqlIsNotNull(notNullCall, 0)
&& isOperandSqlIsNotNull(notNullCall, 2)) {
equalCall = (RexCall) notNullCall.operands.get(1);
notNull1 = (RexCall) notNullCall.operands.get(0);
notNull2 = (RexCall) notNullCall.operands.get(2);
} else if (isOperandSqlEq(notNullCall, 2) && isOperandSqlIsNotNull(notNullCall, 0)
&& isOperandSqlIsNotNull(notNullCall, 1)) {
equalCall = (RexCall) notNullCall.operands.get(2);
notNull1 = (RexCall) notNullCall.operands.get(0);
notNull2 = (RexCall) notNullCall.operands.get(1);
} else {
return null;
}
if (equalCall.operands.get(0).equals(equalCall.operands.get(1))) {
return null;
}
if (!(refs.contains(equalCall.operands.get(0)) && refs.contains(equalCall.operands.get(1)))) {
return null;
}
if (notNull1.operands.get(0).equals(notNull2.operands.get(0))) {
return null;
}
if (!(refs.contains(notNull1.operands.get(0)) && refs.contains(notNull2.operands.get(0)))) {
return null;
}
return Lists.newArrayList(refs);
}