001package gudusoft.gsqlparser.nodes;
002
003import gudusoft.gsqlparser.ESqlClause;
004import gudusoft.gsqlparser.TCustomSqlStatement;
005import gudusoft.gsqlparser.TSourceToken;
006import gudusoft.gsqlparser.nodes.couchbase.TBinding;
007
008/**
009 * This class represents group by clause and having clause.
010 * <p>
011 * <p>Specify the GROUP BY clause if you want the database to group the selected rows based on
012 * the value of expr(s) for each row and return a single row of summary information for each group.
013 * <p>If this clause contains CUBE or ROLLUP extensions, then the database
014 * produces superaggregate groupings in addition to the regular groupings.
015 * <p>
016 * <p>Use the HAVING clause to restrict the groups of returned rows to those groups for
017 * which the specified condition is TRUE. If you omit this clause, then the database returns summary rows for all groups.
018 */
019public class TGroupBy extends TParseTreeNode {
020
021    private TQualifyClause qualifyClause;
022
023    public void setQualifyClause(TQualifyClause qualifyClause) {
024        this.qualifyClause = qualifyClause;
025    }
026
027    public TQualifyClause getQualifyClause() {
028        return qualifyClause;
029    }
030
031    private TPTNodeList<TBinding> bindings;
032
033    public TPTNodeList<TBinding> getBindings() {
034        return bindings;
035    }
036
037    private TGroupByItemList items = null;
038    private TExpression havingClause = null;
039
040    private TSourceToken GROUP= null;
041    private TSourceToken BY= null;
042    private TSourceToken ALL= null;
043
044    private boolean rollupModifier = false;
045    private boolean cubeModifier = false;
046    private boolean totalsModifier = false;
047    private boolean allModifier = false;
048
049    public void setCubeModifier(boolean cubeModifier) {
050        this.cubeModifier = cubeModifier;
051    }
052
053    public boolean isCubeModifier() {
054        return cubeModifier;
055    }
056
057    public void setRollupModifier(boolean rollupModifier) {
058        this.rollupModifier = rollupModifier;
059    }
060
061    public boolean isRollupModifier() {
062
063        return rollupModifier;
064    }
065
066    /**
067     * Sets whether this GROUP BY clause uses the WITH TOTALS modifier.
068     * <p>WITH TOTALS adds an extra row with totals to the result,
069     * which is the sum across all values in the column.
070     * <p>Applies to ClickHouse.
071     *
072     * @param totalsModifier true if WITH TOTALS is used, false otherwise
073     */
074    public void setTotalsModifier(boolean totalsModifier) {
075        this.totalsModifier = totalsModifier;
076    }
077
078    /**
079     * Returns whether this GROUP BY clause uses the WITH TOTALS modifier.
080     * <p>WITH TOTALS adds an extra row with totals to the result.
081     *
082     * @return true if WITH TOTALS is used, false otherwise
083     */
084    public boolean isTotalsModifier() {
085        return totalsModifier;
086    }
087
088    /**
089     * Sets whether this GROUP BY clause uses the ALL modifier.
090     * <p>GROUP BY ALL is a shorthand notation to add all SELECT-list expressions
091     * not containing aggregate functions as group expressions.
092     * <p>Applies to Databricks SQL Databricks Runtime 12.2 LTS and above.
093     *
094     * @param allModifier true if GROUP BY ALL is used, false otherwise
095     */
096    public void setAllModifier(boolean allModifier) {
097        this.allModifier = allModifier;
098    }
099
100    /**
101     * Returns whether this GROUP BY clause uses the ALL modifier.
102     * <p>GROUP BY ALL automatically groups by all non-aggregate expressions
103     * in the SELECT clause.
104     *
105     * @return true if GROUP BY ALL is used, false otherwise
106     */
107    public boolean isAllModifier() {
108        return allModifier;
109    }
110
111    public void setBY(TSourceToken BY) {
112        this.BY = BY;
113    }
114
115    public void setGROUP(TSourceToken GROUP) {
116        this.GROUP = GROUP;
117    }
118
119    public void setHAVING(TSourceToken HAVING) {
120        this.HAVING = HAVING;
121    }
122
123    /**
124     * Sets the ALL token for GROUP BY ALL syntax.
125     *
126     * @param ALL the ALL token
127     */
128    public void setALL(TSourceToken ALL) {
129        this.ALL = ALL;
130    }
131
132    public TSourceToken getBY() {
133
134        return BY;
135    }
136
137    public TSourceToken getGROUP() {
138        return GROUP;
139    }
140
141    public TSourceToken getHAVING() {
142        return HAVING;
143    }
144
145    /**
146     * Gets the ALL token for GROUP BY ALL syntax.
147     *
148     * @return the ALL token, or null if GROUP BY ALL is not used
149     */
150    public TSourceToken getALL() {
151        return ALL;
152    }
153
154    private TSourceToken HAVING= null;
155
156    /**
157     * Restrict the groups of returned rows to those groups for which the specified condition is TRUE.
158     * <p>If you omit this clause, then the database returns summary rows for all groups.
159     * @return
160     */
161    public TExpression getHavingClause() {
162        return havingClause;
163    }
164
165    /**
166     *
167     * @return Items in group by clause, can be expr, rollup_cube_clause and grouping_sets_clause.
168     * @see TExpression
169     * @see TRollupCube
170     * @see TGroupingSet
171     */
172    public TGroupByItemList getItems() {
173        if (items == null){
174            items = new TGroupByItemList();
175        }
176        return items;
177    }
178
179    public void setHavingClause(TExpression havingClause) {
180        this.havingClause = havingClause;
181        if ((this.getHAVING() != null)&&(this.havingClause == null)){
182            this.getHAVING().removeFromChain();
183        }
184    }
185
186    public void init(Object arg1){
187        bindings = (TPTNodeList<TBinding>)arg1;
188    }
189
190    public void init(Object arg1,Object arg2)
191    {
192        if (arg1 != null){
193            if (arg1 instanceof TGroupByItemList){
194                items = (TGroupByItemList)arg1;
195            }else if (arg1 instanceof TExpressionList){
196                items = new TGroupByItemList();
197                TExpressionList expressionList  = (TExpressionList)arg1;
198                for(int i=0;i<expressionList.size();i++ ){
199                    TGroupByItem item = new TGroupByItem();
200                    item.setExpr(expressionList.getExpression(i));
201                    item.setStartToken(expressionList.getExpression(i));
202                    item.setEndToken(expressionList.getExpression(i));
203                    items.addGroupByItem(item);
204                }
205            }
206        }
207        if (arg2 != null){
208            havingClause = (TExpression)arg2;
209        }
210    }
211
212    public void doParse(TCustomSqlStatement psql, ESqlClause plocation){
213        if (items != null){
214            items.doParse(psql,plocation);
215        }
216        if (havingClause != null){
217            havingClause.doParse(psql,ESqlClause.having);
218        }
219    }
220
221    public void setBindings(TPTNodeList<TBinding> bindings) {
222        this.bindings = bindings;
223    }
224
225    public void accept(TParseTreeVisitor v){
226        v.preVisit(this);
227        v.postVisit(this);
228    }
229
230    public void acceptChildren(TParseTreeVisitor v){
231        v.preVisit(this);
232        if (this.getItems() != null){
233            this.getItems().acceptChildren(v);
234        }
235
236        if (this.getHavingClause() != null){
237            this.getHavingClause().acceptChildren(v);
238        }
239        v.postVisit(this);
240    }
241
242    public void setItems(TGroupByItemList items) {
243        this.items = items;
244    }
245}