析取 :用连词v把几个公式连接起来所构成的公式叫做析取
合取 :用连词^把几个公式连接起来而构成的公式叫做合取
RexNode.getOperands() : 获取表达式的子节点,单元表达式只有一个节点,使用数组下表[0]获取
/**
* Decomposes a predicate into a list of expressions that are AND'ed
* together.
*
* @param rexPredicate predicate to be analyzed
* @param rexList list of decomposed RexNodes
*/
public static void decomposeConjunction(
RexNode rexPredicate,
List<RexNode> rexList) {
if (rexPredicate == null || rexPredicate.isAlwaysTrue()) {
return;
}
if (rexPredicate.isA(SqlKind.AND)) {
for (RexNode operand : ((RexCall) rexPredicate).getOperands()) {
decomposeConjunction(operand, rexList);
}
} else {
rexList.add(rexPredicate);
}
}
即表达式rexList结果中只要有一个为真,整个表达式 rexPredicate为真。
A OR (B AND C) -> lIST(A, (B AND C))
/**
* Decomposes a predicate into a list of expressions that are OR'ed
* together.
* 这个方法抽取条件表达式中的析取范式list,即当list中表达式全部为true的时候,表达式为true
*
* @param rexPredicate predicate to be analyzed
* @param rexList list of decomposed RexNodes
*/
public static void decomposeDisjunction(
RexNode rexPredicate,
List<RexNode> rexList) {
// 合取范式, 表达式恒为假时, 不需要作为合取范式的条件
if (rexPredicate == null || rexPredicate.isAlwaysFalse()) {
return;
}
// 合取范式只需要处理或条件
if (rexPredicate.isA(SqlKind.OR)) {
for (RexNode operand : ((RexCall) rexPredicate).getOperands()) {
decomposeDisjunction(operand, rexList);
}
} else {
rexList.add(rexPredicate);
}
}
rexList 全部为true 并且 notList全为false的时候,整个表达式为真
A AND (NOT B) AND (C OR D) AND NOT (NOT(E) OR (F AND G)) 解析的结果为 rexList = List(A, C OR D, E) notList = List(B, F AND G)
/**
* Decomposes a predicate into a list of expressions that are AND'ed
* together, and a list of expressions that are preceded by NOT.
*
* <p>For example, {@code a AND NOT b AND NOT (c and d) AND TRUE AND NOT
* FALSE} returns {@code rexList = [a], notList = [b, c AND d]}.</p>
*
* <p>TRUE and NOT FALSE expressions are ignored. FALSE and NOT TRUE
* expressions are placed on {@code rexList} and {@code notList} as other
* expressions.</p>
*
* <p>For example, {@code a AND TRUE AND NOT TRUE} returns
* {@code rexList = [a], notList = [TRUE]}.</p>
*
* @param rexPredicate predicate to be analyzed
* @param rexList list of decomposed RexNodes (except those with NOT)
* @param notList list of decomposed RexNodes that were prefixed NOT
*/
public static void decomposeConjunction(
RexNode rexPredicate,
List<RexNode> rexList,
List<RexNode> notList) {
// 如果需要被判断的条件为空切恒为真,不需要进行解析
if (rexPredicate == null || rexPredicate.isAlwaysTrue()) {
return;
}
switch (rexPredicate.getKind()) {
// 这一层没有case OR, 因为AND相连,此处不拆分OR条件,Spark中存在同样的问题
case AND:
// 如果是AND则需要继续取左右子节点(operands)继续判断
for (RexNode operand : ((RexCall) rexPredicate).getOperands()) {
decomposeConjunction(operand, rexList, notList);
}
break;
case NOT:
// 如果是NOT,则取第一个子节点即NOT的子节点进行判断
final RexNode e = ((RexCall) rexPredicate).getOperands().get(0);
// 如果为假,在NOT的条件下即为真,不需要继续执行
if (e.isAlwaysFalse()) {
return;
}
switch (e.getKind()) {
// NOT OR 组合需要获取所有的析取范式
case OR:
final List<RexNode> ors = new ArrayList<>();
decomposeDisjunction(e, ors);
for (RexNode or : ors) {
switch (or.getKind()) {
case NOT:
// E = NOT(NOT(X) OR (YYY)), 如果要E为真,则需要X为假
// 所以这里是添加到析取列表
rexList.add(((RexCall) or).operands.get(0));
break;
default:
notList.add(or);
}
}
break;
default:
// 加入非析取list, 这里没有case AN, 因为在NOT条件中对于外层而言,
// AND作为一个整体, 无法被完全分解
notList.add(e);
}
break;
case LITERAL:
// 如果是常量,并且非空 & boolean类型值为true,可直接返回不判断
if (!RexLiteral.isNullLiteral(rexPredicate)
&& RexLiteral.booleanValue(rexPredicate)) {
return; // ignore TRUE
}
// 如果既不为空,常量值也不为true,由下面default处理
// fall through
default:
// 非上述情况,则添加到析取队列
rexList.add(rexPredicate);
break;
}
}