001package gudusoft.gsqlparser.nodes;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.sqlenv.TSQLTable;
005import gudusoft.gsqlparser.visitors.TColumnNameVisitor;
006
007import java.util.ArrayList;
008
009/**
010*  use the PIVOT and UNPIVOT relational operators to change a table-valued expression into another table. 
011*/
012
013public class TPivotClause extends TNodeWithAliasClause implements IRelation {
014
015
016    ArrayList<TAttributeNode> relationAttributes = new ArrayList<>();
017    @Override
018    public ArrayList<TAttributeNode> getAttributes(){
019        return relationAttributes;
020    }
021
022    @Override
023    public int size(){
024        return relationAttributes.size();
025    }
026
027    @Override
028    public String getRelationName(){
029        return displayName;
030    };
031
032    private String displayName;
033    public String getDisplayName(){
034        return displayName;
035    }
036    public void initAttributes(){
037        displayName = "";
038        ArrayList<String> columns = new ArrayList<>();
039
040        switch (getType()) {
041            case pivot:
042                displayName = TTable.PIVOT_CLAUSE_ALIAS;
043                if (pivotInClause.getItems() != null){
044                    for(TResultColumn resultColumn: pivotInClause.getItems()){
045                        columns.add(resultColumn.getDisplayName());
046                    }
047                }
048                break;
049            case unpivot:
050                displayName = TTable.UNPIVOT_CLAUSE_ALIAS;
051                break;
052        }
053
054
055        if (getAliasClause() != null){
056            displayName = getAliasClause().getAliasName().toString();
057            if (getAliasClause().getColumns() != null){
058                columns.clear();
059                for(TObjectName column:getAliasClause().getColumns()){
060
061                    columns.add(column.toString());
062                }
063            }
064        }
065
066        for(String c:columns){
067            TAttributeNode node = new TAttributeNode(displayName+"."+c,pivotTable);
068            //relationAttributes.add(node);
069            TAttributeNode.addNodeToList(node,relationAttributes);
070        }
071
072    }
073
074
075    public final static int pivot = 1;
076    public final static int unpivot = 2;
077
078    private int type = pivot;
079
080    public TTable getPivotTable() {
081        return pivotTable;
082    }
083
084    private TTable pivotTable = null;
085
086
087//    private TAliasClause aliasClause = null;
088//
089//    @Override
090//    public TAliasClause getAliasClause() {
091//        return aliasClause;
092//    }
093//
094//    @Override
095//    public void setAliasClause(TAliasClause aliasClause) {
096//
097//        this.aliasClause = aliasClause;
098//    }
099
100    private TPivotInClause pivotInClause;
101
102    public TPivotInClause getPivotInClause() {
103        return pivotInClause;
104    }
105
106    private TUnpivotInClause unpivotInClause;
107
108    public TUnpivotInClause getUnpivotInClause() {
109        return unpivotInClause;
110    }
111
112    private TResultColumnList aggregation_function_list;
113    /**
114     * @deprecated since 1.7.1.1
115     */
116    private TResultColumnList in_result_list;
117
118    private TObjectNameList pivotColumnList;
119
120    public TObjectNameList getPivotColumnList() {
121        return pivotColumnList;
122    }
123
124    /**
125     * @deprecated since 1.7.1.1, use {@link #getPivotInClause} instead
126     * @return result column list
127     */
128    public TResultColumnList getIn_result_list() {
129        return in_result_list;
130    }
131
132    public TResultColumnList getAggregation_function_list() {
133
134        return aggregation_function_list;
135    }
136
137    public void setType(int type) {
138        this.type = type;
139    }
140
141    public int getType() {
142
143        return type;
144    }
145
146    private TFunctionCall aggregation_function = null;
147    /**
148     * @deprecated since 1.7.1.1, use  {@link #valueColumnList} instead
149     */
150    private TObjectName valueColumn = null;
151    private TObjectNameList valueColumnList = null;
152
153    public TObjectNameList getValueColumnList() {
154        return valueColumnList;
155    }
156
157    /**
158     * @deprecated since 1.7.1.1, use {@link #getPivotColumnList} instead.
159     */
160    private TObjectName pivotColumn = null;
161    private TObjectNameList columnList = null;
162
163    /**
164     *
165     * @return Is a system or user-defined aggregate function that accepts one or more inputs. 
166     */
167    public TFunctionCall getAggregation_function() {
168        return aggregation_function;
169    }
170
171    /**
172     *
173     * @return     In the PIVOT clause, lists the values in the pivot_column that will become the column names of the output table. The list cannot specify any column names that already exist in the input table_source that is being pivoted.
174     *  In the UNPIVOT clause, lists the columns in table_source that will be narrowed into a single pivot_column.
175     */
176    public TObjectNameList getColumnList() {
177        return columnList;
178    }
179
180    /**
181     * @deprecated since 1.7.1.1 , use {@link #getPivotColumnList} instead.
182     * @return Is the pivot column of the PIVOT operator. 
183     */
184    public TObjectName getPivotColumn() {
185        return pivotColumn;
186    }
187
188    /**
189     * @deprecated  since 1.7.1.1, use {@link #getValueColumnList} instead.
190     * @return  Is the value column of the PIVOT operator.
191     * When used with UNPIVOT, value_column cannot be the name of an existing column in the input table_source.
192     */
193    public TObjectName getValueColumn() {
194        return valueColumn;
195    }
196
197    public void init(Object arg1,Object arg2){
198        if (arg1 instanceof TFunctionCall){
199            aggregation_function = (TFunctionCall)arg1; // pivot clause, sql server
200        }else if (arg1 instanceof TResultColumnList){
201            aggregation_function_list = (TResultColumnList)arg1; // pivot clause, oracle
202        }else if (arg1 instanceof TObjectNameList){
203           valueColumnList = (TObjectNameList)arg1; // unpivot clause
204        }else if (arg1 instanceof TObjectName){
205            valueColumn = (TObjectName)arg1;
206        }
207
208        if (arg2 instanceof TObjectName){
209            pivotColumn = (TObjectName)arg2;
210        }else if (arg2 instanceof TObjectNameList){
211            pivotColumnList = (TObjectNameList)arg2;
212        }
213    }
214
215    public void init(Object arg1,Object arg2,Object arg3){
216        init(arg1,arg2);
217        if (arg3 instanceof TUnpivotInClause){
218            unpivotInClause = (TUnpivotInClause)arg3;
219        } else if (arg3 instanceof TPivotInClause){
220            pivotInClause = (TPivotInClause)arg3;
221        }
222//        else if (arg3 instanceof TResultColumnList){
223//            in_result_list = (TResultColumnList)arg3;
224//        } else if (arg3 instanceof TObjectNameList){
225//            pivotColumnList = (TObjectNameList)arg3;
226//        }
227    }
228
229    public void doParse(TCustomSqlStatement psql, ESqlClause plocation){
230        TSQLTable sqlTable = null;
231        boolean addColumnFromAlias = false;
232
233        if (getAliasClause() != null){
234            getAliasClause().doParse(psql,plocation);
235
236            pivotTable = new TTable();
237
238            pivotTable.setTableName(getAliasClause().getAliasName());
239            pivotTable.setTableType(ETableSource.pivoted_table);
240            pivotTable.setEffectType(ETableEffectType.tetPivot);
241            psql.getTables().addTable(pivotTable);
242
243            pivotTable.setSourceTableOfPivot(psql.getTables().getTable(0));
244
245            if (psql.getSqlEnv() != null) {
246                sqlTable = psql.getSqlEnv().addTable(pivotTable.getFullName(), true);
247            }
248            if (getAliasClause().getColumns()!=null){
249                addColumnFromAlias = true;
250                for(TObjectName column:getAliasClause().getColumns()){
251                    pivotTable.getLinkedColumns().addObjectName(column);
252                    column.setSourceTable(pivotTable);
253                }
254
255                if (sqlTable != null){
256                    for(TObjectName column:getAliasClause().getColumns()){
257                        sqlTable.addColumn(column.toString());
258                    }
259                }
260            }
261        }else { // alias is not specified
262
263            pivotTable = new TTable();
264            if (getType() == pivot){
265                pivotTable.setTableName(TObjectName.createObjectName (psql.dbvendor, EDbObjectType.column_alias,new TSourceToken("pivot_alias")));
266            }else{
267                pivotTable.setTableName(TObjectName.createObjectName (psql.dbvendor,EDbObjectType.column_alias,new TSourceToken("unpivot_alias")));
268            }
269
270
271            pivotTable.setTableType(ETableSource.pivoted_table);
272            pivotTable.setEffectType(ETableEffectType.tetPivot);
273            psql.getTables().addTable(pivotTable);
274
275            pivotTable.setSourceTableOfPivot(psql.getTables().getTable(0));
276
277            if (psql.getSqlEnv() != null) {
278                sqlTable = psql.getSqlEnv().addTable(pivotTable.getFullName(), true);
279            }
280        }
281
282        switch (getType()){
283            case pivot:
284                if (aggregation_function_list != null){
285                    TColumnNameVisitor objectNameVisitor = new TColumnNameVisitor();
286                    aggregation_function_list.acceptChildren(objectNameVisitor);
287                    for(TObjectName objectName:objectNameVisitor.getObjectNames()){
288                        pivotTable.getSourceTableOfPivot().getLinkedColumns().addObjectName(objectName);
289                        objectName.setSourceTable(pivotTable.getSourceTableOfPivot());
290                    }
291                    aggregation_function_list.doParse(psql,plocation);
292                }else if (aggregation_function != null){
293                    TColumnNameVisitor objectNameVisitor = new TColumnNameVisitor();
294                    aggregation_function.getArgs().acceptChildren(objectNameVisitor);
295                    for(TObjectName objectName:objectNameVisitor.getObjectNames()){
296                        pivotTable.getSourceTableOfPivot().getLinkedColumns().addObjectName(objectName);
297                        objectName.setSourceTable(pivotTable.getSourceTableOfPivot());
298                    }
299
300                    aggregation_function.doParse(psql,plocation);
301                };
302
303                if (pivotColumnList != null){
304                    for(TObjectName objectName:pivotColumnList){
305                        pivotTable.getSourceTableOfPivot().getLinkedColumns().addObjectName(objectName);
306                        objectName.setSourceTable(pivotTable.getSourceTableOfPivot());
307                    }
308                }
309                pivotInClause.doParse(psql,plocation);
310                if (!addColumnFromAlias){
311                    pivotInClause.linkColumnToTable(pivotTable, sqlTable);
312                }
313
314                break;
315            case unpivot:
316                //valueColumnList.
317                if (pivotTable!=null){
318                    if (valueColumnList != null){
319                        for(TObjectName objectName: valueColumnList){
320                            pivotTable.getLinkedColumns().addObjectName(objectName);
321                            objectName.setSourceTable(pivotTable);
322                            if (sqlTable != null){
323                                sqlTable.addColumn(objectName.toString());
324                            }
325                        }
326                    }
327
328                    if (pivotColumnList!=null){
329                        for(TObjectName objectName: pivotColumnList){
330                            pivotTable.getLinkedColumns().addObjectName(objectName);
331                            objectName.setSourceTable(pivotTable);
332                            if (sqlTable != null){
333                                sqlTable.addColumn(objectName.toString());
334                            }
335                        }
336                    }
337                }
338                unpivotInClause.doParse(psql,plocation);
339                unpivotInClause.linkColumnToPivotSourceTable(pivotTable.getSourceTableOfPivot());
340                break;
341        }
342    }
343
344    public void accept(TParseTreeVisitor v){
345        v.preVisit(this);
346        v.postVisit(this);
347    }
348
349    public void acceptChildren(TParseTreeVisitor v){
350        v.preVisit(this);
351      //  pivotTable.acceptChildren(v);
352        switch (getType()){
353            case pivot:
354                if (aggregation_function_list != null){
355                    aggregation_function_list.acceptChildren(v);
356                }else if (aggregation_function != null){
357                    aggregation_function.acceptChildren(v);
358                }
359                pivotColumnList.acceptChildren(v);
360                if (pivotInClause != null){
361                    pivotInClause.acceptChildren(v);
362                }
363                break;
364            case unpivot:
365                valueColumnList.acceptChildren(v);
366                pivotColumnList.acceptChildren(v);
367                unpivotInClause.acceptChildren(v);
368                break;
369        }
370
371
372       if (getAliasClause() != null){
373            getAliasClause().acceptChildren(v);
374        }
375        v.postVisit(this);
376    }
377
378    public void setPivotInClause(TPivotInClause pivotInClause) {
379        this.pivotInClause = pivotInClause;
380    }
381
382    public void setUnpivotInClause(TUnpivotInClause unpivotInClause) {
383        this.unpivotInClause = unpivotInClause;
384    }
385
386    public void setAggregation_function_list(TResultColumnList aggregation_function_list) {
387        this.aggregation_function_list = aggregation_function_list;
388    }
389
390    public void setPivotColumnList(TObjectNameList pivotColumnList) {
391        this.pivotColumnList = pivotColumnList;
392    }
393
394    public void setAggregation_function(TFunctionCall aggregation_function) {
395        this.aggregation_function = aggregation_function;
396    }
397
398    public void setValueColumnList(TObjectNameList valueColumnList) {
399        this.valueColumnList = valueColumnList;
400    }
401
402    public void setColumnList(TObjectNameList columnList) {
403        this.columnList = columnList;
404    }
405}