1 module hunt.sql.ast.expr.SQLAggregateExpr; 2 3 import hunt.sql.ast; 4 import hunt.sql.visitor.SQLASTVisitor; 5 import hunt.sql.ast.expr.SQLAggregateOption; 6 import hunt.sql.util.FnvHash; 7 import hunt.sql.SQLUtils; 8 import hunt.sql.ast.expr.SQLIntegerExpr; 9 import hunt.sql.ast.expr.SQLCharExpr; 10 11 import hunt.collection; 12 13 14 public class SQLAggregateExpr : SQLExprImpl , SQLReplaceable { 15 16 protected string methodName; 17 protected long _methodNameHashCod64; 18 19 protected SQLAggregateOption option; 20 protected List!SQLExpr arguments; 21 protected SQLKeep keep; 22 protected SQLExpr filter; 23 protected SQLOver over; 24 protected SQLName overRef; 25 protected SQLOrderBy withinGroup; 26 protected bool ignoreNulls = false; 27 28 this() 29 { 30 arguments = new ArrayList!SQLExpr(); 31 } 32 33 public this(string methodName){ 34 this(); 35 this.methodName = methodName; 36 } 37 38 public this(string methodName, SQLAggregateOption option){ 39 this(); 40 this.methodName = methodName; 41 this.option = option; 42 } 43 44 public string getMethodName() { 45 return this.methodName; 46 } 47 48 public void setMethodName(string methodName) { 49 this.methodName = methodName; 50 } 51 52 public long methodNameHashCod64() { 53 if (_methodNameHashCod64 == 0) { 54 _methodNameHashCod64 = FnvHash.hashCode64(methodName); 55 } 56 return _methodNameHashCod64; 57 } 58 59 public SQLOrderBy getWithinGroup() { 60 return withinGroup; 61 } 62 63 public void setWithinGroup(SQLOrderBy withinGroup) { 64 if (withinGroup !is null) { 65 withinGroup.setParent(this); 66 } 67 68 this.withinGroup = withinGroup; 69 } 70 71 public SQLAggregateOption getOption() { 72 return this.option; 73 } 74 75 public void setOption(SQLAggregateOption option) { 76 this.option = option; 77 } 78 79 public List!SQLExpr getArguments() { 80 return this.arguments; 81 } 82 83 public void addArgument(SQLExpr argument) { 84 if (argument !is null) { 85 argument.setParent(this); 86 } 87 this.arguments.add(argument); 88 } 89 90 public SQLOver getOver() { 91 return over; 92 } 93 94 public void setOver(SQLOver over) { 95 if (over !is null) { 96 over.setParent(this); 97 } 98 this.over = over; 99 } 100 101 public SQLName getOverRef() { 102 return overRef; 103 } 104 105 public void setOverRef(SQLName x) { 106 if (x !is null) { 107 x.setParent(this); 108 } 109 this.overRef = x; 110 } 111 112 public SQLKeep getKeep() { 113 return keep; 114 } 115 116 public void setKeep(SQLKeep keep) { 117 if (keep !is null) { 118 keep.setParent(this); 119 } 120 this.keep = keep; 121 } 122 123 public bool isIgnoreNulls() { 124 return /*this.ignoreNulls !is null && */this.ignoreNulls; 125 } 126 127 public bool getIgnoreNulls() { 128 return this.ignoreNulls; 129 } 130 131 public void setIgnoreNulls(bool ignoreNulls) { 132 this.ignoreNulls = ignoreNulls; 133 } 134 135 public override string toString() { 136 return SQLUtils.toSQLString(this); 137 } 138 139 140 protected override void accept0(SQLASTVisitor visitor) { 141 if (visitor.visit(this)) { 142 acceptChild!SQLExpr(visitor, this.arguments); 143 acceptChild(visitor, this.keep); 144 acceptChild(visitor, this.over); 145 acceptChild(visitor, this.overRef); 146 acceptChild(visitor, this.withinGroup); 147 } 148 149 visitor.endVisit(this); 150 } 151 152 public override List!SQLObject getChildren() { 153 List!SQLObject children = new ArrayList!SQLObject(); 154 children.addAll(cast(List!SQLObject)(this.arguments)); 155 if (keep !is null) { 156 children.add(this.keep); 157 } 158 if (over !is null) { 159 children.add(over); 160 } 161 if (withinGroup !is null) { 162 children.add(withinGroup); 163 } 164 return children; 165 } 166 167 public override bool opEquals(Object o) { 168 if (this == o) return true; 169 if (o is null || typeid(SQLAggregateExpr) != typeid(o)) return false; 170 171 SQLAggregateExpr that = cast(SQLAggregateExpr) o; 172 173 if (_methodNameHashCod64 != that._methodNameHashCod64) return false; 174 if (methodName !is null ? !(methodName == that.methodName) : that.methodName !is null) return false; 175 if (option != that.option) return false; 176 if (arguments !is null ? !(cast(Object)arguments).opEquals(cast(Object)(that.arguments)) : that.arguments !is null) return false; 177 if (keep !is null ? !(cast(Object)(keep)).opEquals(cast(Object)(that.keep)) : that.keep !is null) return false; 178 if (filter !is null ? !(cast(Object)filter).opEquals(cast(Object)(that.filter)) : that.filter !is null) return false; 179 if (over !is null ? !(cast(Object)(over)).opEquals(cast(Object)(that.over)) : that.over !is null) return false; 180 if (overRef !is null ? !(cast(Object)overRef).opEquals(cast(Object)(that.overRef)) : that.overRef !is null) return false; 181 if (withinGroup !is null ? !(cast(Object)(withinGroup)).opEquals(cast(Object)(that.withinGroup)) : that.withinGroup !is null) return false; 182 return ignoreNulls == that.ignoreNulls; 183 } 184 185 public override size_t toHash() @trusted nothrow { 186 size_t result = methodName !is null ? hashOf(methodName) : 0; 187 result = 31 * result + cast(int) (_methodNameHashCod64 ^ (_methodNameHashCod64 >>> 32)); 188 result = 31 * result + hashOf(option); 189 result = 31 * result + (arguments !is null ? (cast(Object)arguments).toHash() : 0); 190 result = 31 * result + (keep !is null ? (cast(Object)keep).toHash() : 0); 191 result = 31 * result + (filter !is null ? (cast(Object)filter).toHash() : 0); 192 result = 31 * result + (over !is null ? (cast(Object)over).toHash() : 0); 193 result = 31 * result + (overRef !is null ? (cast(Object)overRef).toHash() : 0); 194 result = 31 * result + (withinGroup !is null ? (cast(Object)withinGroup).toHash() : 0); 195 result = 31 * result + hashOf(ignoreNulls); 196 return result; 197 } 198 199 public override SQLAggregateExpr clone() { 200 SQLAggregateExpr x = new SQLAggregateExpr(methodName); 201 202 x.option = option; 203 204 foreach (SQLExpr arg ; arguments) { 205 x.addArgument(arg.clone()); 206 } 207 208 if (keep !is null) { 209 x.setKeep(keep.clone()); 210 } 211 212 if (filter !is null) { 213 x.setFilter(filter.clone()); 214 } 215 216 if (over !is null) { 217 x.setOver(over.clone()); 218 } 219 220 if (overRef !is null) { 221 x.setOverRef(overRef.clone()); 222 } 223 224 if (withinGroup !is null) { 225 x.setWithinGroup(withinGroup.clone()); 226 } 227 228 x.ignoreNulls = ignoreNulls; 229 230 return x; 231 } 232 233 public SQLExpr getFilter() { 234 return filter; 235 } 236 237 public void setFilter(SQLExpr x) { 238 if (x !is null) { 239 x.setParent(this); 240 } 241 this.filter = x; 242 } 243 244 public override SQLDataType computeDataType() { 245 long hash = methodNameHashCod64(); 246 247 if (hash == FnvHash.Constants.COUNT 248 || hash == FnvHash.Constants.ROW_NUMBER) { 249 return SQLIntegerExpr.DEFAULT_DATA_TYPE; 250 } 251 252 if (arguments.size() > 0) { 253 SQLDataType dataType = arguments.get(0).computeDataType(); 254 if (dataType !is null) { 255 return dataType; 256 } 257 } 258 259 if (hash == FnvHash.Constants.WM_CONCAT 260 || hash == FnvHash.Constants.GROUP_CONCAT) { 261 return SQLCharExpr.DEFAULT_DATA_TYPE; 262 } 263 264 return null; 265 } 266 267 public bool replace(SQLExpr expr, SQLExpr target) { 268 if (target is null) { 269 return false; 270 } 271 272 for (int i = 0; i < arguments.size(); ++i) { 273 if (arguments.get(i) == expr) { 274 arguments.set(i, target); 275 target.setParent(this); 276 return true; 277 } 278 } 279 280 if (overRef == expr) { 281 setOverRef(cast(SQLName) target); 282 return true; 283 } 284 285 if (filter == expr) { 286 this.filter = target; 287 target.setParent(this); 288 } 289 290 return false; 291 } 292 }