001
002package gudusoft.gsqlparser.dlineage.dataflow.model;
003
004import java.util.LinkedHashSet;
005import java.util.Set;
006
007import gudusoft.gsqlparser.EDbVendor;
008import gudusoft.gsqlparser.EExpressionType;
009import gudusoft.gsqlparser.ESetOperatorType;
010import gudusoft.gsqlparser.TSourceToken;
011import gudusoft.gsqlparser.dlineage.util.DlineageUtil;
012import gudusoft.gsqlparser.dlineage.util.Pair3;
013import gudusoft.gsqlparser.nodes.TObjectName;
014import gudusoft.gsqlparser.nodes.TResultColumn;
015import gudusoft.gsqlparser.sqlenv.ESQLDataObjectType;
016import gudusoft.gsqlparser.sqlenv.TSQLEnv;
017import gudusoft.gsqlparser.stmt.TSelectSqlStatement;
018import gudusoft.gsqlparser.util.SQLUtil;
019
020public class SelectSetResultColumn extends ResultColumn {
021        
022        private LinkedHashSet<String> aliasSet = new LinkedHashSet<String>();
023
024    public SelectSetResultColumn(ResultSet resultSet,
025                                 TResultColumn resultColumnObject, int index) {
026        super(resultSet, resultColumnObject);
027        aliasSet.clear();
028        if (isNotSameAlias(resultSet, index)) {
029            this.name = aliasSet.iterator().next();
030                } else {
031                        if (resultColumnObject.getAliasClause() != null) {
032                                this.name = resultColumnObject.getAliasClause().toString();
033                        } else if (resultColumnObject.getColumnNameOnly() != null
034                                        && !"".equals(resultColumnObject.getColumnNameOnly())) {
035                                this.name = resultColumnObject.getColumnNameOnly();
036                        } else if (resultColumnObject.getExpr().getExpressionType() == EExpressionType.simple_constant_t) {
037                                this.name = resultColumnObject.getExpr().toString();
038                        } 
039                        else {
040                                this.name = quote(resultColumnObject.toString());
041                        }
042                }
043
044        this.fullName = this.name;
045    }
046
047    private boolean isNotSameAlias(ResultSet resultSet, int index) {
048        if (resultSet instanceof SelectSetResultSet) {
049            SelectSetResultSet selectSetResultSet = (SelectSetResultSet) resultSet;
050            if (selectSetResultSet
051                    .getSetOperatorType() == ESetOperatorType.none) {
052                return false;
053            }
054            TSelectSqlStatement select = selectSetResultSet.getSelectObject();
055            return isNotSameAlias(select, index);
056        } else if (resultSet instanceof SelectResultSet) {
057            SelectResultSet selectResultSet = (SelectResultSet) resultSet;
058            if (selectResultSet.getSelectStmt()
059                    .getSetOperatorType() == ESetOperatorType.none) {
060                return false;
061            }
062            TSelectSqlStatement select = selectResultSet.getSelectStmt();
063            return isNotSameAlias(select, index);
064        }
065        return false;
066    }
067
068    private boolean isNotSameAlias(TSelectSqlStatement select, int index) {
069        collectSelectAlias(select, index, aliasSet);
070        aliasSet.remove("*");
071        return aliasSet.size() > 1;
072    }
073
074    private void collectSelectAlias(TSelectSqlStatement select, int index,
075                                    Set<String> aliasSet) {
076        // Iterative traversal using explicit stack to avoid StackOverflow
077        java.util.Deque<TSelectSqlStatement> stack = new java.util.ArrayDeque<>();
078        stack.push(select);
079
080        while (!stack.isEmpty()) {
081            TSelectSqlStatement current = stack.pop();
082            if (current.getSetOperatorType() == ESetOperatorType.none) {
083                if (current.getResultColumnList() == null) {
084                    continue;
085                }
086                TResultColumn column = current.getResultColumnList()
087                        .getResultColumn(index);
088
089                String alias = null;
090                if (column == null) {
091                    continue;
092                }
093                if (column.getAliasClause() != null) {
094                    alias = column.getAliasClause().toString();
095                } else if (column.getColumnNameOnly() != null && !"".equals(column.getColumnNameOnly())) {
096                    alias = column.getColumnNameOnly();
097                } else if (column.getExpr().getExpressionType() == EExpressionType.simple_constant_t) {
098                    alias = column.getExpr().toString();
099                } else {
100                    alias = quote(column.toString());
101                }
102                aliasSet.add(alias);
103            } else {
104                // Push right first so left is processed first
105                if (current.getRightStmt() != null) stack.push(current.getRightStmt());
106                if (current.getLeftStmt() != null) stack.push(current.getLeftStmt());
107            }
108        }
109    }
110
111    private String quote(String column) {
112        EDbVendor vendor = ModelBindingManager.getGlobalVendor();
113        if (!DlineageUtil.isQuote(column)){
114                return SQLUtil.quoteDottedName(vendor, ESQLDataObjectType.dotColumn, column);
115        }
116        else return column;
117    }
118
119    public SelectSetResultColumn(ResultSet resultSet,
120                                 ResultColumn resultColumn) {
121        if (resultColumn == null || resultSet == null)
122            throw new IllegalArgumentException(
123                    "ResultColumn arguments can't be null.");
124
125        id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
126
127        this.resultSet = resultSet;
128        resultSet.addColumn(this);
129        this.setStruct(resultColumn.isStruct());
130
131        if(resultColumn.getRefColumnName()!=null) {
132                TResultColumn resultColumnObject = (TResultColumn) resultColumn
133                    .getColumnObject();
134                TSourceToken startToken = resultColumnObject.getStartToken();
135            TSourceToken endToken = resultColumnObject.getEndToken();
136            this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo,
137                    startToken.columnNo, ModelBindingManager.getGlobalHash());
138            this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo,
139                    endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash());
140            this.columnObject = resultColumnObject;
141            this.refColumnName = resultColumn.getRefColumnName();
142            this.name = resultColumn.getName();
143        }
144        else if (resultColumn.getColumnObject() instanceof TResultColumn) {
145            TResultColumn resultColumnObject = (TResultColumn) resultColumn
146                    .getColumnObject();
147            if (resultColumnObject.getAliasClause() != null) {
148                this.alias = resultColumnObject.getAliasClause().toString();
149                TSourceToken startToken = resultColumnObject.getAliasClause()
150                        .getStartToken();
151                TSourceToken endToken = resultColumnObject.getAliasClause()
152                        .getEndToken();
153                this.aliasStartPosition = new Pair3<Long, Long, String>(
154                        startToken.lineNo, startToken.columnNo, ModelBindingManager.getGlobalHash());
155                this.aliasEndPosition = new Pair3<Long, Long, String>(endToken.lineNo,
156                        endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash());
157
158                this.name = this.alias;
159            } else if (resultColumnObject.getExpr()
160                    .getExpressionType() == EExpressionType.simple_object_name_t) {
161                this.name = resultColumnObject.getColumnNameOnly();
162            } else if (resultColumnObject.getFieldAttr() != null) {
163                this.name = resultColumnObject.getColumnNameOnly();
164            } else {
165                if (resultColumnObject.getExpr()
166                        .getExpressionType() == EExpressionType.simple_constant_t) {
167                    this.name = resultColumnObject.toString();
168                } else if (resultColumnObject.getExpr()
169                        .getExpressionType() == EExpressionType.function_t) {
170                    this.name = resultColumnObject.getCompactString();
171                } else if (resultColumnObject.getColumnNameOnly() != null
172                        && !"".equals(
173                        resultColumnObject.getColumnNameOnly())) {
174                    this.name = resultColumnObject.getColumnNameOnly();
175                } else {
176                    this.name = resultColumnObject.toString();
177                }
178            }
179
180            if (resultColumnObject.getExpr()
181                    .getExpressionType() == EExpressionType.function_t) {
182                this.fullName = resultColumnObject.getExpr()
183                        .getFunctionCall()
184                        .getFunctionName()
185                        .toString();
186            } else {
187                this.fullName = resultColumnObject.toString();
188            }
189
190            TSourceToken startToken = resultColumnObject.getStartToken();
191            TSourceToken endToken = resultColumnObject.getEndToken();
192            this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo,
193                    startToken.columnNo, ModelBindingManager.getGlobalHash());
194            this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo,
195                    endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash());
196            this.columnObject = resultColumnObject;
197        } else if (resultColumn.getColumnObject() instanceof TObjectName) {
198            TObjectName resultColumnObject = (TObjectName) resultColumn
199                    .getColumnObject();
200
201            if (resultColumnObject.getColumnNameOnly() != null
202                    && !"".equals(resultColumnObject.getColumnNameOnly())) {
203                this.name = resultColumnObject.getColumnNameOnly();
204            } else {
205                this.name = resultColumnObject.toString();
206            }
207
208            this.fullName = this.name;
209
210            TSourceToken startToken = resultColumnObject.getStartToken();
211            TSourceToken endToken = resultColumnObject.getEndToken();
212            this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo,
213                    startToken.columnNo, ModelBindingManager.getGlobalHash());
214            this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo,
215                    endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash());
216            this.columnObject = resultColumnObject;
217        } else {
218            this.name = resultColumn.getName();
219            this.fullName = this.name;
220
221            TSourceToken startToken = resultColumn.getColumnObject()
222                    .getStartToken();
223            TSourceToken endToken = resultColumn.getColumnObject()
224                    .getEndToken();
225            this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo,
226                    startToken.columnNo, ModelBindingManager.getGlobalHash());
227            this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo,
228                    endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash());
229            this.columnObject = resultColumn.getColumnObject();
230        }
231    }
232
233        public Set<String> getAliasSet() {
234                return aliasSet;
235        }
236}