001
002package gudusoft.gsqlparser.dlineage.dataflow.model;
003
004import java.util.*;
005import java.util.concurrent.atomic.AtomicInteger;
006
007import gudusoft.gsqlparser.EExpressionType;
008import gudusoft.gsqlparser.TSourceToken;
009import gudusoft.gsqlparser.dlineage.util.DlineageUtil;
010import gudusoft.gsqlparser.dlineage.util.Pair;
011import gudusoft.gsqlparser.dlineage.util.Pair3;
012import gudusoft.gsqlparser.nodes.TExpression;
013import gudusoft.gsqlparser.nodes.TObjectName;
014import gudusoft.gsqlparser.nodes.TParseTreeNode;
015import gudusoft.gsqlparser.nodes.TResultColumn;
016import gudusoft.gsqlparser.nodes.TResultColumnList;
017import gudusoft.gsqlparser.util.SQLUtil;
018
019public class ResultColumn extends Column{
020
021        protected ResultSet resultSet;
022
023        protected long id;
024
025        protected String alias;
026        protected Pair3<Long, Long, String> aliasStartPosition;
027        protected Pair3<Long, Long, String> aliasEndPosition;
028
029        protected String fullName;
030        protected String name;
031
032        protected Pair3<Long, Long, String> startPosition;
033        protected Pair3<Long, Long, String> endPosition;
034
035        protected TParseTreeNode columnObject;
036        
037        protected String refColumnName;
038
039        protected Map<String, Set<TObjectName>> starLinkColumns = new LinkedHashMap<String, Set<TObjectName>>();
040
041        private boolean showStar = true;
042
043        protected boolean isFunction = false;
044        
045        private boolean isPseduo = false;
046        
047        private boolean isStruct = false;
048        
049        private List<Transform> transforms;
050
051        public ResultColumn() {
052
053        }
054
055        public ResultColumn(ResultSet resultSet, TParseTreeNode columnObject) {
056                if (columnObject == null || resultSet == null)
057                        throw new IllegalArgumentException("ResultColumn arguments can't be null.");
058
059                id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
060
061                this.resultSet = resultSet;
062                resultSet.addColumn(this);
063
064                this.columnObject = columnObject;
065
066                TSourceToken startToken = columnObject.getStartToken();
067                TSourceToken endToken = columnObject.getEndToken();
068
069                if (columnObject instanceof TObjectName) {
070                        if (((TObjectName) columnObject).getColumnNameOnly() != null
071                                        && !"".equals(((TObjectName) columnObject).getColumnNameOnly())) {
072                                this.name = ((TObjectName) columnObject).getColumnNameOnly();
073                        } else {
074                                this.name = ((TObjectName) columnObject).toString();
075                        }
076                } else
077                        this.name = columnObject.toString();
078
079                this.fullName = columnObject.toString();
080
081                this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo,
082                                ModelBindingManager.getGlobalHash());
083                this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo, endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(),
084                                ModelBindingManager.getGlobalHash());
085        }
086
087        public ResultColumn(ResultSet resultSet, TResultColumn resultColumnObject) {
088                if (resultColumnObject == null || resultSet == null)
089                        throw new IllegalArgumentException("ResultColumn arguments can't be null.");
090
091                id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
092
093                this.resultSet = resultSet;
094                resultSet.addColumn(this);
095
096                this.columnObject = resultColumnObject;
097
098                if (resultColumnObject.getAliasClause() != null) {
099                        this.alias = resultColumnObject.getAliasClause().toString();
100                        TSourceToken startToken = resultColumnObject.getAliasClause().getStartToken();
101                        TSourceToken endToken = resultColumnObject.getAliasClause().getEndToken();
102                        this.aliasStartPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo,
103                                        ModelBindingManager.getGlobalHash());
104                        this.aliasEndPosition = new Pair3<Long, Long, String>(endToken.lineNo,
105                                        endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash());
106
107                        if(resultSet.getAliasMap().containsKey(this.alias.toLowerCase())){
108                                int index = resultSet.getAliasMap().get(this.alias.toLowerCase()).incrementAndGet();
109                                this.name = SQLUtil.trimSingleQuote(this.alias) + "(" + index + ")";
110                        }
111                        else {
112                                resultSet.getAliasMap().put(this.alias.toLowerCase(), new AtomicInteger(0));
113                                this.name = SQLUtil.trimSingleQuote(this.alias);
114                        }
115                } else if (resultColumnObject.getExpr() != null) {
116                        this.name = getColumnName(resultColumnObject.getExpr());
117                } 
118                
119                if(this.name == null){
120                        if (resultColumnObject.getColumnNameOnly() != null
121                                        && !"".equals(resultColumnObject.getColumnNameOnly())) {
122                                if (resultColumnObject.getExpr().getObjectOperand() != null
123                                                && resultColumnObject.getExpr().getObjectOperand().getPropertyToken() != null) {
124                                        this.name = resultColumnObject.getExpr().getObjectOperand().getPropertyToken().getAstext();
125                                } else {
126                                        this.name = resultColumnObject.getColumnNameOnly();
127                                }
128                        } else {
129                                this.name = resultColumnObject.toString();
130                        }
131                }
132                
133                if (resultColumnObject.getExpr().getExpressionType() == EExpressionType.function_t) {
134                        this.fullName = resultColumnObject.getExpr().getFunctionCall().toString();
135                } else if (resultColumnObject.getExpr().getExpressionType() == EExpressionType.typecast_t) {
136                        this.fullName = resultColumnObject.getExpr().getLeftOperand().toString();
137                } else {
138                        this.fullName = resultColumnObject.toString();
139                }
140
141                TSourceToken startToken = resultColumnObject.getStartToken();
142                TSourceToken endToken = resultColumnObject.getEndToken();
143                this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo,
144                                ModelBindingManager.getGlobalHash());
145                this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo, endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(),
146                                ModelBindingManager.getGlobalHash());
147        }
148        
149        public ResultColumn(ResultSet resultSet, TResultColumn resultColumnObject, String refColumnName) {
150                if (resultColumnObject == null || resultSet == null)
151                        throw new IllegalArgumentException("ResultColumn arguments can't be null.");
152
153                id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
154
155                this.resultSet = resultSet;
156                resultSet.addColumn(this);
157
158                this.columnObject = resultColumnObject;
159                this.refColumnName = refColumnName;
160                
161                this.name = refColumnName;
162
163                TSourceToken startToken = resultColumnObject.getStartToken();
164                TSourceToken endToken = resultColumnObject.getEndToken();
165                this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo,
166                                ModelBindingManager.getGlobalHash());
167                this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo, endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(),
168                                ModelBindingManager.getGlobalHash());
169        }
170
171        protected String getColumnName(TExpression expr) {
172                if (expr.getExpressionType() == EExpressionType.simple_constant_t) {
173                        return expr.toString();
174                } else if (expr.getExpressionType() == EExpressionType.sqlserver_proprietary_column_alias_t) {
175                        this.alias = expr.getLeftOperand().toString();
176                        TSourceToken startToken = expr.getLeftOperand().getStartToken();
177                        TSourceToken endToken = expr.getLeftOperand().getEndToken();
178                        this.aliasStartPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo,
179                                        ModelBindingManager.getGlobalHash());
180                        this.aliasEndPosition = new Pair3<Long, Long, String>(endToken.lineNo,
181                                        endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash());
182
183                        return this.alias;
184                } else if (expr.getExpressionType() == EExpressionType.function_t) {
185                        return expr.getFunctionCall().toString();
186                } else if (expr.getExpressionType() == EExpressionType.typecast_t) {
187                        return expr.getLeftOperand().toString();
188                } else if (expr.getExpressionType() == EExpressionType.parenthesis_t) {
189                        TExpression inner = expr.getLeftOperand();
190                        while (inner != null && inner.getExpressionType() == EExpressionType.parenthesis_t) {
191                                inner = inner.getLeftOperand();
192                        }
193                        return getColumnName(inner);
194                } else if (expr.getExpressionType() == EExpressionType.simple_object_name_t) {
195                        TObjectName columnName = expr.getObjectOperand();
196                        if (columnName.getPropertyToken() != null) {
197                                return columnName.getPropertyToken().getAstext();
198                        } else {
199                                if (SQLUtil.isEmpty(columnName.getColumnNameOnly())) {
200                                        return columnName.toString();
201                                } else {
202                                        return columnName.getColumnNameOnly();
203                                }
204                        }
205                } else if (expr.getExpressionType() == EExpressionType.subquery_t) {
206                        TResultColumnList resultset = expr.getSubQuery().getResultColumnList();
207                        if (resultset != null && resultset.size() == 1) {
208                                TResultColumn resultColumn = resultset.getResultColumn(0);
209                                if (!SQLUtil.isEmpty(resultColumn.getColumnAlias())) {
210                                        return resultColumn.getColumnAlias();
211                                } else if (resultColumn.getExpr() != null) {
212                                        return getColumnName(resultColumn.getExpr());
213                                } else if (resultColumn.getColumnNameOnly() != null
214                                                && !"".equals(resultColumn.getColumnNameOnly())) {
215                                        if (resultColumn.getExpr().getObjectOperand() != null
216                                                        && resultColumn.getExpr().getObjectOperand().getPropertyToken() != null) {
217                                                this.name = resultColumn.getExpr().getObjectOperand().getPropertyToken().getAstext();
218                                        } else {
219                                                this.name = resultColumn.getColumnNameOnly();
220                                        }
221                                } else {
222                                        this.name = resultColumn.toString();
223                                }
224                        }
225                }
226                return null;
227        }
228
229        public ResultColumn(SelectResultSet resultSet, Pair<TResultColumn, TObjectName> starColumnPair) {
230                if (starColumnPair == null || resultSet == null)
231                        throw new IllegalArgumentException("ResultColumn arguments can't be null.");
232
233                id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
234
235                this.resultSet = resultSet;
236                resultSet.addColumn(this);
237
238                this.columnObject = starColumnPair.first;
239
240                TSourceToken startToken = columnObject.getStartToken();
241                TSourceToken endToken = columnObject.getEndToken();
242
243                this.name = ((TObjectName) columnObject).getColumnNameOnly();
244                if(name == null){
245                        name =  ((TObjectName) columnObject).toString();
246                }
247                this.fullName = columnObject.toString();
248
249                this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo,
250                                ModelBindingManager.getGlobalHash());
251                this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo, endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(),
252                                ModelBindingManager.getGlobalHash());
253        }
254
255        // private int getIndexOf(TResultColumnList resultColumnList,
256        // TResultColumn resultColumnObject) {
257        // for (int i = 0; i < resultColumnList.size(); i++) {
258        // if (resultColumnList.getResultColumn(i) == resultColumnObject)
259        // return i;
260        // }
261        // return -1;
262        // }
263
264        public ResultSet getResultSet() {
265                return resultSet;
266        }
267
268        public long getId() {
269                return id;
270        }
271
272        public String getAlias() {
273                return alias;
274        }
275
276        public Pair3<Long, Long, String> getAliasStartPosition() {
277                return aliasStartPosition;
278        }
279
280        public Pair3<Long, Long, String> getAliasEndPosition() {
281                return aliasEndPosition;
282        }
283
284        public String getFullName() {
285                return fullName;
286        }
287
288        public Pair3<Long, Long, String> getStartPosition() {
289                return startPosition;
290        }
291
292        public Pair3<Long, Long, String> getEndPosition() {
293                return endPosition;
294        }
295
296        public TParseTreeNode getColumnObject() {
297                return columnObject;
298        }
299
300        public String getName() {
301                return name;
302        }
303
304        public boolean bindStarLinkColumn(TObjectName objectName) {
305                if (objectName == null) {
306                        return false;
307                }
308
309                String columnName = DlineageUtil.getColumnName(objectName);
310
311                if ("*".equals(columnName)) {
312                        return false;
313                }
314                
315                boolean flag = false;
316                if (!starLinkColumns.containsKey(columnName)) {
317                        starLinkColumns.put(columnName, new LinkedHashSet<TObjectName>());
318                        flag = true;
319                }
320
321                starLinkColumns.get(columnName).add(objectName);
322
323                if (this.getStarSourceColumns() != null) {
324                        for (Column column : this.getStarSourceColumns()) {
325                                boolean find = false;
326                                if (column instanceof ResultColumn) {
327                                        ResultSet resultset = ((ResultColumn) column).getResultSet();
328                                        for (ResultColumn resultColumn : resultset.getColumns()) {
329                                                if (DlineageUtil.compareColumnIdentifier(getColumnName(resultColumn.name),
330                                                                getColumnName(objectName.toString()))) {
331                                                        find = true;
332                                                        break;
333                                                }
334                                        }
335                                }
336                                if (!find) {
337                                        column.bindStarLinkColumn(objectName);
338                                }
339                        }
340                }
341
342                return flag;
343        }
344        
345        private String getColumnName(String column) {
346                if (column == null) {
347                        return null;
348                }
349                String name = column.substring(column.lastIndexOf(".") + 1);
350                if (name == null || "".equals(name.trim())) {
351                        return DlineageUtil.getIdentifierNormalColumnName(column.toString().trim());
352                } else
353                        return DlineageUtil.getIdentifierNormalColumnName(name.trim());
354        }
355        
356        
357        public int indexOfStarLinkColumn(TObjectName objectName) {
358                if (objectName == null) {
359                        return -1;
360                }
361
362                String columnName = DlineageUtil.getColumnName(objectName);
363
364                if ("*".equals(columnName)) {
365                        return -1;
366                }
367                
368                int index = -1;
369                for (String item : starLinkColumns.keySet()) {
370                        index++;
371                        if (item.equals(columnName)) {
372                                return index;
373                        }
374                }
375                return index;
376        }
377        
378        public void unbindStarLinkColumn(TObjectName objectName) {
379                if (objectName == null) {
380                        return;
381                }
382
383                String columnName = DlineageUtil.getColumnName(objectName);
384                starLinkColumns.remove(columnName);
385        }
386        
387        public void bindStarLinkColumn(TObjectName objectName, int index) {
388                if (objectName == null) {
389                        return;
390                }
391
392                String columnName = DlineageUtil.getColumnName(objectName);
393
394                if ("*".equals(columnName)) {
395                        return;
396                }
397                if (!starLinkColumns.containsKey(columnName)) { 
398                        Map<String, Set<TObjectName>> copyStarLinkColumns = new LinkedHashMap<String, Set<TObjectName>>();
399                        int i = 0;
400                        for(String item: starLinkColumns.keySet()){
401                                if(index == i){
402                                        copyStarLinkColumns.put(columnName, new LinkedHashSet<TObjectName>());
403                                }
404                                copyStarLinkColumns.put(item, starLinkColumns.get(item));
405                                i++;
406                        }
407                        starLinkColumns = copyStarLinkColumns;
408                }
409
410                if (starLinkColumns.get(columnName) != null) {
411                        starLinkColumns.get(columnName).add(objectName);
412                }
413                else {
414                        starLinkColumns.put(columnName, new LinkedHashSet<TObjectName>());
415                        starLinkColumns.get(columnName).add(objectName);
416                }
417        }
418        
419        public boolean hasStarLinkColumn(){
420                return starLinkColumns!=null && !starLinkColumns.isEmpty();
421        }
422
423        public Map<String, Set<TObjectName>> getStarLinkColumns() {
424                return starLinkColumns;
425        }
426
427        public List<TObjectName> getStarLinkColumnList() {
428                List<TObjectName> columns = new ArrayList<TObjectName>();
429                if (starLinkColumns != null) {
430                        for (Set<TObjectName> columnSet : starLinkColumns.values()) {
431                                columns.addAll(columnSet);
432                        }
433                }
434                return columns;
435        }
436        
437        public List<String> getStarLinkColumnNames() {
438                List<String> columns = new ArrayList<String>();
439                if (starLinkColumns != null) {
440                        columns.addAll(starLinkColumns.keySet());
441                }
442                return columns;
443        }
444        
445        public TObjectName getStarLinkColumnName(int index) {
446                List<String> columns = new ArrayList<String>();
447                if (starLinkColumns != null) {
448                        columns.addAll(starLinkColumns.keySet());
449                }
450                return starLinkColumns.get(getStarLinkColumnNames().get(index)).iterator().next();
451        }
452
453        public boolean isShowStar() {
454                return showStar;
455        }
456
457        public void setShowStar(boolean showStar) {
458                this.showStar = showStar;
459        }
460
461        public boolean isFunction() {
462                return isFunction;
463        }
464
465        public void setFunction(boolean isFunction) {
466                this.isFunction = isFunction;
467        }
468        
469        public boolean isPseduo() {
470                return isPseduo;
471        }
472
473        public void setPseduo(boolean isPseduo) {
474                this.isPseduo = isPseduo;
475        }
476        
477        public String getRefColumnName() {
478                return refColumnName;
479        }
480        
481        @Override
482        public String toString() {
483                return this.name;
484        }
485
486        public boolean isStruct() {
487                return isStruct;
488        }
489
490        public void setStruct(boolean isStruct) {
491                this.isStruct = isStruct;
492        }
493
494        public List<Transform> getTransforms() {
495                return transforms;
496        }
497
498        public void setTransform(Transform transform) {
499                if(transform==null) {
500                        return;
501                }
502                if(transforms == null) {
503                        transforms = new ArrayList<Transform>();
504                }
505                if(!transforms.contains(transform)) {
506                        transforms.add(transform);
507                }
508        }
509}