Skip to content

Commit 6f89332

Browse files
committed
Merge pull request #197 from chiastic-security/update-order-by-limit-issue-195
Issue 195: support for ORDER BY and LIMIT, in UPDATE and DELETE statements
2 parents 975cddf + a31333a commit 6f89332

File tree

10 files changed

+302
-79
lines changed

10 files changed

+302
-79
lines changed

src/main/java/net/sf/jsqlparser/statement/delete/Delete.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,26 @@
2525
import net.sf.jsqlparser.schema.Table;
2626
import net.sf.jsqlparser.statement.Statement;
2727
import net.sf.jsqlparser.statement.StatementVisitor;
28+
import net.sf.jsqlparser.statement.select.Limit;
29+
import net.sf.jsqlparser.statement.select.OrderByElement;
30+
import net.sf.jsqlparser.statement.select.PlainSelect;
31+
32+
import java.util.List;
2833

2934
public class Delete implements Statement {
3035

3136
private Table table;
3237
private Expression where;
38+
private Limit limit;
39+
private List<OrderByElement> orderByElements;
40+
41+
public List<OrderByElement> getOrderByElements() {
42+
return orderByElements;
43+
}
44+
45+
public void setOrderByElements(List<OrderByElement> orderByElements) {
46+
this.orderByElements = orderByElements;
47+
}
3348

3449
@Override
3550
public void accept(StatementVisitor statementVisitor) {
@@ -52,8 +67,19 @@ public void setWhere(Expression expression) {
5267
where = expression;
5368
}
5469

70+
public Limit getLimit() {
71+
return limit;
72+
}
73+
74+
public void setLimit(Limit limit) {
75+
this.limit = limit;
76+
}
77+
5578
@Override
5679
public String toString() {
57-
return "DELETE FROM " + table + ((where != null) ? " WHERE " + where : "");
80+
return "DELETE FROM " + table +
81+
((where != null) ? " WHERE " + where : "") +
82+
(orderByElements!=null? PlainSelect.orderByToString(orderByElements):"") +
83+
(limit != null ? limit : "");
5884
}
5985
}

src/main/java/net/sf/jsqlparser/statement/update/Update.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import net.sf.jsqlparser.statement.select.Join;
3333
import net.sf.jsqlparser.statement.select.PlainSelect;
3434
import net.sf.jsqlparser.statement.select.Select;
35+
import net.sf.jsqlparser.statement.select.OrderByElement;
36+
import net.sf.jsqlparser.statement.select.Limit;
3537

3638
/**
3739
* The update statement.
@@ -47,6 +49,8 @@ public class Update implements Statement {
4749
private Select select;
4850
private boolean useColumnsBrackets = true;
4951
private boolean useSelect = false;
52+
private List<OrderByElement> orderByElements;
53+
private Limit limit;
5054

5155
@Override
5256
public void accept(StatementVisitor statementVisitor) {
@@ -137,6 +141,22 @@ public void setUseSelect(boolean useSelect) {
137141
this.useSelect = useSelect;
138142
}
139143

144+
public void setOrderByElements(List<OrderByElement> orderByElements) {
145+
this.orderByElements = orderByElements;
146+
}
147+
148+
public void setLimit(Limit limit) {
149+
this.limit = limit;
150+
}
151+
152+
public List<OrderByElement> getOrderByElements() {
153+
return orderByElements;
154+
}
155+
156+
public Limit getLimit() {
157+
return limit;
158+
}
159+
140160
@Override
141161
public String toString() {
142162
StringBuilder b = new StringBuilder("UPDATE ");
@@ -184,6 +204,12 @@ public String toString() {
184204
b.append(" WHERE ");
185205
b.append(where);
186206
}
207+
if (orderByElements!=null) {
208+
b.append(PlainSelect.orderByToString(orderByElements));
209+
}
210+
if (limit != null) {
211+
b.append(limit);
212+
}
187213
return b.toString();
188214
}
189215
}

src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ public void deParse(Delete delete) {
5959
delete.getWhere().accept(expressionVisitor);
6060
}
6161

62+
if(delete.getOrderByElements()!=null){
63+
new OrderByDeParser(expressionVisitor, buffer).deParse(delete.getOrderByElements());
64+
}
65+
if (delete.getLimit() != null) {
66+
new LimitDeparser(buffer).deParse(delete.getLimit());
67+
}
68+
6269
}
6370

6471
public ExpressionVisitor getExpressionVisitor() {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2015 JSQLParser
6+
* %%
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Lesser General Public License as
9+
* published by the Free Software Foundation, either version 2.1 of the
10+
* License, or (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Lesser Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Lesser Public
18+
* License along with this program. If not, see
19+
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
20+
* #L%
21+
*/
22+
package net.sf.jsqlparser.util.deparser;
23+
24+
import net.sf.jsqlparser.statement.select.Limit;
25+
26+
public class LimitDeparser {
27+
28+
private StringBuilder buffer;
29+
30+
public LimitDeparser(StringBuilder buffer) {
31+
this.buffer = buffer;
32+
}
33+
34+
public void deParse(Limit limit) {
35+
if (limit.isRowCountJdbcParameter()) {
36+
buffer.append(" LIMIT ");
37+
buffer.append("?");
38+
} else if (limit.getRowCount() >= 0) {
39+
buffer.append(" LIMIT ");
40+
buffer.append(limit.getRowCount());
41+
} else if (limit.isLimitNull()) {
42+
buffer.append(" LIMIT NULL");
43+
}
44+
45+
if (limit.isOffsetJdbcParameter()) {
46+
buffer.append(" OFFSET ?");
47+
} else if (limit.getOffset() != 0) {
48+
buffer.append(" OFFSET ").append(limit.getOffset());
49+
}
50+
}
51+
52+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2015 JSQLParser
6+
* %%
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Lesser General Public License as
9+
* published by the Free Software Foundation, either version 2.1 of the
10+
* License, or (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Lesser Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Lesser Public
18+
* License along with this program. If not, see
19+
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
20+
* #L%
21+
*/
22+
package net.sf.jsqlparser.util.deparser;
23+
24+
25+
import net.sf.jsqlparser.expression.ExpressionVisitor;
26+
import net.sf.jsqlparser.statement.select.OrderByElement;
27+
28+
import java.util.Iterator;
29+
import java.util.List;
30+
31+
public class OrderByDeParser {
32+
33+
private StringBuilder buffer;
34+
private ExpressionVisitor expressionVisitor;
35+
36+
public OrderByDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer) {
37+
this.expressionVisitor= expressionVisitor;
38+
this.buffer = buffer;
39+
}
40+
41+
public void deParse( List<OrderByElement> orderByElementList) {
42+
deParse(false, orderByElementList);
43+
}
44+
45+
46+
public void deParse(boolean oracleSiblings, List<OrderByElement> orderByElementList){
47+
if (oracleSiblings) {
48+
buffer.append(" ORDER SIBLINGS BY ");
49+
} else {
50+
buffer.append(" ORDER BY ");
51+
}
52+
53+
for (Iterator<OrderByElement> iter = orderByElementList.iterator(); iter.hasNext();) {
54+
OrderByElement orderByElement = iter.next();
55+
deParseElement(orderByElement);
56+
if (iter.hasNext()) {
57+
buffer.append(", ");
58+
}
59+
}
60+
}
61+
62+
public void deParseElement(OrderByElement orderBy){
63+
orderBy.getExpression().accept(expressionVisitor);
64+
if (!orderBy.isAsc()) {
65+
buffer.append(" DESC");
66+
} else if (orderBy.isAscDescPresent()) {
67+
buffer.append(" ASC");
68+
}
69+
if (orderBy.getNullOrdering() != null) {
70+
buffer.append(' ');
71+
buffer.append(orderBy.getNullOrdering() == OrderByElement.NullOrdering.NULLS_FIRST ? "NULLS FIRST" : "NULLS LAST");
72+
}
73+
}
74+
}

src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java

Lines changed: 5 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
* A class to de-parse (that is, tranform from JSqlParser hierarchy into a
3232
* string) a {@link net.sf.jsqlparser.statement.select.Select}
3333
*/
34-
public class SelectDeParser implements SelectVisitor, OrderByVisitor, SelectItemVisitor, FromItemVisitor, PivotVisitor {
34+
public class SelectDeParser implements SelectVisitor, SelectItemVisitor, FromItemVisitor, PivotVisitor {
3535

3636
private StringBuilder buffer;
3737
private ExpressionVisitor expressionVisitor;
@@ -147,11 +147,11 @@ public void visit(PlainSelect plainSelect) {
147147
}
148148

149149
if (plainSelect.getOrderByElements() != null) {
150-
deparseOrderBy(plainSelect.isOracleSiblings(), plainSelect.getOrderByElements());
150+
new OrderByDeParser(expressionVisitor, buffer).deParse(plainSelect.isOracleSiblings(), plainSelect.getOrderByElements());
151151
}
152152

153153
if (plainSelect.getLimit() != null) {
154-
deparseLimit(plainSelect.getLimit());
154+
new LimitDeparser(buffer).deParse(plainSelect.getLimit());
155155
}
156156
if (plainSelect.getOffset() != null) {
157157
deparseOffset(plainSelect.getOffset());
@@ -170,20 +170,6 @@ public void visit(PlainSelect plainSelect) {
170170
}
171171
}
172172

173-
@Override
174-
public void visit(OrderByElement orderBy) {
175-
orderBy.getExpression().accept(expressionVisitor);
176-
if (!orderBy.isAsc()) {
177-
buffer.append(" DESC");
178-
} else if (orderBy.isAscDescPresent()) {
179-
buffer.append(" ASC");
180-
}
181-
if (orderBy.getNullOrdering() != null) {
182-
buffer.append(' ');
183-
buffer.append(orderBy.getNullOrdering() == OrderByElement.NullOrdering.NULLS_FIRST ? "NULLS FIRST" : "NULLS LAST");
184-
}
185-
}
186-
187173
public void visit(Column column) {
188174
buffer.append(column.getFullyQualifiedName());
189175
}
@@ -271,44 +257,7 @@ public void visit(PivotXml pivot) {
271257
buffer.append("))");
272258
}
273259

274-
public void deparseOrderBy(List<OrderByElement> orderByElements) {
275-
deparseOrderBy(false, orderByElements);
276-
}
277260

278-
public void deparseOrderBy(boolean oracleSiblings, List<OrderByElement> orderByElements) {
279-
if (oracleSiblings) {
280-
buffer.append(" ORDER SIBLINGS BY ");
281-
} else {
282-
buffer.append(" ORDER BY ");
283-
}
284-
for (Iterator<OrderByElement> iter = orderByElements.iterator(); iter.hasNext();) {
285-
OrderByElement orderByElement = iter.next();
286-
orderByElement.accept(this);
287-
if (iter.hasNext()) {
288-
buffer.append(", ");
289-
}
290-
}
291-
}
292-
293-
public void deparseLimit(Limit limit) {
294-
// LIMIT n OFFSET skip
295-
if (limit.isRowCountJdbcParameter()) {
296-
buffer.append(" LIMIT ");
297-
buffer.append("?");
298-
} else if (limit.getRowCount() >= 0) {
299-
buffer.append(" LIMIT ");
300-
buffer.append(limit.getRowCount());
301-
} else if (limit.isLimitNull()) {
302-
buffer.append(" LIMIT NULL");
303-
}
304-
305-
if (limit.isOffsetJdbcParameter()) {
306-
buffer.append(" OFFSET ?");
307-
} else if (limit.getOffset() != 0) {
308-
buffer.append(" OFFSET ").append(limit.getOffset());
309-
}
310-
311-
}
312261

313262
public void deparseOffset(Offset offset) {
314263
// OFFSET offset
@@ -429,11 +378,11 @@ public void visit(SetOperationList list) {
429378
buffer.append(")");
430379
}
431380
if (list.getOrderByElements() != null) {
432-
deparseOrderBy(list.getOrderByElements());
381+
new OrderByDeParser(expressionVisitor,buffer).deParse(list.getOrderByElements());
433382
}
434383

435384
if (list.getLimit() != null) {
436-
deparseLimit(list.getLimit());
385+
new LimitDeparser(buffer).deParse(list.getLimit());
437386
}
438387
if (list.getOffset() != null) {
439388
deparseOffset(list.getOffset());

src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@
2929
import net.sf.jsqlparser.statement.update.Update;
3030
import net.sf.jsqlparser.statement.select.Select;
3131
import net.sf.jsqlparser.statement.select.SelectVisitor;
32+
import net.sf.jsqlparser.statement.select.OrderByVisitor;
33+
import net.sf.jsqlparser.statement.select.OrderByElement;
3234

3335
/**
3436
* A class to de-parse (that is, tranform from JSqlParser hierarchy into a
3537
* string) an {@link net.sf.jsqlparser.statement.update.Update}
3638
*/
37-
public class UpdateDeParser {
39+
public class UpdateDeParser implements OrderByVisitor {
3840

3941
private StringBuilder buffer;
4042
private ExpressionVisitor expressionVisitor;
@@ -116,6 +118,12 @@ public void deParse(Update update) {
116118
buffer.append(" WHERE ");
117119
update.getWhere().accept(expressionVisitor);
118120
}
121+
if (update.getOrderByElements()!=null) {
122+
new OrderByDeParser(expressionVisitor, buffer).deParse(update.getOrderByElements());
123+
}
124+
if (update.getLimit() != null) {
125+
new LimitDeparser(buffer).deParse(update.getLimit());
126+
}
119127

120128
}
121129

@@ -126,4 +134,18 @@ public ExpressionVisitor getExpressionVisitor() {
126134
public void setExpressionVisitor(ExpressionVisitor visitor) {
127135
expressionVisitor = visitor;
128136
}
137+
138+
@Override
139+
public void visit(OrderByElement orderBy) {
140+
orderBy.getExpression().accept(expressionVisitor);
141+
if (!orderBy.isAsc()) {
142+
buffer.append(" DESC");
143+
} else if (orderBy.isAscDescPresent()) {
144+
buffer.append(" ASC");
145+
}
146+
if (orderBy.getNullOrdering() != null) {
147+
buffer.append(' ');
148+
buffer.append(orderBy.getNullOrdering() == OrderByElement.NullOrdering.NULLS_FIRST ? "NULLS FIRST" : "NULLS LAST");
149+
}
150+
}
129151
}

0 commit comments

Comments
 (0)