1 /*
2  * Copyright 2015-2018 HuntLabs.cn
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 module hunt.sql.ast.expr.SQLIdentifierExpr;
17 
18 import hunt.sql.SQLUtils;
19 import hunt.sql.ast;
20 import hunt.sql.ast.statement;
21 import hunt.sql.visitor.SQLASTVisitor;
22 import hunt.sql.util.FnvHash;
23 import hunt.collection;
24 import hunt.sql.ast.expr.SQLPropertyExpr;
25 import std.uni;
26 import hunt.String;
27 import hunt.text;
28 import hunt.util.StringBuilder;
29 
30 class SQLIdentifierExpr : SQLExprImpl , SQLName {
31     string    name;
32     private   long      _hashCode64;
33 
34     private   SQLObject resolvedColumn;
35     private   SQLObject resolvedOwnerObject;
36 
37     this(){
38 
39     }
40 
41     this(string name){
42         this.name = name;
43     }
44 
45     this(string name, long hash_lower){
46         this.name = name;
47         this._hashCode64 = hash_lower;
48     }
49 
50     string getSimpleName() {
51         return name;
52     }
53 
54     string getLowerName() {
55         if (name is null) {
56             return null;
57         }
58 
59         return toLower(name);
60     }
61 
62     string getName() {
63         return this.name;
64     }
65 
66     void setName(string name) {
67         this.name = name;
68         this._hashCode64 = 0L;
69 
70         if (cast(SQLPropertyExpr)parent !is null) {
71             SQLPropertyExpr propertyExpr = cast(SQLPropertyExpr) parent;
72             propertyExpr.computeHashCode64();
73         }
74     }
75 
76     long nameHashCode64() {
77         return hashCode64();
78     }
79 
80    override
81     long hashCode64() {
82         if (_hashCode64 == 0
83                 && name !is null) {
84             _hashCode64 = FnvHash.hashCode64(name);
85         }
86         return _hashCode64;
87     }
88 
89     override void output(StringBuilder buf) {
90         buf.append(this.name);
91     }
92 
93     override  protected void accept0(SQLASTVisitor visitor) {
94         visitor.visit(this);
95 
96         visitor.endVisit(this);
97     }
98 
99    override
100     size_t toHash() @trusted nothrow {
101         long value ;
102         try
103         {
104             value = hashCode64();
105         }
106         catch(Exception)
107         {
108         }
109         return cast(size_t)(value ^ (value >>> 32));
110     }
111 
112    override
113     bool opEquals(Object obj) {
114         // if (!(cast(SQLIdentifierExpr)(obj) !is null)) {
115         //     return false;
116         // }
117 
118         SQLIdentifierExpr other = cast(SQLIdentifierExpr) obj;
119         if(other is null)
120             return false;
121         return this.hashCode64() == other.hashCode64();
122     }
123 
124     override string toString() {
125         return this.name;
126     }
127 
128     override SQLIdentifierExpr clone() {
129         SQLIdentifierExpr x = new SQLIdentifierExpr(this.name, _hashCode64);
130         x.resolvedColumn = resolvedColumn;
131         x.resolvedOwnerObject = resolvedOwnerObject;
132         return x;
133     }
134 
135     SQLIdentifierExpr simplify() {
136         string normalized = SQLUtils.normalize(name);
137         if (normalized != name) {
138            return new SQLIdentifierExpr(normalized, _hashCode64);
139         }
140         return this;
141     }
142 
143     string normalizedName() {
144         return SQLUtils.normalize(name);
145     }
146 
147     SQLColumnDefinition getResolvedColumn() {
148         if ( cast(SQLColumnDefinition)resolvedColumn !is null) {
149             return cast(SQLColumnDefinition) resolvedColumn;
150         }
151 
152         return null;
153     }
154 
155     SQLObject getResolvedColumnObject() {
156         return resolvedColumn;
157     }
158 
159     void setResolvedColumn(SQLColumnDefinition resolvedColumn) {
160         this.resolvedColumn = resolvedColumn;
161     }
162 
163     SQLTableSource getResolvedTableSource() {
164         if (cast(SQLTableSource)resolvedOwnerObject !is null) {
165             return cast(SQLTableSource) resolvedOwnerObject;
166         }
167 
168         return null;
169     }
170 
171     void setResolvedTableSource(SQLTableSource resolvedTableSource) {
172         this.resolvedOwnerObject = resolvedTableSource;
173     }
174 
175     SQLObject getResolvedOwnerObject() {
176         return resolvedOwnerObject;
177     }
178 
179     void setResolvedOwnerObject(SQLObject resolvedOwnerObject) {
180         this.resolvedOwnerObject = resolvedOwnerObject;
181     }
182 
183     SQLParameter getResolvedParameter() {
184         if (cast(SQLParameter)resolvedColumn !is null) {
185             return cast(SQLParameter) this.resolvedColumn;
186         }
187         return null;
188     }
189 
190     void setResolvedParameter(SQLParameter resolvedParameter) {
191         this.resolvedColumn = resolvedParameter;
192     }
193 
194     SQLDeclareItem getResolvedDeclareItem() {
195         if ( cast(SQLDeclareItem)resolvedColumn !is null) {
196             return cast(SQLDeclareItem) this.resolvedColumn;
197         }
198         return null;
199     }
200 
201     void setResolvedDeclareItem(SQLDeclareItem resolvedDeclareItem) {
202         this.resolvedColumn = resolvedDeclareItem;
203     }
204 
205     override SQLDataType computeDataType() {
206         SQLColumnDefinition resolvedColumn = getResolvedColumn();
207         if (resolvedColumn !is null) {
208             return resolvedColumn.getDataType();
209         }
210 
211         if (resolvedOwnerObject !is null
212                 &&  (cast(SQLSubqueryTableSource)resolvedOwnerObject !is null)) {
213             SQLSelect select = (cast(SQLSubqueryTableSource) resolvedOwnerObject).getSelect();
214             SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock();
215             if (queryBlock is null) {
216                 return null;
217             }
218             SQLSelectItem selectItem = queryBlock.findSelectItem(nameHashCode64());
219             if (selectItem !is null) {
220                 return selectItem.computeDataType();
221             }
222         }
223 
224         return null;
225     }
226 
227     bool nameEquals(string name) {
228         return SQLUtils.nameEquals(this.name, name);
229     }
230 
231    override
232     List!SQLObject getChildren() {
233         return Collections.emptyList!(SQLObject)();
234     }
235 
236     static bool matchIgnoreCase(SQLExpr expr, string name) {
237         // if (!(cast(SQLIdentifierExpr)(expr) !is null)) {
238         //     return false;
239         // }
240         SQLIdentifierExpr ident = cast(SQLIdentifierExpr) expr;
241         if(ident is null)
242             return false;
243         return equalsIgnoreCase(name,ident.getName());
244     }
245 }