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