Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 29.4k
[SPARK-13739] [SQL] Push Predicate Through Window#11635
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
01e4cdf68357049180687b38a21ed2b84affda8025ac0dccd6e0018b0546772b37a64fc2a872cab6dbd742763562dab70804587701debdfa763706d4de6ec19422a4f52bdf481e95df3fab24cf8b2e33b2ee1876b9f0090ade6f7e9fd63d25199d49404214cc001dd959daa4841d5f64472a6e3458f7be92136ddf401d8b0fba10a3aea1dad420246c05b4ae6db19408fa0294cbf73b3c08f561474df883d9828d72d236107afea58bf200787a165bb9359cdb0d7b3b65bd090babf2da9e0946950a8e4af3337fa09cc36d83a19150483145236a5f4417bdb4cc5f0bd436359ffae2694875d6b604699235c4f4d3c4dedd23eaeaa5e427ce9File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -758,4 +758,223 @@ class FilterPushdownSuite extends PlanTest { | ||||||||||||||||||||||||||||||||||||||||
| val correctedAnswer = agg.copy(child = agg.child.where(a > 1 && b > 2)).analyze | ||||||||||||||||||||||||||||||||||||||||
| comparePlans(optimized, correctedAnswer) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| test("Window: predicate push down -- basic") { | ||||||||||||||||||||||||||||||||||||||||
| val winExpr = windowExpr(count('b), windowSpec('a :: Nil, 'b.asc :: Nil, UnspecifiedFrame)) | ||||||||||||||||||||||||||||||||||||||||
| val originalQuery = testRelation.select('a, 'b, 'c, winExpr.as('window)).where('a > 1) | ||||||||||||||||||||||||||||||||||||||||
| val correctAnswer = testRelation | ||||||||||||||||||||||||||||||||||||||||
| .where('a > 1).select('a, 'b, 'c) | ||||||||||||||||||||||||||||||||||||||||
| .window(winExpr.as('window) :: Nil, 'a :: Nil, 'b.asc :: Nil) | ||||||||||||||||||||||||||||||||||||||||
| .select('a, 'b, 'c, 'window).analyze | ||||||||||||||||||||||||||||||||||||||||
| comparePlans(Optimize.execute(originalQuery.analyze), correctAnswer) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| test("Window: predicate push down -- predicates with compound predicate using only one column") { | ||||||||||||||||||||||||||||||||||||||||
| val winExpr = | ||||||||||||||||||||||||||||||||||||||||
| windowExpr(count('b), windowSpec('a.attr :: 'b.attr :: Nil, 'b.asc :: Nil, UnspecifiedFrame)) | ||||||||||||||||||||||||||||||||||||||||
| val originalQuery = testRelation.select('a, 'b, 'c, winExpr.as('window)).where('a * 3 > 15) | ||||||||||||||||||||||||||||||||||||||||
| val correctAnswer = testRelation | ||||||||||||||||||||||||||||||||||||||||
| .where('a * 3 > 15).select('a, 'b, 'c) | ||||||||||||||||||||||||||||||||||||||||
| .window(winExpr.as('window) :: Nil, 'a.attr :: 'b.attr :: Nil, 'b.asc :: Nil) | ||||||||||||||||||||||||||||||||||||||||
| .select('a, 'b, 'c, 'window).analyze | ||||||||||||||||||||||||||||||||||||||||
| comparePlans(Optimize.execute(originalQuery.analyze), correctAnswer) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| test("Window: predicate push down -- multi window expressions with the same window spec") { | ||||||||||||||||||||||||||||||||||||||||
| val winSpec = windowSpec('a.attr :: 'b.attr :: Nil, 'b.asc :: Nil, UnspecifiedFrame) | ||||||||||||||||||||||||||||||||||||||||
| val winExpr1 = windowExpr(count('b), winSpec) | ||||||||||||||||||||||||||||||||||||||||
| val winExpr2 = windowExpr(sum('b), winSpec) | ||||||||||||||||||||||||||||||||||||||||
| val originalQuery = testRelation | ||||||||||||||||||||||||||||||||||||||||
| .select('a, 'b, 'c, winExpr1.as('window1), winExpr2.as('window2)).where('a > 1) | ||||||||||||||||||||||||||||||||||||||||
| val correctAnswer = testRelation | ||||||||||||||||||||||||||||||||||||||||
| .where('a > 1).select('a, 'b, 'c) | ||||||||||||||||||||||||||||||||||||||||
| .window(winExpr1.as('window1) :: winExpr2.as('window2) :: Nil, | ||||||||||||||||||||||||||||||||||||||||
| 'a.attr :: 'b.attr :: Nil, 'b.asc :: Nil) | ||||||||||||||||||||||||||||||||||||||||
| .select('a, 'b, 'c, 'window1, 'window2).analyze | ||||||||||||||||||||||||||||||||||||||||
| comparePlans(Optimize.execute(originalQuery.analyze), correctAnswer) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| test("Window: predicate push down -- multi window specification - 1") { | ||||||||||||||||||||||||||||||||||||||||
| // order by clauses are different between winSpec1 and winSpec2 | ||||||||||||||||||||||||||||||||||||||||
| val winSpec1 = windowSpec('a.attr :: 'b.attr :: Nil, 'b.asc :: Nil, UnspecifiedFrame) | ||||||||||||||||||||||||||||||||||||||||
| val winExpr1 = windowExpr(count('b), winSpec1) | ||||||||||||||||||||||||||||||||||||||||
| val winSpec2 = windowSpec('a.attr :: 'b.attr :: Nil, 'a.asc :: Nil, UnspecifiedFrame) | ||||||||||||||||||||||||||||||||||||||||
| val winExpr2 = windowExpr(count('b), winSpec2) | ||||||||||||||||||||||||||||||||||||||||
| val originalQuery = testRelation | ||||||||||||||||||||||||||||||||||||||||
| .select('a, 'b, 'c, winExpr1.as('window1), winExpr2.as('window2)).where('a > 1) | ||||||||||||||||||||||||||||||||||||||||
| val correctAnswer1 = testRelation | ||||||||||||||||||||||||||||||||||||||||
| .where('a > 1).select('a, 'b, 'c) | ||||||||||||||||||||||||||||||||||||||||
| .window(winExpr1.as('window1) :: Nil, 'a.attr :: 'b.attr :: Nil, 'b.asc :: Nil) | ||||||||||||||||||||||||||||||||||||||||
| .window(winExpr2.as('window2) :: Nil, 'a.attr :: 'b.attr :: Nil, 'a.asc :: Nil) | ||||||||||||||||||||||||||||||||||||||||
| .select('a, 'b, 'c, 'window1, 'window2).analyze | ||||||||||||||||||||||||||||||||||||||||
| val correctAnswer2 = testRelation | ||||||||||||||||||||||||||||||||||||||||
| .where('a > 1).select('a, 'b, 'c) | ||||||||||||||||||||||||||||||||||||||||
| .window(winExpr2.as('window2) :: Nil, 'a.attr :: 'b.attr :: Nil, 'a.asc :: Nil) | ||||||||||||||||||||||||||||||||||||||||
| .window(winExpr1.as('window1) :: Nil, 'a.attr :: 'b.attr :: Nil, 'b.asc :: Nil) | ||||||||||||||||||||||||||||||||||||||||
| .select('a, 'b, 'c, 'window1, 'window2).analyze | ||||||||||||||||||||||||||||||||||||||||
| // When Analyzer adding Window operators after grouping the extracted Window Expressions | ||||||||||||||||||||||||||||||||||||||||
| // based on their Partition and Order Specs, the order of Window operators is | ||||||||||||||||||||||||||||||||||||||||
| // non-deterministic. Thus, we have two correct plans | ||||||||||||||||||||||||||||||||||||||||
| val optimizedQuery = Optimize.execute(originalQuery.analyze) | ||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||
| valgroupedWindowExpressions= extractedWindowExprBuffer.groupBy { expr => | |
| valdistinctWindowSpec= expr.collect { | |
| casewindow: WindowExpression=> window.windowSpec | |
| }.distinct | |
| // We do a final check and see if we only have a single Window Spec defined in an | |
| // expressions. | |
| if (distinctWindowSpec.length ==0 ) { | |
| failAnalysis(s"$expr does not have any WindowExpression.") | |
| } elseif (distinctWindowSpec.length >1) { | |
| // newExpressionsWithWindowFunctions only have expressions with a single | |
| // WindowExpression. If we reach here, we have a bug. | |
| failAnalysis(s"$expr has multiple Window Specifications ($distinctWindowSpec)."+ | |
| s"Please file a bug report with this error message, stack trace, and the query.") | |
| } else { | |
| valspec= distinctWindowSpec.head | |
| (spec.partitionSpec, spec.orderSpec) | |
| } | |
| }.toSeq |
I did not change the behavior of the source codes since the orders of Window only matter for verifying the test cases. The order will not change the results.
Previously, I saw different orders in multiple runs. Thus, I am afraid the way you mentioned does not work too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a line of documentation to explain why you are using try/catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Math.pow(NIT, 100): What does the style guide say about ternary expression onliners?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nevermind, I looked it up. It is allowed.