001
002package gudusoft.gsqlparser.dlineage.dataflow.model;
003
004import java.util.ArrayList;
005import java.util.List;
006
007import gudusoft.gsqlparser.ESqlClause;
008import gudusoft.gsqlparser.TSourceToken;
009import gudusoft.gsqlparser.dlineage.util.Pair3;
010import gudusoft.gsqlparser.nodes.TObjectName;
011import gudusoft.gsqlparser.nodes.TParseTreeNode;
012import gudusoft.gsqlparser.util.SQLUtil;
013
014public class ResultColumnRelationshipElement implements
015                RelationshipElement<ResultColumn>
016{
017
018        private ResultColumn column;
019
020        private TObjectName columnName;
021
022        private ESqlClause relationLocation;
023
024        private int starIndex = -1;
025
026        // Where THIS relation referenced the column (e.g. the operand in an ON or
027        // WHERE clause). A derived table's / CTE's ResultColumn model carries its
028        // select-list definition span, so it cannot hold the per-reference
029        // coordinate. Null when unknown or synthesized. Deliberately excluded from
030        // equals/hashCode.
031        private Pair3<Long, Long, String> referenceStartPosition;
032
033        private Pair3<Long, Long, String> referenceEndPosition;
034
035        // The column is a star whose members' order is unknown, read at a position (an INSERT column list), so no
036        // member can be told to be the one at that position: the relation reads the star itself (Mantis 4856).
037        // Deliberately excluded from equals/hashCode.
038        private boolean positionUnproven;
039
040    private List<Transform> transforms = new ArrayList<Transform>();
041
042        public ResultColumnRelationshipElement(ResultColumn column)
043        {
044                this.column = column;
045        }
046        
047        public ResultColumnRelationshipElement(ResultColumn column, int starIndex )
048        {
049                this.column = column;
050                this.starIndex = starIndex;
051        }
052        
053        public ResultColumnRelationshipElement(ResultColumn column, TObjectName columnName) {
054                this.column = column;
055                this.columnName = columnName;
056        }
057
058        public ResultColumnRelationshipElement(ResultColumn column,
059                                                                                   ESqlClause relationLocation )
060        {
061                this.column = column;
062                this.relationLocation = relationLocation;
063        }
064
065        public ResultColumnRelationshipElement(ResultColumn column, ESqlClause relationLocation,
066                        TObjectName referenceObject)
067        {
068                this(column, relationLocation);
069                setReferencePosition(referenceObject);
070        }
071
072        /**
073         * Records the span of the object name this relation was built from, so the
074         * serialized source can point at the reference site (the ON/WHERE operand)
075         * instead of the result column's select-list definition span. Ignores
076         * synthesized object names, which have no real source token (their tokens
077         * sit at line 1, column 1).
078         */
079        public void setReferencePosition(TObjectName referenceObject) {
080                if (referenceObject == null || referenceObject.getStartToken() == null
081                                || referenceObject.getEndToken() == null) {
082                        return;
083                }
084                TSourceToken startToken = referenceObject.getStartToken();
085                TSourceToken endToken = referenceObject.getEndToken();
086                if (startToken.lineNo <= 0 || (startToken.lineNo == 1 && startToken.columnNo == 1)) {
087                        return;
088                }
089                this.referenceStartPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo,
090                                ModelBindingManager.getGlobalHash());
091                this.referenceEndPosition = new Pair3<Long, Long, String>(endToken.lineNo,
092                                endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(),
093                                ModelBindingManager.getGlobalHash());
094        }
095
096        public Pair3<Long, Long, String> getReferenceStartPosition() {
097                return referenceStartPosition;
098        }
099
100        public Pair3<Long, Long, String> getReferenceEndPosition() {
101                return referenceEndPosition;
102        }
103
104        @Override
105        public ResultColumn getElement( )
106        {
107                return column;
108        }
109
110        public ESqlClause getRelationLocation( )
111        {
112                return relationLocation;
113        }
114
115
116        public TObjectName getColumnName() {
117                return columnName;
118        }
119
120        @Override
121        public int hashCode( )
122        {
123                final int prime = 31;
124                int result = 1;
125                result = prime
126                                * result
127                                + ( ( column == null ) ? 0 : column.hashCode( ) );
128                result = prime
129                                * result
130                                + ( ( relationLocation == null ) ? 0
131                                                : relationLocation.hashCode( ) );
132                return result;
133        }
134
135        @Override
136        public boolean equals( Object obj )
137        {
138                if ( this == obj )
139                        return true;
140                if ( obj == null )
141                        return false;
142                if ( getClass( ) != obj.getClass( ) )
143                        return false;
144                ResultColumnRelationshipElement other = (ResultColumnRelationshipElement) obj;
145                if ( column == null )
146                {
147                        if ( other.column != null )
148                                return false;
149                }
150                else if ( !column.equals( other.column ) )
151                        return false;
152                if ( relationLocation != other.relationLocation )
153                        return false;
154                return true;
155        }
156        
157        @Override
158        public List<Transform> getTransforms() {
159                return transforms;
160        }
161        
162        public void addTransform(String type, TParseTreeNode code) {
163                if (ModelBindingManager.getGlobalOption()!=null && !ModelBindingManager.getGlobalOption().isTransform()) {
164                        return;
165                }
166                Transform transform = new Transform();
167                transform.setType(type);
168                transform.setCode(code);
169                transforms.add(transform);
170        }
171
172        public int getStarIndex() {
173                return starIndex;
174        }
175
176        public boolean isPositionUnproven() {
177                return positionUnproven;
178        }
179
180        public void setPositionUnproven(boolean positionUnproven) {
181                this.positionUnproven = positionUnproven;
182        }
183
184        public void setStarIndex(int starIndex) {
185                this.starIndex = starIndex;
186        }
187
188}