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