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.SQLDeleteStatement;
17 
18 import hunt.sql.SQLUtils;
19 import hunt.sql.ast;
20 import hunt.sql.ast.expr.SQLBinaryOpExpr;
21 import hunt.sql.ast.expr.SQLBinaryOpExprGroup;
22 import hunt.sql.ast.expr.SQLBinaryOperator;
23 import hunt.sql.ast.expr.SQLIdentifierExpr;
24 import hunt.sql.visitor.SQLASTVisitor;
25 import hunt.sql.ast.statement.SQLWithSubqueryClause;
26 import hunt.sql.ast.statement.SQLExprTableSource;
27 import hunt.sql.ast.statement.SQLTableSource;
28 import hunt.sql.ast.statement.SQLSelectQueryBlock;
29 import hunt.sql.ast.statement.SQLSubqueryTableSource;
30 import hunt.sql.ast.statement.SQLSelectQuery;
31 
32 import hunt.collection;
33 
34 public class SQLDeleteStatement : SQLStatementImpl , SQLReplaceable {
35     protected SQLWithSubqueryClause  _with;
36 
37     protected SQLTableSource tableSource;
38     protected SQLExpr        where;
39     protected SQLTableSource from;
40     protected SQLTableSource using;
41 
42     protected bool        only      = false;
43 
44     public this(){
45 
46     }
47     
48     public this(string dbType){
49         super (dbType);
50     }
51 
52     protected void cloneTo(SQLDeleteStatement x) {
53         if (headHints !is null) {
54             foreach (SQLCommentHint h ; headHints) {
55                 SQLCommentHint h2 = h.clone();
56                 h2.setParent(x);
57                 x.headHints.add(h2);
58             }
59         }
60 
61         if (_with !is null) {
62             x.setWith(_with.clone());
63         }
64 
65         if (tableSource !is null) {
66             x.setTableSource(tableSource.clone());
67         }
68         if (where !is null) {
69             x.setWhere(where.clone());
70         }
71         if (from !is null) {
72             x.setFrom(from.clone());
73         }
74         if (using !is null) {
75             x.setUsing(using.clone());
76         }
77         x.only = only;
78     }
79 
80     override public SQLDeleteStatement clone() {
81         SQLDeleteStatement x = new SQLDeleteStatement();
82         cloneTo(x);
83         return x;
84     }
85 
86     public SQLTableSource getTableSource() {
87         return tableSource;
88     }
89 
90     public SQLExprTableSource getExprTableSource() {
91         return cast(SQLExprTableSource) getTableSource();
92     }
93 
94     public void setTableSource(SQLExpr expr) {
95         this.setTableSource(new SQLExprTableSource(expr));
96     }
97 
98     public void setTableSource(SQLTableSource tableSource) {
99         if (tableSource !is null) {
100             tableSource.setParent(this);
101         }
102         this.tableSource = tableSource;
103     }
104 
105     public SQLName getTableName() {
106         if (cast(SQLExprTableSource)(this.tableSource) !is null ) {
107             SQLExprTableSource exprTableSource = cast(SQLExprTableSource) this.tableSource;
108             return cast(SQLName) exprTableSource.getExpr();
109         }
110 
111         if (cast(SQLSubqueryTableSource)(tableSource) !is null ) {
112             SQLSelectQuery selectQuery = (cast(SQLSubqueryTableSource) tableSource).getSelect().getQuery();
113             if (cast(SQLSelectQueryBlock)(selectQuery) !is null ) {
114                 SQLTableSource subQueryTableSource = (cast(SQLSelectQueryBlock) selectQuery).getFrom();
115                 if (cast(SQLExprTableSource)(subQueryTableSource) !is null ) {
116                     SQLExpr subQueryTableSourceExpr = (cast(SQLExprTableSource) subQueryTableSource).getExpr();
117                     return cast(SQLName) subQueryTableSourceExpr;
118                 }
119             }
120         }
121 
122         return null;
123     }
124 
125     public void setTableName(SQLName tableName) {
126         this.setTableSource(new SQLExprTableSource(tableName));
127     }
128 
129     public void setTableName(string name) {
130         setTableName(new SQLIdentifierExpr(name));
131     }
132 
133     public SQLExpr getWhere() {
134         return where;
135     }
136 
137     public void setWhere(SQLExpr where) {
138         if (where !is null) {
139             where.setParent(this);
140         }
141         this.where = where;
142     }
143 
144     public string getAlias() {
145         return this.tableSource.getAlias();
146     }
147 
148     public void setAlias(string alias_p) {
149         this.tableSource.setAlias(alias_p);
150     }
151 
152     
153     override  protected void accept0(SQLASTVisitor visitor) {
154         if (visitor.visit(this)) {
155             acceptChild(visitor, _with);
156             acceptChild(visitor, tableSource);
157             acceptChild(visitor, where);
158         }
159 
160         visitor.endVisit(this);
161     }
162 
163     override
164     public List!SQLObject getChildren() {
165         List!SQLObject children = new ArrayList!SQLObject();
166         if (_with !is null) {
167             children.add(_with);
168         }
169         children.add(tableSource);
170         if (where !is null) {
171             children.add(where);
172         }
173         return children;
174     }
175 
176     public SQLTableSource getFrom() {
177         return from;
178     }
179 
180     public void setFrom(SQLTableSource from) {
181         if (from !is null) {
182             from.setParent(this);
183         }
184         this.from = from;
185     }
186 
187     override
188     public bool replace(SQLExpr expr, SQLExpr target) {
189         if (where == expr) {
190             setWhere(target);
191             return true;
192         }
193         return false;
194     }
195 
196     public bool isOnly() {
197         return only;
198     }
199 
200     public void setOnly(bool only) {
201         this.only = only;
202     }
203 
204     public SQLTableSource getUsing() {
205         return using;
206     }
207 
208     public void setUsing(SQLTableSource using) {
209         this.using = using;
210     }
211 
212     public SQLWithSubqueryClause getWith() {
213         return _with;
214     }
215 
216     public void setWith(SQLWithSubqueryClause _with) {
217         if (_with !is null) {
218             _with.setParent(this);
219         }
220         this._with = _with;
221     }
222 
223     public void addCondition(string conditionSql) {
224         if (conditionSql is null || conditionSql.length == 0) {
225             return;
226         }
227 
228         SQLExpr condition = SQLUtils.toSQLExpr(conditionSql, dbType);
229         addCondition(condition);
230     }
231 
232     public void addCondition(SQLExpr expr) {
233         if (expr is null) {
234             return;
235         }
236 
237         this.setWhere(SQLBinaryOpExpr.and(where, expr));
238     }
239 
240     public bool removeCondition(string conditionSql) {
241         if (conditionSql is null || conditionSql.length == 0) {
242             return false;
243         }
244 
245         SQLExpr condition = SQLUtils.toSQLExpr(conditionSql, dbType);
246 
247         return removeCondition(condition);
248     }
249 
250     public bool removeCondition(SQLExpr condition) {
251         if (condition is null) {
252             return false;
253         }
254 
255         if (cast(SQLBinaryOpExprGroup)(where) !is null ) {
256             SQLBinaryOpExprGroup group = cast(SQLBinaryOpExprGroup) where;
257 
258             int removedCount = 0;
259             List!SQLExpr items = group.getItems();
260             for (int i = items.size() - 1; i >= 0; i--) {
261                 if ((cast(Object)(items.get(i))).opEquals(cast(Object)(condition))) {
262                     items.removeAt(i);
263                     removedCount++;
264                 }
265             }
266             if (items.size() == 0) {
267                 where = null;
268             }
269 
270             return removedCount > 0;
271         }
272 
273         if (cast(SQLBinaryOpExpr)(where) !is null ) {
274             SQLBinaryOpExpr binaryOpWhere = cast(SQLBinaryOpExpr) where;
275             SQLBinaryOperator operator = binaryOpWhere.getOperator();
276             if (operator == SQLBinaryOperator.BooleanAnd || operator == SQLBinaryOperator.BooleanOr) {
277                 List!SQLExpr items = SQLBinaryOpExpr.split(binaryOpWhere);
278 
279                 int removedCount = 0;
280                 for (int i = items.size() - 1; i >= 0; i--) {
281                     SQLExpr item = items.get(i);
282                     if ((cast(Object)(item)).opEquals(cast(Object)(condition))) {
283                         if (SQLUtils.replaceInParent(item, null)) {
284                             removedCount++;
285                         }
286                     }
287                 }
288 
289                 return removedCount > 0;
290             }
291         }
292 
293         if ((cast(Object)(condition)).opEquals(cast(Object)(where))) {
294             where = null;
295             return true;
296         }
297 
298         return false;
299     }
300 
301     public bool addWhere(SQLExpr where) {
302         if (where is null) {
303             return false;
304         }
305 
306         this.addCondition(where);
307         return true;
308     }
309 }