19
19
20
20
import java .util .ArrayList ;
21
21
import java .util .BitSet ;
22
+ import java .util .HashSet ;
22
23
import java .util .LinkedHashSet ;
23
24
import java .util .List ;
24
25
import java .util .Set ;
26
+ import java .util .stream .Collectors ;
25
27
28
+ import org .apache .commons .collections .CollectionUtils ;
29
+ import org .apache .doris .catalog .Type ;
26
30
import org .apache .doris .common .AnalysisException ;
27
31
import org .apache .logging .log4j .LogManager ;
28
32
import org .apache .logging .log4j .Logger ;
@@ -47,10 +51,10 @@ public class GroupByClause implements ParseNode {
47
51
private GroupingType groupingType ;
48
52
private SyntaxType syntaxType ;
49
53
private ArrayList <Expr > groupingExprs ;
50
- private ArrayList <Expr > groupingExprsForPrint ;
54
+ private ArrayList <Expr > oriGroupingExprs ;
51
55
private List <BitSet > groupingIdList ;
52
56
// grouping functions virtual slot
53
- private List < SlotRef > groupingSlots ;
57
+ private Set < VirtualSlotRef > groupingSlots ;
54
58
// reserve this info for toSQL
55
59
private List <ArrayList <Expr >> groupingSetList ;
56
60
private ArrayList <Expr > groupByExprs ;
@@ -64,24 +68,26 @@ public GroupByClause(List<ArrayList<Expr>> groupingSetList, ArrayList<Expr> grou
64
68
this .groupingIdList = new ArrayList <>();
65
69
this .groupByExprs = groupByExprs ;
66
70
Preconditions .checkState (type == GroupingType .GROUPING_SETS );
67
- groupingExprsForPrint = null ;
68
- groupingSlots = new ArrayList <>();
71
+ groupingSlots = new HashSet <>();
69
72
virtualTuple = null ;
70
73
}
71
74
72
75
public GroupByClause (ArrayList <Expr > groupingExprs , GroupingType type , SyntaxType syntaxType ) {
73
76
this .groupingType = type ;
74
77
this .syntaxType = syntaxType ;
75
- this .groupingExprs = groupingExprs ;
78
+ this .oriGroupingExprs = groupingExprs ;
79
+ this .groupingExprs = new ArrayList <>();
80
+ this .groupingExprs .addAll (oriGroupingExprs );
76
81
this .groupingIdList = new ArrayList <>();
77
82
Preconditions .checkState (type != GroupingType .GROUPING_SETS );
78
- groupingExprsForPrint = Expr .cloneList (groupingExprs );
79
- groupingSlots = new ArrayList <>();
83
+ groupingSlots = new HashSet <>();
80
84
virtualTuple = null ;
81
85
}
82
86
protected GroupByClause (GroupByClause other ) {
83
87
this .groupingType = other .groupingType ;
84
88
this .groupingExprs = (other .groupingExprs != null ) ? Expr .cloneAndResetList (other .groupingExprs ) : null ;
89
+ this .oriGroupingExprs =
90
+ (other .oriGroupingExprs != null ) ? Expr .cloneAndResetList (other .oriGroupingExprs ) : null ;
85
91
if (other .groupingIdList != null ) {
86
92
this .groupingIdList = new ArrayList <>();
87
93
for (BitSet bitSet : other .groupingIdList ) {
@@ -97,67 +103,75 @@ protected GroupByClause(GroupByClause other) {
97
103
this .groupingSetList .add (Expr .cloneAndResetList (exprList ));
98
104
}
99
105
}
100
- if (other .groupingExprsForPrint != null ) {
101
- this .groupingExprsForPrint = Expr .cloneAndResetList (other .groupingExprsForPrint );
102
- }
103
106
if (other .groupingSlots != null ) {
104
- this .groupingSlots = Expr .cloneList (other .groupingSlots );
107
+ this .groupingSlots = new HashSet <>( Expr .cloneList (new ArrayList ( other .groupingSlots )) );
105
108
}
106
109
this .virtualTuple = other .virtualTuple ;
107
110
}
108
111
109
- public void setVirtualTuple (TupleDescriptor virtualTuple ) {
110
- this .virtualTuple = virtualTuple ;
111
- }
112
-
113
- public List <SlotRef > getGroupingSlots () {
114
- return groupingSlots ;
112
+ public void reset () {
113
+ groupingExprs = new ArrayList <>();
114
+ analyzed_ = false ;
115
+ exprGenerated = false ;
116
+ if (oriGroupingExprs != null ) {
117
+ Expr .resetList (oriGroupingExprs );
118
+ groupingExprs .addAll (oriGroupingExprs );
119
+ }
120
+ groupingIdList = new ArrayList <>();
121
+ groupingSlots = new HashSet <>();
122
+ if (groupingSetList != null ) {
123
+ for (List <Expr > s : groupingSetList ) {
124
+ for (Expr e : s ) {
125
+ if (e != null ) {
126
+ e .reset ();
127
+ }
128
+ }
129
+ }
130
+ }
131
+ virtualTuple = null ;
115
132
}
116
133
117
134
public ArrayList <Expr > getGroupingExprs () {
118
135
Preconditions .checkState (exprGenerated );
119
136
return groupingExprs ;
120
137
}
121
138
122
- public TupleId getGroupingTupleId () {
123
- if (!isGroupByExtension () || virtualTuple == null ) {
139
+ public TupleDescriptor getGroupingTuple () {
140
+ if (!isGroupByExtension ()) {
124
141
return null ;
125
142
}
126
- return virtualTuple . getId () ;
143
+ return virtualTuple ;
127
144
}
128
145
129
- public TupleDescriptor getGroupingTuple ( ) {
130
- if (!isGroupByExtension () || virtualTuple == null ) {
146
+ public TupleDescriptor getVirtualTuple ( Analyzer analyzer ) {
147
+ if (!isGroupByExtension ()) {
131
148
return null ;
149
+ } else if (virtualTuple == null ) {
150
+ virtualTuple = analyzer .getDescTbl ().createTupleDescriptor (VIRTUAL_TUPLE );
132
151
}
133
152
return virtualTuple ;
134
153
}
135
154
136
- public void genVirtualTuple (Analyzer analyzer ) {
137
- virtualTuple = analyzer .getDescTbl ().createTupleDescriptor (VIRTUAL_TUPLE );
138
- analyzer .setGroupingVirtualTuple (virtualTuple );
139
- }
140
-
141
155
public void genGroupingExprs (Analyzer analyzer ) throws AnalysisException {
142
156
if (exprGenerated ) {
143
157
return ;
144
158
}
145
- if (groupingExprs != null && ! groupingExprs . isEmpty ( )) {
159
+ if (CollectionUtils . isNotEmpty ( groupingExprs )) {
146
160
// remove repeated element
147
161
Set <Expr > groupingExprSet = new LinkedHashSet <>(groupingExprs );
148
162
groupingExprs .clear ();
149
163
groupingExprs .addAll (groupingExprSet );
150
164
}
151
165
if (groupingType == GroupingType .CUBE || groupingType == GroupingType .ROLLUP ) {
152
- if (groupingExprs == null || groupingExprs .isEmpty ()) {
166
+ if (CollectionUtils .isEmpty (groupingExprs )) {
153
167
throw new AnalysisException (
154
168
"The expresions in GROUPING CUBE or ROLLUP can not be empty" );
155
169
}
156
170
157
171
buildGroupingClause (analyzer );
158
172
159
173
} else if (groupingType == GroupingType .GROUPING_SETS ) {
160
- if (groupingSetList == null || groupingSetList .isEmpty ()) {
174
+ if (CollectionUtils .isEmpty (groupingSetList )) {
161
175
throw new AnalysisException ("The expresions in GROUPINGING SETS can not be empty" );
162
176
}
163
177
// collect all Expr elements
@@ -230,25 +244,23 @@ public void analyze(Analyzer analyzer) throws AnalysisException {
230
244
}
231
245
232
246
public boolean isGroupByExtension () {
233
- if (groupingType != GroupingType .GROUPING_SETS
234
- && groupingType != GroupingType .CUBE
235
- && groupingType != GroupingType .ROLLUP ) {
247
+ if (groupingType == GroupingType .GROUP_BY ||
248
+ groupingType == GroupingType .GROUPING_SETS && (groupingSetList == null || groupingSetList .size () < 2 )) {
236
249
return false ;
250
+ } else {
251
+ return true ;
237
252
}
238
-
239
- return groupingType != GroupingType .GROUPING_SETS ||
240
- groupingSetList == null || groupingSetList .size () > 1 ;
241
253
}
242
254
243
255
@ Override
244
256
public String toSql () {
245
257
StringBuilder strBuilder = new StringBuilder ();
246
258
switch (groupingType ) {
247
259
case GROUP_BY :
248
- if (groupingExprsForPrint != null ) {
249
- for (int i = 0 ; i < groupingExprsForPrint .size (); ++i ) {
250
- strBuilder .append (groupingExprsForPrint .get (i ).toSql ());
251
- strBuilder .append ((i + 1 != groupingExprsForPrint .size ()) ? ", " : "" );
260
+ if (oriGroupingExprs != null ) {
261
+ for (int i = 0 ; i < oriGroupingExprs .size (); ++i ) {
262
+ strBuilder .append (oriGroupingExprs .get (i ).toSql ());
263
+ strBuilder .append ((i + 1 != oriGroupingExprs .size ()) ? ", " : "" );
252
264
}
253
265
}
254
266
break ;
@@ -279,32 +291,32 @@ public String toSql() {
279
291
}
280
292
break ;
281
293
case CUBE :
282
- if (groupingExprsForPrint != null && syntaxType == SyntaxType .ORACLE ) {
294
+ if (oriGroupingExprs != null && syntaxType == SyntaxType .ORACLE ) {
283
295
strBuilder .append ("CUBE (" );
284
- for (int i = 0 ; i < groupingExprsForPrint .size (); ++i ) {
285
- strBuilder .append (groupingExprsForPrint .get (i ).toSql ());
286
- strBuilder .append ((i + 1 != groupingExprsForPrint .size ()) ? ", " : "" );
296
+ for (int i = 0 ; i < oriGroupingExprs .size (); ++i ) {
297
+ strBuilder .append (oriGroupingExprs .get (i ).toSql ());
298
+ strBuilder .append ((i + 1 != oriGroupingExprs .size ()) ? ", " : "" );
287
299
}
288
300
strBuilder .append (")" );
289
- } else if (groupingExprsForPrint != null && syntaxType == SyntaxType .HIVE ) {
290
- for (int i = 0 ; i < groupingExprsForPrint .size (); ++i ) {
291
- strBuilder .append (groupingExprsForPrint .get (i ).toSql ());
292
- strBuilder .append ((i + 1 != groupingExprsForPrint .size ()) ? ", " : " WITH CUBE" );
301
+ } else if (oriGroupingExprs != null && syntaxType == SyntaxType .HIVE ) {
302
+ for (int i = 0 ; i < oriGroupingExprs .size (); ++i ) {
303
+ strBuilder .append (oriGroupingExprs .get (i ).toSql ());
304
+ strBuilder .append ((i + 1 != oriGroupingExprs .size ()) ? ", " : " WITH CUBE" );
293
305
}
294
306
}
295
307
break ;
296
308
case ROLLUP :
297
- if (groupingExprsForPrint != null && syntaxType == SyntaxType .ORACLE ) {
309
+ if (oriGroupingExprs != null && syntaxType == SyntaxType .ORACLE ) {
298
310
strBuilder .append ("ROLLUP (" );
299
- for (int i = 0 ; i < groupingExprsForPrint .size (); ++i ) {
300
- strBuilder .append (groupingExprsForPrint .get (i ).toSql ());
301
- strBuilder .append ((i + 1 != groupingExprsForPrint .size ()) ? ", " : "" );
311
+ for (int i = 0 ; i < oriGroupingExprs .size (); ++i ) {
312
+ strBuilder .append (oriGroupingExprs .get (i ).toSql ());
313
+ strBuilder .append ((i + 1 != oriGroupingExprs .size ()) ? ", " : "" );
302
314
}
303
315
strBuilder .append (")" );
304
- } else if (groupingExprsForPrint != null && syntaxType == SyntaxType .HIVE ) {
305
- for (int i = 0 ; i < groupingExprsForPrint .size (); ++i ) {
306
- strBuilder .append (groupingExprsForPrint .get (i ).toSql ());
307
- strBuilder .append ((i + 1 != groupingExprsForPrint .size ()) ? ", " : " WITH ROLLUP" );
316
+ } else if (oriGroupingExprs != null && syntaxType == SyntaxType .HIVE ) {
317
+ for (int i = 0 ; i < oriGroupingExprs .size (); ++i ) {
318
+ strBuilder .append (oriGroupingExprs .get (i ).toSql ());
319
+ strBuilder .append ((i + 1 != oriGroupingExprs .size ()) ? ", " : " WITH ROLLUP" );
308
320
}
309
321
}
310
322
break ;
@@ -319,20 +331,24 @@ public GroupByClause clone() {
319
331
return new GroupByClause (this );
320
332
}
321
333
322
- public void reset () {
323
- if (groupingExprs != null ) {
324
- Expr .resetList (groupingExprs );
325
- }
326
- this .analyzed_ = false ;
327
- }
328
-
329
334
public boolean isEmpty () {
330
- return groupingExprs == null || groupingExprs .isEmpty ();
335
+ return CollectionUtils .isEmpty (groupingExprs );
331
336
}
332
337
333
- public void addGroupingCol (List <VirtualSlotRef > vSlots ) {
334
- groupingSlots .addAll (vSlots );
335
- groupingExprs .addAll (groupingSlots );
338
+ public VirtualSlotRef addGroupingSlots (List <SlotRef > realSlots , Analyzer analyzer ) throws AnalysisException {
339
+ String colName = realSlots .stream ().map (SlotRef ::getColumnName ).collect (Collectors .joining ("_" ));
340
+ colName = "GROUPING_PREFIX_" + colName ;
341
+ VirtualSlotRef virtualSlot = new VirtualSlotRef (colName , Type .BIGINT , getVirtualTuple (analyzer ), realSlots );
342
+ virtualSlot .analyze (analyzer );
343
+ if (groupingSlots .contains (virtualSlot )) {
344
+ for (VirtualSlotRef vs : groupingSlots ) {
345
+ if (vs .equals (virtualSlot )) {
346
+ return vs ;
347
+ }
348
+ }
349
+ }
350
+ groupingSlots .add (virtualSlot );
351
+ return virtualSlot ;
336
352
}
337
353
338
354
private void buildGroupingClause (Analyzer analyzer ) {
0 commit comments