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.SQLSelectItem; 17 18 import hunt.sql.SQLUtils; 19 import hunt.sql.ast; 20 import hunt.sql.ast.expr.SQLAllColumnExpr; 21 import hunt.sql.ast.expr.SQLIdentifierExpr; 22 import hunt.sql.ast.expr.SQLPropertyExpr; 23 // import hunt.sql.dialect.oracle.ast.OracleSQLObject; 24 import hunt.sql.visitor.SQLASTVisitor; 25 import hunt.sql.util.FnvHash; 26 import hunt.sql.util.DBType; 27 import hunt.collection; 28 import hunt.sql.ast.statement.SQLTableSource; 29 import hunt.util.StringBuilder; 30 31 public class SQLSelectItem : SQLObjectImpl , SQLReplaceable { 32 33 protected SQLExpr expr; 34 protected string _alias; 35 36 protected bool connectByRoot = false; 37 38 protected long aliasHashCode64; 39 40 public this(){ 41 42 } 43 44 public this(SQLExpr expr){ 45 this(expr, null); 46 } 47 48 public this(SQLExpr expr, string alias_p){ 49 this.expr = expr; 50 this._alias = alias_p; 51 52 if (expr !is null) { 53 expr.setParent(this); 54 } 55 } 56 57 public this(SQLExpr expr, string alias_p, bool connectByRoot){ 58 this.connectByRoot = connectByRoot; 59 this.expr = expr; 60 this._alias = alias_p; 61 62 if (expr !is null) { 63 expr.setParent(this); 64 } 65 } 66 67 public SQLExpr getExpr() { 68 return this.expr; 69 } 70 71 public void setExpr(SQLExpr expr) { 72 if (expr !is null) { 73 expr.setParent(this); 74 } 75 this.expr = expr; 76 } 77 78 public string computeAlias() { 79 string alias_p = this.getAlias(); 80 if (alias_p is null) { 81 if (cast(SQLIdentifierExpr)(expr) !is null ) { 82 alias_p = (cast(SQLIdentifierExpr) expr).getName(); 83 } else if (cast(SQLPropertyExpr)(expr) !is null ) { 84 alias_p = (cast(SQLPropertyExpr) expr).getName(); 85 } 86 } 87 88 return SQLUtils.normalize(alias_p); 89 } 90 91 override public SQLDataType computeDataType() { 92 if (expr is null) { 93 return null; 94 } 95 96 return expr.computeDataType(); 97 } 98 99 public string getAlias() { 100 return this._alias; 101 } 102 103 public void setAlias(string alias_p) { 104 this._alias = alias_p; 105 } 106 107 override public void output(StringBuilder buf) { 108 if(this.connectByRoot) { 109 buf.append(" CONNECT_BY_ROOT "); 110 } 111 this.expr.output(buf); 112 if ((this._alias !is null) && (this._alias.length != 0)) { 113 buf.append(" AS "); 114 buf.append(this._alias); 115 } 116 } 117 118 override protected void accept0(SQLASTVisitor visitor) { 119 if (visitor.visit(this)) { 120 acceptChild(visitor, this.expr); 121 } 122 visitor.endVisit(this); 123 } 124 125 override 126 public size_t toHash() @trusted nothrow { 127 int prime = 31; 128 size_t result = 1; 129 result = prime * result + hashOf(_alias); 130 result = prime * result + ((expr is null) ? 0 : (cast(Object)expr).toHash()); 131 return result; 132 } 133 134 override 135 public bool opEquals(Object obj) { 136 if (this == obj) return true; 137 if (obj is null) return false; 138 if (typeid(this) != typeid(obj)) return false; 139 SQLSelectItem other = cast(SQLSelectItem) obj; 140 if (_alias is null) { 141 if (other._alias !is null) return false; 142 } else if (!(_alias == other._alias)) return false; 143 if (expr is null) { 144 if (other.expr !is null) return false; 145 } else if (!(cast(Object)(expr)).opEquals(cast(Object)(other.expr))) return false; 146 return true; 147 } 148 149 public bool isConnectByRoot() { 150 return connectByRoot; 151 } 152 153 public void setConnectByRoot(bool connectByRoot) { 154 this.connectByRoot = connectByRoot; 155 } 156 157 override public SQLSelectItem clone() { 158 SQLSelectItem x = new SQLSelectItem(); 159 x._alias = _alias; 160 if (expr !is null) { 161 x.setExpr(expr.clone()); 162 } 163 x.connectByRoot = connectByRoot; 164 return x; 165 } 166 167 override 168 public bool replace(SQLExpr expr, SQLExpr target) { 169 if (this.expr == expr) { 170 setExpr(target); 171 return true; 172 } 173 174 return false; 175 } 176 177 public bool match(string alias_p) { 178 if (alias_p is null) { 179 return false; 180 } 181 182 long hash = FnvHash.hashCode64(alias_p); 183 return match(hash); 184 } 185 186 public long alias_hash() { 187 if (this.aliasHashCode64 == 0) { 188 this.aliasHashCode64 = FnvHash.hashCode64(_alias); 189 } 190 return aliasHashCode64; 191 } 192 193 public bool match(long _alias_hash) { 194 long hash = alias_hash(); 195 196 if (hash == _alias_hash) { 197 return true; 198 } 199 200 if (cast(SQLAllColumnExpr)(expr) !is null ) { 201 SQLTableSource resolvedTableSource = (cast(SQLAllColumnExpr) expr).getResolvedTableSource(); 202 if (resolvedTableSource !is null 203 && resolvedTableSource.findColumn(_alias_hash) !is null) { 204 return true; 205 } 206 return false; 207 } 208 209 if (cast(SQLIdentifierExpr)(expr) !is null ) { 210 return (cast(SQLIdentifierExpr) expr).nameHashCode64() == _alias_hash; 211 } 212 213 if (cast(SQLPropertyExpr)(expr) !is null ) { 214 string ident = (cast(SQLPropertyExpr) expr).getName(); 215 if ("*" == (ident)) { 216 SQLTableSource resolvedTableSource = (cast(SQLPropertyExpr) expr).getResolvedTableSource(); 217 if (resolvedTableSource !is null 218 && resolvedTableSource.findColumn(_alias_hash) !is null) { 219 return true; 220 } 221 return false; 222 } 223 224 return (cast(SQLPropertyExpr) expr).nameHashCode64() == _alias_hash; 225 } 226 227 return false; 228 } 229 230 override public string toString() { 231 string dbType = null; 232 // if (cast(OracleSQLObject)(parent) !is null ) { 233 // dbType = DBType.ORACLE; 234 // } 235 return SQLUtils.toSQLString(this, dbType); 236 } 237 }