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.SQLSelect; 17 18 19 import hunt.collection; 20 21 import hunt.sql.SQLUtils; 22 import hunt.sql.ast; 23 import hunt.sql.ast.expr.SQLAllColumnExpr; 24 //import hunt.sql.dialect.oracle.ast.OracleSQLObject; //@gxc 25 import hunt.sql.visitor.SQLASTOutputVisitor; 26 import hunt.sql.visitor.SQLASTVisitor; 27 import hunt.sql.util.DBType; 28 import hunt.sql.ast.statement.SQLWithSubqueryClause; 29 import hunt.sql.ast.statement.SQLSelectQuery; 30 import hunt.sql.ast.statement.SQLSelectQueryBlock; 31 import hunt.sql.ast.statement.SQLUnionQuery; 32 import hunt.util.StringBuilder; 33 34 public class SQLSelect : SQLObjectImpl { 35 36 protected SQLWithSubqueryClause withSubQuery; 37 protected SQLSelectQuery query; 38 protected SQLOrderBy orderBy; 39 40 protected List!SQLHint hints; 41 42 protected SQLObject restriction; 43 44 protected bool forBrowse; 45 protected List!string forXmlOptions = null; 46 protected SQLExpr xmlPath; 47 48 protected SQLExpr rowCount; 49 protected SQLExpr offset; 50 51 public this(){ 52 53 } 54 55 public List!SQLHint getHints() { 56 if (hints is null) { 57 hints = new ArrayList!SQLHint(2); 58 } 59 return hints; 60 } 61 62 public int getHintsSize() { 63 if (hints is null) { 64 return 0; 65 } 66 return hints.size(); 67 } 68 69 public this(SQLSelectQuery query){ 70 this.setQuery(query); 71 } 72 73 public SQLWithSubqueryClause getWithSubQuery() { 74 return withSubQuery; 75 } 76 77 public void setWithSubQuery(SQLWithSubqueryClause withSubQuery) { 78 this.withSubQuery = withSubQuery; 79 } 80 81 public SQLSelectQuery getQuery() { 82 return this.query; 83 } 84 85 public void setQuery(SQLSelectQuery query) { 86 if (query !is null) { 87 query.setParent(this); 88 } 89 this.query = query; 90 } 91 92 public SQLSelectQueryBlock getQueryBlock() { 93 if (cast(SQLSelectQueryBlock)(query) !is null ) { 94 return cast(SQLSelectQueryBlock) query; 95 } 96 97 return null; 98 } 99 100 public SQLOrderBy getOrderBy() { 101 return this.orderBy; 102 } 103 104 public void setOrderBy(SQLOrderBy orderBy) { 105 if (orderBy !is null) { 106 orderBy.setParent(this); 107 } 108 this.orderBy = orderBy; 109 } 110 111 override protected void accept0(SQLASTVisitor visitor) { 112 if (visitor.visit(this)) { 113 acceptChild(visitor, this.withSubQuery); 114 acceptChild(visitor, this.query); 115 acceptChild(visitor, this.restriction); 116 acceptChild(visitor, this.orderBy); 117 acceptChild!SQLHint(visitor, this.hints); 118 acceptChild(visitor, this.offset); 119 acceptChild(visitor, this.rowCount); 120 } 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 + ((orderBy is null) ? 0 : (cast(Object)orderBy).toHash()); 130 result = prime * result + ((query is null) ? 0 : (cast(Object)query).toHash()); 131 result = prime * result + ((withSubQuery is null) ? 0 : (cast(Object)withSubQuery).toHash()); 132 return result; 133 } 134 135 override 136 public bool opEquals(Object obj) { 137 if (this == obj) return true; 138 if (obj is null) return false; 139 if (typeid(this) != typeid(obj)) return false; 140 SQLSelect other = cast(SQLSelect) obj; 141 if (orderBy is null) { 142 if (other.orderBy !is null) return false; 143 } else if (!(cast(Object)(orderBy)).opEquals(cast(Object)(other.orderBy))) return false; 144 if (query is null) { 145 if (other.query !is null) return false; 146 } else if (!(cast(Object)(query)).opEquals(cast(Object)(other.query))) return false; 147 if (withSubQuery is null) { 148 if (other.withSubQuery !is null) return false; 149 } else if (!(cast(Object)(withSubQuery)).opEquals(cast(Object)(other.withSubQuery))) return false; 150 return true; 151 } 152 153 override public void output(StringBuilder buf) { 154 string dbType = null; 155 156 SQLObject parent = this.getParent(); 157 if (cast(SQLStatement)(parent) !is null ) { 158 dbType = (cast(SQLStatement) parent).getDbType(); 159 } 160 161 // if (dbType is null && (cast(OracleSQLObject)parent) !is null ) { 162 // dbType = DBType.ORACLE; 163 // } //@gxc 164 165 if (dbType is null && (cast(SQLSelectQueryBlock)query) !is null ) { 166 dbType = (cast(SQLSelectQueryBlock) query).dbType; 167 } 168 169 SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(buf, dbType); 170 this.accept(visitor); 171 } 172 173 override public string toString() { 174 SQLObject parent = this.getParent(); 175 if (cast(SQLStatement)(parent) !is null ) { 176 string dbType = (cast(SQLStatement) parent).getDbType(); 177 178 if (dbType !is null) { 179 return SQLUtils.toSQLString(this, dbType); 180 } 181 } 182 183 // if (cast(OracleSQLObject)(parent) !is null ) { 184 // return SQLUtils.toSQLString(this, DBType.ORACLE); 185 // } //@gxc 186 187 if (cast(SQLSelectQueryBlock)(query) !is null ) { 188 string dbType = (cast(SQLSelectQueryBlock) query).dbType; 189 190 if (dbType !is null) { 191 return SQLUtils.toSQLString(this, dbType); 192 } 193 } 194 195 return super.toString(); 196 } 197 198 override public SQLSelect clone() { 199 SQLSelect x = new SQLSelect(); 200 201 x.withSubQuery = this.withSubQuery; 202 if (query !is null) { 203 x.setQuery(query.clone()); 204 } 205 206 if (orderBy !is null) { 207 x.setOrderBy(this.orderBy.clone()); 208 } 209 if (restriction !is null) { 210 x.setRestriction(restriction.clone()); 211 } 212 213 if (this.hints !is null) { 214 foreach (SQLHint hint ; this.hints) { 215 x.hints.add(hint); 216 } 217 } 218 219 x.forBrowse = forBrowse; 220 221 if (forXmlOptions !is null) { 222 x.forXmlOptions = (forXmlOptions); 223 } 224 225 if (xmlPath !is null) { 226 x.setXmlPath(xmlPath.clone()); 227 } 228 229 if (rowCount !is null) { 230 x.setRowCount(rowCount.clone()); 231 } 232 233 if (offset !is null) { 234 x.setOffset(offset.clone()); 235 } 236 237 return x; 238 } 239 240 public bool isSimple() { 241 return withSubQuery is null 242 && (hints is null || hints.size() == 0) 243 && restriction is null 244 && (!forBrowse) 245 && (forXmlOptions is null || forXmlOptions.size() == 0) 246 && xmlPath is null 247 && rowCount is null 248 && offset is null; 249 } 250 251 public SQLObject getRestriction() { 252 return this.restriction; 253 } 254 255 public void setRestriction(SQLObject restriction) { 256 if (restriction !is null) { 257 restriction.setParent(this); 258 } 259 this.restriction = restriction; 260 } 261 262 public bool isForBrowse() { 263 return forBrowse; 264 } 265 266 public void setForBrowse(bool forBrowse) { 267 this.forBrowse = forBrowse; 268 } 269 270 public List!string getForXmlOptions() { 271 if (forXmlOptions is null) { 272 forXmlOptions = new ArrayList!string(4); 273 } 274 275 return forXmlOptions; 276 } 277 278 public int getForXmlOptionsSize() { 279 if (forXmlOptions is null) { 280 return 0; 281 } 282 return forXmlOptions.size(); 283 } 284 285 public SQLExpr getRowCount() { 286 return rowCount; 287 } 288 289 public void setRowCount(SQLExpr rowCount) { 290 if (rowCount !is null) { 291 rowCount.setParent(this); 292 } 293 294 this.rowCount = rowCount; 295 } 296 297 public SQLExpr getOffset() { 298 return offset; 299 } 300 301 public void setOffset(SQLExpr offset) { 302 if (offset !is null) { 303 offset.setParent(this); 304 } 305 this.offset = offset; 306 } 307 308 public SQLExpr getXmlPath() { 309 return xmlPath; 310 } 311 312 public void setXmlPath(SQLExpr xmlPath) { 313 if (xmlPath !is null) { 314 xmlPath.setParent(this); 315 } 316 this.xmlPath = xmlPath; 317 } 318 319 public SQLSelectQueryBlock getFirstQueryBlock() { 320 if (cast(SQLSelectQueryBlock)(query) !is null ) { 321 return cast(SQLSelectQueryBlock) query; 322 } 323 324 if (cast(SQLUnionQuery)(query) !is null ) { 325 return (cast(SQLUnionQuery) query).getFirstQueryBlock(); 326 } 327 328 return null; 329 } 330 331 public bool addWhere(SQLExpr where) { 332 if (where is null) { 333 return false; 334 } 335 336 if (cast(SQLSelectQueryBlock)(query) !is null ) { 337 (cast(SQLSelectQueryBlock) query).addWhere(where); 338 return true; 339 } 340 341 if (cast(SQLUnionQuery)(query) !is null ) { 342 SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock(); 343 queryBlock.setFrom(new SQLSelect(query), "u"); 344 queryBlock.addSelectItem(new SQLAllColumnExpr()); 345 queryBlock.setParent(queryBlock); 346 query = queryBlock; 347 return true; 348 } 349 350 return false; 351 } 352 }