001
002package gudusoft.gsqlparser.dlineage.dataflow.model;
003
004import gudusoft.gsqlparser.EExpressionType;
005import gudusoft.gsqlparser.TCustomSqlStatement;
006import gudusoft.gsqlparser.dlineage.util.DlineageUtil;
007import gudusoft.gsqlparser.nodes.*;
008import gudusoft.gsqlparser.stmt.TCreateViewSqlStatement;
009
010import java.util.Collection;
011import java.util.LinkedHashSet;
012import java.util.List;
013import java.util.Set;
014import java.util.Stack;
015
016public abstract class AbstractRelationship implements Relationship {
017
018    private long id;
019
020    private String function; 
021    
022    private EffectType effectType;
023    
024    private String partition;
025    
026    private boolean showStarRelation;
027
028    protected RelationshipElement<?> target;
029    
030    protected Set<RelationshipElement<?>> sources = new LinkedHashSet<RelationshipElement<?>>();
031    
032    private Process process;
033
034        private String sqlHash;
035        
036        private Long procedureId;
037        
038        private String sqlComment;
039
040    public AbstractRelationship() {
041        id = ++ModelBindingManager.get().RELATION_ID;
042    }
043
044    public long getId() {
045        return id;
046    }
047
048    public RelationshipElement<?> getTarget() {
049        return target;
050    }
051
052    public void setTarget(RelationshipElement<?> target) {
053        this.target = target;
054        SqllrObservations observations = SqllrObservations.current();
055        if (observations != null) {
056            observations.onTarget(this, target);
057        }
058        if(target.getElement() instanceof RelationRows<?>){
059                ((RelationRows<?>)target.getElement()).holdRelation(this);
060                ((RelationRows<?>)target.getElement()).setHasRelation(true);
061        }
062
063        Stack<TCustomSqlStatement> stmtStack = ModelBindingManager.getGlobalStmtStack();
064        if (stmtStack.isEmpty()) {
065            return;
066        }
067        TCustomSqlStatement stmt = DlineageUtil.getTopStmt(stmtStack.peek());
068        
069                if(ModelBindingManager.getGlobalOption().isTraceSQL()) {
070                        this.sqlHash = ModelBindingManager.get().getSqlHash(stmt);
071                        try {
072                                this.sqlComment = stmt.getCommentBeforeNode();
073                        } catch (Exception e) {
074                        }
075                }
076                else if(ModelBindingManager.getGlobalOption().isShowComment()
077                                && !ModelBindingManager.isSyntheticStmtContext()) {
078                        // The innermost statement, bounded at a blank line: the label the author put on THIS
079                        // statement. `stmt` above is the top-level one, whose comment is the procedure header.
080                        try {
081                                this.sqlComment = stmtStack.peek().getCommentBeforeNode(true);
082                        } catch (Exception e) {
083                        }
084                }
085                
086                if(ModelBindingManager.getGlobalOption().isTraceProcedure()) {
087                        Object model = ModelBindingManager.get().getModel(stmt);
088                        if(model instanceof Procedure) {
089                                this.procedureId = ((Procedure)model).getId();
090                        }
091                }
092    }
093
094    public Collection<RelationshipElement<?>> getSources() {
095        return sources;
096    }
097
098    public void addSource(RelationshipElement<?> source) {
099        addSource(source, true);
100    }
101    
102    private void addTransformsInReverse(RelationshipElement<?> source, List<Transform> transforms) {
103        if (transforms == null) return;
104        for (int i = transforms.size() - 1; i >= 0; i--) {
105            Transform transform = transforms.get(i);
106            source.addTransform(transform.getType(), transform.getCode());
107        }
108    }
109
110    public void addSource(RelationshipElement<?> source, boolean inferStar) {
111        SqllrObservations observations = SqllrObservations.current();
112        if (observations != null) {
113            observations.onSource(this, source); // before de-duplication: a + a reads a twice
114        }
115        if (source != null && !sources.contains(source)) {
116            sources.add(source);
117
118            Object obj = source.getElement();
119            if (obj instanceof ResultColumn) {
120                ResultSet resultSet = ((ResultColumn) obj).getResultSet();
121                if (resultSet.isTarget() && !(resultSet instanceof Function)) {
122                    resultSet.setTarget(false);
123                }
124            }
125
126            if (getTarget() instanceof ResultColumnRelationshipElement) {
127                ResultColumn column = ((ResultColumnRelationshipElement) getTarget()).getElement();
128                if (column != null) {
129                    if (column.getTransforms() != null) {
130                        addTransformsInReverse(source, column.getTransforms());
131                    } else if (column.getColumnObject() instanceof TResultColumn) {
132                        TResultColumn columnObject = (TResultColumn) column.getColumnObject();
133                        TExpression expression = columnObject.getExpr();
134                        addExpressionTransform(source, expression);
135                    } else if (column instanceof FunctionResultColumn) {
136                        FunctionResultColumn functionColumn = (FunctionResultColumn) column;
137                        if (functionColumn.getFunction() instanceof TFunctionCall) {
138                            source.addTransform(Transform.FUNCTION, functionColumn.getFunction());
139                        }
140                        if (functionColumn.getFunction() instanceof TCaseExpression) {
141                            source.addTransform(Transform.CASE, functionColumn.getFunction());
142                        }
143                    } else if (column.getColumnObject() instanceof TObjectName) {
144                        source.addTransform(Transform.SIMPLE, (TObjectName) column.getColumnObject());
145                    }
146                }
147
148                if (source.getElement() instanceof ResultColumn) {
149                    ResultColumn sourceColumn = (ResultColumn) source.getElement();
150                    if (column != null && sourceColumn.isStarColumn() && column.isStarColumn() && inferStar) {
151                        column.appendStarSourceColumn(sourceColumn);
152                    }
153                    addTransformsInReverse(source, sourceColumn.getTransforms());
154                } else if (source.getElement() instanceof TableColumn) {
155                    TableColumn sourceColumn = (TableColumn) source.getElement();
156                    if (column != null && sourceColumn.isStarColumn() && column.isStarColumn() && inferStar) {
157                        column.appendStarSourceColumn(sourceColumn);
158                    }
159                    addTransformsInReverse(source, sourceColumn.getTransforms());
160                }
161            } else if (getTarget() instanceof ViewColumnRelationshipElement) {
162                TableColumn column = ((ViewColumnRelationshipElement) getTarget()).getElement();
163                if (column.getTable() != null && column.getTable().getSqlStatement() instanceof TCreateViewSqlStatement) {
164                    TCreateViewSqlStatement view = (TCreateViewSqlStatement) column.getTable().getSqlStatement();
165                    if (view.getSubquery() != null && column.getColumnObject() != null) {
166                        source.addTransform(Transform.SIMPLE, column.getColumnObject());
167                    }
168                }
169
170                if (source.getElement() instanceof ResultColumn) {
171                    ResultColumn sourceColumn = (ResultColumn) source.getElement();
172                    if (sourceColumn.isStarColumn() && column.isStarColumn() && inferStar) {
173                        column.appendStarSourceColumn(sourceColumn);
174                    }
175                    addTransformsInReverse(source, sourceColumn.getTransforms());
176                } else if (source.getElement() instanceof TableColumn) {
177                    TableColumn sourceColumn = (TableColumn) source.getElement();
178                    if (sourceColumn.isStarColumn() && column.isStarColumn() && inferStar) {
179                        column.appendStarSourceColumn(sourceColumn);
180                    }
181                    addTransformsInReverse(source, sourceColumn.getTransforms());
182                }
183            } else if (getTarget() instanceof TableColumnRelationshipElement) {
184                if (source.getElement() instanceof ResultColumn) {
185                    ResultColumn column = (ResultColumn) source.getElement();
186                    addTransformsInReverse(source, column.getTransforms());
187                }
188            } else if (getTarget() == null && source.getElement() instanceof TableColumn) {
189                TableColumn column = (TableColumn) source.getElement();
190                addTransformsInReverse(source, column.getTransforms());
191            }
192
193            if (source.getElement() instanceof RelationRows<?>) {
194                ((RelationRows<?>) source.getElement()).setHasRelation(true);
195            }
196        }
197    }
198
199        protected void addExpressionTransform(RelationshipElement<?> source, TExpression expression) {
200                if (expression.getExpressionType() == EExpressionType.simple_object_name_t) {
201                        source.addTransform(Transform.SIMPLE, expression);
202                }
203                else if (expression.getExpressionType() == EExpressionType.function_t) {
204                        source.addTransform(Transform.FUNCTION, expression);
205                }
206                else if (expression.getExpressionType() == EExpressionType.simple_constant_t) {
207                        source.addTransform(Transform.FUNCTION, expression);
208                }
209                else if (expression.getExpressionType() == EExpressionType.case_t) {
210                        source.addTransform(Transform.CASE, expression);
211                }
212                else if (expression.getExpressionType() == EExpressionType.subquery_t) {
213                        source.addTransform(Transform.SUBQUERY, expression);
214                }
215                else if (expression.getExpressionType() == EExpressionType.parenthesis_t) {
216                        TExpression inner = expression.getLeftOperand();
217                        while (inner != null && inner.getExpressionType() == EExpressionType.parenthesis_t) {
218                                inner = inner.getLeftOperand();
219                        }
220                        if (inner != null) {
221                                addExpressionTransform(source, inner);
222                        }
223                }
224                else if (expression.getOperatorToken() != null) {
225                        source.addTransform(Transform.EXPRESSION, expression);
226                }
227        }
228
229    public EffectType getEffectType() {
230        return effectType;
231    }
232
233    public void setEffectType(EffectType effectType) {
234        this.effectType = effectType;
235    }
236
237        public String getFunction() {
238                return function;
239        }
240
241        public void setFunction(String function) {
242                this.function = function;
243        }
244
245        public boolean isShowStarRelation() {
246                return showStarRelation;
247        }
248
249        public void setShowStarRelation(boolean showStarRelation) {
250                this.showStarRelation = showStarRelation;
251        }
252
253        public Process getProcess() {
254                return process;
255        }
256
257        public void setProcess(Process process) {
258                this.process = process;
259        }
260
261
262        public String getSqlHash() {
263                return sqlHash;
264        }
265
266        public String getSqlComment() {
267                return sqlComment;
268        }
269
270        public String getPartition() {
271                return partition;
272        }
273
274        public void setPartition(String partition) {
275                this.partition = partition;
276        }
277
278        public Long getProcedureId() {
279                return procedureId;
280        }
281
282        public void setProcedureId(Long procedureId) {
283                this.procedureId = procedureId;
284        }
285        
286}