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.statement.SQLExprTableSource; 17 18 19 import hunt.collection; 20 21 import hunt.sql.SQLUtils; 22 import hunt.sql.ast.SQLExpr; 23 import hunt.sql.ast.SQLName; 24 import hunt.sql.ast.SQLReplaceable; 25 import hunt.sql.ast.SQLStatement; 26 import hunt.sql.ast.expr.SQLIdentifierExpr; 27 import hunt.sql.ast.expr.SQLPropertyExpr; 28 import hunt.sql.repository.SchemaObject; 29 import hunt.sql.visitor.SQLASTVisitor; 30 import hunt.sql.util.FnvHash; 31 import hunt.sql.ast.statement.SQLColumnDefinition; 32 import hunt.sql.ast.statement.SQLTableSourceImpl; 33 import hunt.sql.ast.statement.SQLTableSource; 34 import hunt.sql.ast.statement.SQLCreateTableStatement; 35 import hunt.util.StringBuilder; 36 37 38 public class SQLExprTableSource : SQLTableSourceImpl , SQLReplaceable { 39 40 public SQLExpr expr; 41 private List!SQLName partitions; 42 private SchemaObject schemaObject; 43 44 public this(){ 45 46 } 47 48 public this(SQLExpr expr){ 49 this(expr, null); 50 } 51 52 public this(SQLExpr expr, string alias_P){ 53 this.setExpr(expr); 54 this.setAlias(alias_P); 55 } 56 57 public SQLExpr getExpr() { 58 return this.expr; 59 } 60 61 public void setExpr(SQLExpr expr) { 62 if (expr !is null) { 63 expr.setParent(this); 64 } 65 this.expr = expr; 66 } 67 68 public void setExpr(string name) { 69 this.setExpr(new SQLIdentifierExpr(name)); 70 } 71 72 public SQLName getName() { 73 if (cast(SQLName)(expr) !is null ) { 74 return cast(SQLName) expr; 75 } 76 return null; 77 } 78 79 public string getSchema() { 80 if (expr is null) { 81 return null; 82 } 83 84 if (cast(SQLPropertyExpr)(expr) !is null ) { 85 return (cast(SQLPropertyExpr) expr).getOwnernName(); 86 } 87 88 return null; 89 } 90 91 public void setSchema(string schema) { 92 if (cast(SQLIdentifierExpr)(expr) !is null ) { 93 if (schema is null) { 94 return; 95 } 96 97 string ident = (cast(SQLIdentifierExpr) expr).getName(); 98 this.setExpr(new SQLPropertyExpr(schema, ident)); 99 } else if (cast(SQLPropertyExpr)(expr) !is null ) { 100 SQLPropertyExpr propertyExpr = cast(SQLPropertyExpr) expr; 101 if (schema is null) { 102 setExpr(new SQLIdentifierExpr(propertyExpr.getName())); 103 } else { 104 propertyExpr.setOwner(schema); 105 } 106 } 107 } 108 109 public List!SQLName getPartitions() { 110 if (this.partitions is null) { 111 this.partitions = new ArrayList!SQLName(2); 112 } 113 114 return partitions; 115 } 116 117 public int getPartitionSize() { 118 if (this.partitions is null) { 119 return 0; 120 } 121 return this.partitions.size(); 122 } 123 124 public void addPartition(SQLName partition) { 125 if (partition !is null) { 126 partition.setParent(this); 127 } 128 129 if (this.partitions is null) { 130 this.partitions = new ArrayList!SQLName(2); 131 } 132 this.partitions.add(partition); 133 } 134 135 136 override protected void accept0(SQLASTVisitor visitor) { 137 if (visitor.visit(this)) { 138 acceptChild(visitor, this.expr); 139 } 140 visitor.endVisit(this); 141 } 142 143 override public void output(StringBuilder buf) { 144 this.expr.output(buf); 145 } 146 147 override 148 public bool opEquals(Object o) { 149 if (this == o) return true; 150 if (o is null || typeid(this) != typeid(o)) return false; 151 152 SQLExprTableSource that = cast(SQLExprTableSource) o; 153 154 if (expr !is null ? !(cast(Object)(expr)).opEquals(cast(Object)(that.expr)) : that.expr !is null) return false; 155 return partitions !is null ? (cast(Object)(partitions)).opEquals(cast(Object)(that.partitions)) : that.partitions is null; 156 } 157 158 override 159 public size_t toHash() @trusted nothrow { 160 size_t result = expr !is null ? (cast(Object)expr).toHash() : 0; 161 result = 31 * result + (partitions !is null ? (cast(Object)partitions).toHash() : 0); 162 return result; 163 } 164 165 override public string computeAlias() { 166 string alias_p = this.getAlias(); 167 168 if (alias_p is null) { 169 if (cast(SQLName)(expr) !is null ) { 170 alias_p =(cast(SQLName) expr).getSimpleName(); 171 } 172 } 173 174 return SQLUtils.normalize(alias_p); 175 } 176 177 override public SQLExprTableSource clone() { 178 SQLExprTableSource x = new SQLExprTableSource(); 179 cloneTo(x); 180 return x; 181 } 182 183 public void cloneTo(SQLExprTableSource x) { 184 x._alias = _alias; 185 186 if (expr !is null) { 187 x.expr = expr.clone(); 188 } 189 190 if (partitions !is null) { 191 foreach (SQLName p ; partitions) { 192 SQLName p1 = p.clone(); 193 x.addPartition(p1); 194 } 195 } 196 } 197 198 public SchemaObject getSchemaObject() { 199 return schemaObject; 200 } 201 202 public void setSchemaObject(SchemaObject schemaObject) { 203 this.schemaObject = schemaObject; 204 } 205 206 override public bool containsAlias(string alias_p) { 207 long hashCode64 = FnvHash.hashCode64(alias_p); 208 209 return containsAlias(hashCode64); 210 } 211 212 public bool containsAlias(long aliasHash) { 213 if (this.aliasHashCode64() == aliasHash) { 214 return true; 215 } 216 217 if (cast(SQLPropertyExpr)(expr) !is null ) { 218 long exprNameHash = (cast(SQLPropertyExpr) expr).hashCode64(); 219 if (exprNameHash == aliasHash) { 220 return true; 221 } 222 } 223 224 if (cast(SQLName)(expr) !is null ) { 225 long exprNameHash = (cast(SQLName) expr).nameHashCode64(); 226 return exprNameHash == aliasHash; 227 } 228 229 return false; 230 } 231 232 override public SQLColumnDefinition findColumn(string columnName) { 233 if (columnName is null) { 234 return null; 235 } 236 237 long hash = FnvHash.hashCode64(columnName); 238 return findColumn(hash); 239 } 240 241 override public SQLColumnDefinition findColumn(long columnNameHash) { 242 if (schemaObject is null) { 243 return null; 244 } 245 246 SQLStatement stmt = schemaObject.getStatement(); 247 if (cast(SQLCreateTableStatement)(stmt) !is null ) { 248 SQLCreateTableStatement createTableStmt = cast(SQLCreateTableStatement) stmt; 249 return createTableStmt.findColumn(columnNameHash); 250 } 251 return null; 252 } 253 254 override public SQLTableSource findTableSourceWithColumn(string columnName) { 255 if (columnName is null) { 256 return null; 257 } 258 259 long hash = FnvHash.hashCode64(columnName); 260 return findTableSourceWithColumn(hash); 261 } 262 263 override public SQLTableSource findTableSourceWithColumn(long columnName_hash) { 264 if (schemaObject !is null) { 265 SQLStatement stmt = schemaObject.getStatement(); 266 if (cast(SQLCreateTableStatement)(stmt) !is null ) { 267 SQLCreateTableStatement createTableStmt = cast(SQLCreateTableStatement) stmt; 268 if (createTableStmt.findColumn(columnName_hash) !is null) { 269 return this; 270 } 271 } 272 } 273 274 if (cast(SQLIdentifierExpr)(expr) !is null ) { 275 SQLTableSource tableSource = (cast(SQLIdentifierExpr) expr).getResolvedTableSource(); 276 if (tableSource !is null) { 277 return tableSource.findTableSourceWithColumn(columnName_hash); 278 } 279 } 280 281 return null; 282 } 283 284 override public SQLTableSource findTableSource(long alias_hash) { 285 if (alias_hash == 0) { 286 return null; 287 } 288 289 if (aliasHashCode64() == alias_hash) { 290 return this; 291 } 292 293 if (cast(SQLName)(expr) !is null ) { 294 long exprNameHash = (cast(SQLName) expr).nameHashCode64(); 295 if (exprNameHash == alias_hash) { 296 return this; 297 } 298 } 299 300 if (cast(SQLPropertyExpr)(expr) !is null ) { 301 long hash = (cast(SQLPropertyExpr) expr).hashCode64(); 302 if (hash == alias_hash) { 303 return this; 304 } 305 } 306 307 return null; 308 } 309 310 override 311 public bool replace(SQLExpr expr, SQLExpr target) { 312 if (expr == this.expr) { 313 this.setExpr(target); 314 return true; 315 } 316 return false; 317 } 318 }