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