@@ -43,6 +43,8 @@ object PhysicalOperation extends PredicateHelper {
4343
4444 /**
4545 * Collects all deterministic projects and filters, in-lining/substituting aliases if necessary.
46+ * Note that, if the filter is non-deterministic the deterministic expressions should be
47+ * extracted.
4648 * Here are two examples for alias in-lining/substitution.
4749 * Before:
4850 * {{{
@@ -63,9 +65,8 @@ object PhysicalOperation extends PredicateHelper {
6365 val substitutedFields = fields.map(substitute(aliases)).asInstanceOf [Seq [NamedExpression ]]
6466 (Some (substitutedFields), filters, other, collectAliases(substitutedFields))
6567
66- case filter @ Filter (condition, child)
67- if condition.deterministic || condition.isInstanceOf [And ] =>
68- val determinedCondition = getDeterminedExpression(condition)
68+ case filter @ Filter (condition, child) =>
69+ val determinedCondition = extractDeterministicExpressions(condition)
6970 if (determinedCondition.isDefined) {
7071 val (fields, filters, other, aliases) = collectProjectsAndFilters(child)
7172 val substitutedCondition = substitute(aliases)(determinedCondition.get)
@@ -98,21 +99,48 @@ object PhysicalOperation extends PredicateHelper {
9899 }
99100 }
100101
101- private def getDeterminedExpression (expr : Expression ): Option [Expression ] = {
102+ /**
103+ * Extract the deterministic expressions in non-deterministic expressions, i.e. 'And' and 'Or'.
104+ *
105+ * Example input:
106+ * {{{
107+ * col = 1 and rand() < 1
108+ * (col1 = 1 and rand() < 1) and col2 = 1
109+ * col1 = 1 or rand() < 1
110+ * (col1 = 1 and rand() < 1) or (col2 = 1 and rand() < 1)
111+ * }}}
112+ *
113+ * Result:
114+ * {{{
115+ * col = 1
116+ * col1 = 1 and col2 = 1
117+ * None
118+ * col1 = 1 or col2 = 1
119+ * }}}
120+ */
121+ private [planning] def extractDeterministicExpressions (expr : Expression ): Option [Expression ] = {
102122 if (expr.deterministic) {
103123 Some (expr)
104124 } else {
105125 expr match {
106126 case And (left, right) =>
107- val leftDeterminedExpr = getDeterminedExpression (left)
108- val rightDeterminedExpr = getDeterminedExpression (right)
127+ val leftDeterminedExpr = extractDeterministicExpressions (left)
128+ val rightDeterminedExpr = extractDeterministicExpressions (right)
109129 if (leftDeterminedExpr.isDefined && rightDeterminedExpr.isDefined) {
110130 Some (And (leftDeterminedExpr.get, rightDeterminedExpr.get))
111131 } else if (leftDeterminedExpr.isDefined || rightDeterminedExpr.isDefined) {
112132 Some (leftDeterminedExpr.getOrElse(rightDeterminedExpr.get))
113133 } else {
114134 None
115135 }
136+ case Or (left, right) =>
137+ val leftDeterminedExpr = extractDeterministicExpressions(left)
138+ val rightDeterminedExpr = extractDeterministicExpressions(right)
139+ if (leftDeterminedExpr.isDefined && rightDeterminedExpr.isDefined) {
140+ Some (Or (leftDeterminedExpr.get, rightDeterminedExpr.get))
141+ } else {
142+ None
143+ }
116144 case _ =>
117145 None
118146 }
0 commit comments