@@ -65,10 +65,13 @@ public class WindowFilterPushDown
6565 private final RowExpressionDomainTranslator domainTranslator ;
6666 private final LogicalRowExpressions logicalRowExpressions ;
6767
68- public WindowFilterPushDown (Metadata metadata )
68+ private boolean isNativeExecution ;
69+
70+ public WindowFilterPushDown (Metadata metadata , boolean isNativeExecution )
6971 {
7072 this .metadata = requireNonNull (metadata , "metadata is null" );
7173 this .domainTranslator = new RowExpressionDomainTranslator (metadata );
74+ this .isNativeExecution = isNativeExecution ;
7275 this .logicalRowExpressions = new LogicalRowExpressions (
7376 new RowExpressionDeterminismEvaluator (metadata .getFunctionAndTypeManager ()),
7477 new FunctionResolution (metadata .getFunctionAndTypeManager ().getFunctionAndTypeResolver ()),
@@ -84,7 +87,7 @@ public PlanOptimizerResult optimize(PlanNode plan, Session session, TypeProvider
8487 requireNonNull (variableAllocator , "variableAllocator is null" );
8588 requireNonNull (idAllocator , "idAllocator is null" );
8689
87- Rewriter rewriter = new Rewriter (idAllocator , metadata , domainTranslator , logicalRowExpressions , session );
90+ Rewriter rewriter = new Rewriter (idAllocator , metadata , domainTranslator , logicalRowExpressions , session , isNativeExecution );
8891 PlanNode rewrittenPlan = SimplePlanRewriter .rewriteWith (rewriter , plan , null );
8992 return PlanOptimizerResult .optimizerResult (rewrittenPlan , rewriter .isPlanChanged ());
9093 }
@@ -97,15 +100,17 @@ private static class Rewriter
97100 private final RowExpressionDomainTranslator domainTranslator ;
98101 private final LogicalRowExpressions logicalRowExpressions ;
99102 private final Session session ;
103+ private final boolean isNativeExecution ;
100104 private boolean planChanged ;
101105
102- private Rewriter (PlanNodeIdAllocator idAllocator , Metadata metadata , RowExpressionDomainTranslator domainTranslator , LogicalRowExpressions logicalRowExpressions , Session session )
106+ private Rewriter (PlanNodeIdAllocator idAllocator , Metadata metadata , RowExpressionDomainTranslator domainTranslator , LogicalRowExpressions logicalRowExpressions , Session session , boolean isNativeExecution )
103107 {
104108 this .idAllocator = requireNonNull (idAllocator , "idAllocator is null" );
105109 this .metadata = requireNonNull (metadata , "metadata is null" );
106110 this .domainTranslator = requireNonNull (domainTranslator , "domainTranslator is null" );
107111 this .logicalRowExpressions = logicalRowExpressions ;
108112 this .session = requireNonNull (session , "session is null" );
113+ this .isNativeExecution = isNativeExecution ;
109114 }
110115
111116 public boolean isPlanChanged ()
@@ -138,6 +143,7 @@ public PlanNode visitWindow(WindowNode node, RewriteContext<Void> context)
138143 public PlanNode visitLimit (LimitNode node , RewriteContext <Void > context )
139144 {
140145 // Operators can handle MAX_VALUE rows per page, so do not optimize if count is greater than this value
146+ // TODO (Aditi) : Don't think this check is needed for Native engine.
141147 if (node .getCount () > Integer .MAX_VALUE ) {
142148 return context .defaultRewrite (node );
143149 }
@@ -152,11 +158,11 @@ public PlanNode visitLimit(LimitNode node, RewriteContext<Void> context)
152158 planChanged = true ;
153159 source = rowNumberNode ;
154160 }
155- else if (source instanceof WindowNode && canOptimizeWindowFunction ((WindowNode ) source , metadata .getFunctionAndTypeManager ()) && isOptimizeTopNRowNumber (session )) {
161+ else if (source instanceof WindowNode && canOptimizeWindowFunction ((WindowNode ) source , metadata .getFunctionAndTypeManager (), isNativeExecution ) && isOptimizeTopNRowNumber (session )) {
156162 WindowNode windowNode = (WindowNode ) source ;
157163 // verify that unordered row_number window functions are replaced by RowNumberNode
158164 verify (windowNode .getOrderingScheme ().isPresent ());
159- TopNRowNumberNode topNRowNumberNode = convertToTopNRowNumber (windowNode , limit );
165+ TopNRowNumberNode topNRowNumberNode = convertToTopNRowNumber (windowNode , limit , metadata . getFunctionAndTypeManager () );
160166 if (windowNode .getPartitionBy ().isEmpty ()) {
161167 return topNRowNumberNode ;
162168 }
@@ -183,13 +189,13 @@ public PlanNode visitFilter(FilterNode node, RewriteContext<Void> context)
183189 return rewriteFilterSource (node , source , rowNumberVariable , upperBound .getAsInt ());
184190 }
185191 }
186- else if (source instanceof WindowNode && canOptimizeWindowFunction ((WindowNode ) source , metadata .getFunctionAndTypeManager ()) && isOptimizeTopNRowNumber (session )) {
192+ else if (source instanceof WindowNode && canOptimizeWindowFunction ((WindowNode ) source , metadata .getFunctionAndTypeManager (), isNativeExecution ) && isOptimizeTopNRowNumber (session )) {
187193 WindowNode windowNode = (WindowNode ) source ;
188194 VariableReferenceExpression rowNumberVariable = getOnlyElement (windowNode .getCreatedVariable ());
189195 OptionalInt upperBound = extractUpperBound (tupleDomain , rowNumberVariable );
190196
191197 if (upperBound .isPresent ()) {
192- source = convertToTopNRowNumber (windowNode , upperBound .getAsInt ());
198+ source = convertToTopNRowNumber (windowNode , upperBound .getAsInt (), metadata . getFunctionAndTypeManager () );
193199 planChanged = true ;
194200 return rewriteFilterSource (node , source , rowNumberVariable , upperBound .getAsInt ());
195201 }
@@ -273,13 +279,23 @@ private static RowNumberNode mergeLimit(RowNumberNode node, int newRowCountPerPa
273279 return new RowNumberNode (node .getSourceLocation (), node .getId (), node .getSource (), node .getPartitionBy (), node .getRowNumberVariable (), Optional .of (newRowCountPerPartition ), false , node .getHashVariable ());
274280 }
275281
276- private TopNRowNumberNode convertToTopNRowNumber (WindowNode windowNode , int limit )
282+ private TopNRowNumberNode convertToTopNRowNumber (WindowNode windowNode , int limit , FunctionAndTypeManager functionAndTypeManager )
277283 {
284+ VariableReferenceExpression rowNumberVariable = getOnlyElement (windowNode .getWindowFunctions ().keySet ());
285+ FunctionMetadata functionMetadata = functionAndTypeManager .getFunctionMetadata (windowNode .getWindowFunctions ().get (rowNumberVariable ).getFunctionHandle ());
286+
287+ TopNRowNumberNode .RankingFunction rankingFunction =
288+ isRowNumberMetadata (functionAndTypeManager , functionMetadata ) ?
289+ TopNRowNumberNode .RankingFunction .ROW_NUMBER :
290+ isRankMetadata (functionAndTypeManager , functionMetadata ) ?
291+ TopNRowNumberNode .RankingFunction .RANK :
292+ TopNRowNumberNode .RankingFunction .DENSE_RANK ;
278293 return new TopNRowNumberNode (
279294 windowNode .getSourceLocation (),
280295 idAllocator .getNextId (),
281296 windowNode .getSource (),
282297 windowNode .getSpecification (),
298+ rankingFunction ,
283299 getOnlyElement (windowNode .getCreatedVariable ()),
284300 limit ,
285301 false ,
@@ -288,22 +304,48 @@ private TopNRowNumberNode convertToTopNRowNumber(WindowNode windowNode, int limi
288304
289305 private static boolean canReplaceWithRowNumber (WindowNode node , FunctionAndTypeManager functionAndTypeManager )
290306 {
291- return canOptimizeWindowFunction (node , functionAndTypeManager ) && !node .getOrderingScheme ().isPresent ();
307+ if (node .getWindowFunctions ().size () != 1 ) {
308+ return false ;
309+ }
310+ VariableReferenceExpression rowNumberVariable = getOnlyElement (node .getWindowFunctions ().keySet ());
311+
312+ return isRowNumberMetadata (functionAndTypeManager ,
313+ functionAndTypeManager .getFunctionMetadata (node .getWindowFunctions ().get (rowNumberVariable ).getFunctionHandle ()))
314+ && !node .getOrderingScheme ().isPresent ();
292315 }
293316
294- private static boolean canOptimizeWindowFunction (WindowNode node , FunctionAndTypeManager functionAndTypeManager )
317+ private static boolean canOptimizeWindowFunction (WindowNode node , FunctionAndTypeManager functionAndTypeManager , boolean isNativeExecution )
295318 {
296319 if (node .getWindowFunctions ().size () != 1 ) {
297320 return false ;
298321 }
299322 VariableReferenceExpression rowNumberVariable = getOnlyElement (node .getWindowFunctions ().keySet ());
300- return isRowNumberMetadata (functionAndTypeManager , functionAndTypeManager .getFunctionMetadata (node .getWindowFunctions ().get (rowNumberVariable ).getFunctionHandle ()));
323+ FunctionMetadata functionMetadata = functionAndTypeManager .getFunctionMetadata (node .getWindowFunctions ().get (rowNumberVariable ).getFunctionHandle ());
324+ if (isNativeExecution ) {
325+ return isRowNumberMetadata (functionAndTypeManager , functionMetadata )
326+ || node .getOrderingScheme ().isPresent () && (isRankMetadata (functionAndTypeManager , functionMetadata )
327+ || isDenseRankMetadata (functionAndTypeManager , functionMetadata ));
328+ }
329+
330+ return isRowNumberMetadata (functionAndTypeManager , functionMetadata );
301331 }
302332
303333 private static boolean isRowNumberMetadata (FunctionAndTypeManager functionAndTypeManager , FunctionMetadata functionMetadata )
304334 {
305335 FunctionHandle rowNumberFunction = functionAndTypeManager .lookupFunction ("row_number" , ImmutableList .of ());
306336 return functionMetadata .equals (functionAndTypeManager .getFunctionMetadata (rowNumberFunction ));
307337 }
338+
339+ private static boolean isRankMetadata (FunctionAndTypeManager functionAndTypeManager , FunctionMetadata functionMetadata )
340+ {
341+ FunctionHandle rankFunction = functionAndTypeManager .lookupFunction ("rank" , ImmutableList .of ());
342+ return functionMetadata .equals (functionAndTypeManager .getFunctionMetadata (rankFunction ));
343+ }
344+
345+ private static boolean isDenseRankMetadata (FunctionAndTypeManager functionAndTypeManager , FunctionMetadata functionMetadata )
346+ {
347+ FunctionHandle rankFunction = functionAndTypeManager .lookupFunction ("dense_rank" , ImmutableList .of ());
348+ return functionMetadata .equals (functionAndTypeManager .getFunctionMetadata (rankFunction ));
349+ }
308350 }
309351}
0 commit comments