@@ -1983,23 +1983,25 @@ public RelNode visitChart(Chart node, CalcitePlanContext context) {
19831983 // If row or column split does not present or limit equals 0, this is the same as `stats agg
19841984 // [group by col]`
19851985
1986- Integer limit =
1987- Optional .ofNullable (argMap .get ("limit" )).map (l -> (Integer ) l .getValue ()).orElse (10 );
1988- Boolean top =
1989- Optional .ofNullable (argMap .get ("top" )).map (t -> (Boolean ) t .getValue ()).orElse (true );
1990- Boolean useOther =
1991- Optional .ofNullable (argMap .get ("useother" )).map (u -> (Boolean ) u .getValue ()).orElse (true );
1992- String otherStr =
1993- Optional .ofNullable (argMap .get ("otherstr" )).map (o -> (String ) o .getValue ()).orElse ("OTHER" );
1986+ Integer limit = (Integer ) argMap .getOrDefault ("limit" , Chart .DEFAULT_LIMIT ).getValue ();
19941987 if (node .getRowSplit () == null || node .getColumnSplit () == null || Objects .equals (limit , 0 )) {
19951988 return aggregated .getLeft ();
19961989 }
1997- List <RexNode > projected = aggregated .getRight ();
1990+
1991+ Boolean top = (Boolean ) argMap .getOrDefault ("top" , Chart .DEFAULT_TOP ).getValue ();
1992+ Boolean useOther =
1993+ (Boolean ) argMap .getOrDefault ("useother" , Chart .DEFAULT_USE_OTHER ).getValue ();
1994+ Boolean useNull = (Boolean ) argMap .getOrDefault ("usenull" , Chart .DEFAULT_USE_NULL ).getValue ();
1995+ String otherStr = (String ) argMap .getOrDefault ("otherstr" , Chart .DEFAULT_OTHER_STR ).getValue ();
1996+ String nullStr = (String ) argMap .getOrDefault ("nullstr" , Chart .DEFAULT_NULL_STR ).getValue ();
1997+
19981998 String columSplitName = aggregated .getLeft ().getRowType ().getFieldNames ().getLast ();
19991999 RelBuilder relBuilder = context .relBuilder ;
20002000 // 0: agg; 2: column-split
20012001 relBuilder .project (relBuilder .field (0 ), relBuilder .field (2 ));
2002- relBuilder .filter (relBuilder .isNotNull (relBuilder .field (1 )));
2002+ if (!useNull ) {
2003+ relBuilder .filter (relBuilder .isNotNull (relBuilder .field (1 )));
2004+ }
20032005 // 1: column split; 0: agg
20042006 relBuilder .aggregate (
20052007 relBuilder .groupKey (relBuilder .field (1 )),
@@ -2008,11 +2010,13 @@ public RelNode visitChart(Chart node, CalcitePlanContext context) {
20082010 if (top ) {
20092011 grandTotal = relBuilder .desc (grandTotal );
20102012 }
2013+ // Always set it to null last so that it does not interfere with top / bottom calculation
2014+ grandTotal = relBuilder .nullsLast (grandTotal );
20112015 RexNode rowNum =
20122016 PlanUtils .makeOver (
20132017 context ,
20142018 BuiltinFunctionName .ROW_NUMBER ,
2015- relBuilder .literal (1 ),
2019+ relBuilder .literal (1 ), // dummy expression for row number calculation
20162020 List .of (),
20172021 List .of (),
20182022 List .of (grandTotal ),
@@ -2025,26 +2029,29 @@ public RelNode visitChart(Chart node, CalcitePlanContext context) {
20252029
20262030 // on column-split = group key
20272031 relBuilder .join (
2028- JoinRelType .INNER , relBuilder .equals (relBuilder .field (2 , 0 , 2 ), relBuilder .field (2 , 1 , 0 )));
2032+ JoinRelType .LEFT , relBuilder .equals (relBuilder .field (2 , 0 , 2 ), relBuilder .field (2 , 1 , 0 )));
20292033
2030- RexNode condition =
2034+ RexNode colSplitPostJoin = relBuilder .field (2 );
2035+ RexNode lteCondition =
20312036 relBuilder .call (
20322037 SqlStdOperatorTable .LESS_THAN_OR_EQUAL ,
20332038 relBuilder .field ("__row_number__" ),
20342039 relBuilder .literal (limit ));
2040+ RexNode nullCondition = relBuilder .isNull (colSplitPostJoin );
20352041 RexNode columnSplitExpr ;
2036- if (useOther ) {
2037- columnSplitExpr =
2038- relBuilder .call (
2039- SqlStdOperatorTable .CASE ,
2040- condition ,
2041- relBuilder .field (2 ),
2042- relBuilder .literal (otherStr ));
2043- } else {
2044- relBuilder .filter (condition );
2045- columnSplitExpr = relBuilder .field (2 );
2042+ if (!useOther ) {
2043+ relBuilder .filter (lteCondition );
20462044 }
20472045
2046+ columnSplitExpr =
2047+ relBuilder .call (
2048+ SqlStdOperatorTable .CASE ,
2049+ nullCondition ,
2050+ relBuilder .literal (nullStr ),
2051+ lteCondition ,
2052+ relBuilder .field (2 ),
2053+ relBuilder .literal (otherStr ));
2054+
20482055 relBuilder .project (
20492056 relBuilder .field (0 ),
20502057 relBuilder .field (1 ),
0 commit comments