Skip to content

Commit d6ef7b9

Browse files
authored
function order by support (#1108)
1 parent 79e2f58 commit d6ef7b9

File tree

6 files changed

+72
-13
lines changed

6 files changed

+72
-13
lines changed

src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ public void visit(Function function) {
5454
if (function.getKeep() != null) {
5555
function.getKeep().accept(this);
5656
}
57+
if (function.getOrderByElements() != null) {
58+
for (OrderByElement orderByElement : function.getOrderByElements()) {
59+
orderByElement.getExpression().accept(this);
60+
}
61+
}
5762
}
5863

5964
@Override

src/main/java/net/sf/jsqlparser/expression/Function.java

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
1515
import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList;
1616
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
17+
import net.sf.jsqlparser.statement.select.OrderByElement;
18+
import net.sf.jsqlparser.statement.select.PlainSelect;
1719

1820
/**
1921
* A function as MAX,COUNT...
@@ -28,6 +30,7 @@ public class Function extends ASTNodeAccessImpl implements Expression {
2830
private boolean isEscaped = false;
2931
private Expression attribute;
3032
private String attributeName;
33+
private List<OrderByElement> orderByElements;
3134
private KeepExpression keep = null;
3235
private boolean ignoreNulls = false;
3336

@@ -157,12 +160,29 @@ public String toString() {
157160

158161
if (parameters != null || namedParameters != null) {
159162
if (parameters != null) {
160-
params = parameters.toString();
163+
StringBuilder b = new StringBuilder();
164+
b.append("(");
161165
if (isDistinct()) {
162-
params = params.replaceFirst("\\(", "(DISTINCT ");
163-
} else if (isAllColumns()) {
164-
params = params.replaceFirst("\\(", "(ALL ");
166+
b.append("DISTINCT ");
165167
}
168+
if (isAllColumns()) {
169+
b.append("ALL ");
170+
}
171+
b.append(PlainSelect.getStringList(parameters.getExpressions(), true, false));
172+
if (orderByElements != null) {
173+
b.append(" ORDER BY ");
174+
boolean comma = false;
175+
for (OrderByElement orderByElement : orderByElements) {
176+
if (comma) {
177+
b.append(", ");
178+
} else {
179+
comma = true;
180+
}
181+
b.append(orderByElement);
182+
}
183+
}
184+
b.append(")");
185+
params = b.toString();
166186
} else {
167187
params = namedParameters.toString();
168188
}
@@ -172,7 +192,7 @@ public String toString() {
172192
params = "()";
173193
}
174194

175-
String ans = getName() + "" + params + "";
195+
String ans = getName() + params;
176196

177197
if (attribute != null) {
178198
ans += "." + attribute.toString();
@@ -231,6 +251,14 @@ public Function withDistinct(boolean distinct) {
231251
return this;
232252
}
233253

254+
public List<OrderByElement> getOrderByElements() {
255+
return orderByElements;
256+
}
257+
258+
public void setOrderByElements(List<OrderByElement> orderByElements) {
259+
this.orderByElements = orderByElements;
260+
}
261+
234262
public <E extends Expression> E getAttribute(Class<E> type) {
235263
return type.cast(getAttribute());
236264
}

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

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -481,24 +481,42 @@ public void visit(Function function) {
481481
buffer.append("()");
482482
} else {
483483
boolean oldUseBracketsInExprList = useBracketsInExprList;
484-
useBracketsInExprList = true;
484+
useBracketsInExprList = !function.isDistinct() &&
485+
!function.isAllColumns() &&
486+
function.getOrderByElements() == null;
487+
if (!useBracketsInExprList) {
488+
buffer.append("(");
489+
}
485490
if (function.isDistinct()) {
486-
useBracketsInExprList = false;
487-
buffer.append("(DISTINCT ");
491+
buffer.append("DISTINCT ");
488492
} else if (function.isAllColumns()) {
489-
useBracketsInExprList = false;
490-
buffer.append("(ALL ");
493+
buffer.append("ALL ");
491494
}
492495
if (function.getNamedParameters() != null) {
493496
visit(function.getNamedParameters());
494497
}
495498
if (function.getParameters() != null) {
496499
visit(function.getParameters());
497500
}
498-
useBracketsInExprList = oldUseBracketsInExprList;
499-
if (function.isDistinct() || function.isAllColumns()) {
501+
if (function.getOrderByElements() != null) {
502+
buffer.append(" ORDER BY ");
503+
boolean comma = false;
504+
orderByDeParser.setExpressionVisitor(this);
505+
orderByDeParser.setBuffer(buffer);
506+
for (OrderByElement orderByElement : function.getOrderByElements()) {
507+
if (comma) {
508+
buffer.append(", ");
509+
} else {
510+
comma = true;
511+
}
512+
orderByDeParser.deParseElement(orderByElement);
513+
}
514+
}
515+
if (!useBracketsInExprList) {
500516
buffer.append(")");
501517
}
518+
useBracketsInExprList = oldUseBracketsInExprList;
519+
502520
}
503521

504522
if (function.getAttribute() != null) {

src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ public void visit(Function function) {
311311
validateOptionalItemsList(function.getParameters());
312312
validateOptionalExpression(function.getAttribute(), this);
313313
validateOptionalExpression(function.getKeep(), this);
314+
validateOptionalOrderByElements(function.getOrderByElements());
314315
}
315316

316317
@Override

src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3868,6 +3868,7 @@ Function InternalFunction(Function retval) :
38683868
Token tk1 = null;
38693869
Token tk2 = null;
38703870
Expression expr1 = null;
3871+
List<OrderByElement> orderByList;
38713872
boolean ignoreNulls = false;
38723873
}
38733874
{
@@ -3881,9 +3882,10 @@ Function InternalFunction(Function retval) :
38813882
|
38823883
LOOKAHEAD(NamedExpressionListExprFirst()) namedExpressionList = NamedExpressionListExprFirst()
38833884
|
3884-
LOOKAHEAD(3) expressionList=SimpleExpressionList()
3885+
LOOKAHEAD(3) (expressionList=SimpleExpressionList() [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ])
38853886
|
38863887
expr = SubSelect() { expr.setUseBrackets(false); expressionList = new ExpressionList(expr); }
3888+
38873889
)]
38883890
[ <K_IGNORE> <K_NULLS> {retval.setIgnoreNulls(true); }]
38893891
")"

src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4495,4 +4495,9 @@ public void testKeywordAlgorithmIssue1137() throws JSQLParserException {
44954495
public void testKeywordAlgorithmIssue1138() throws JSQLParserException {
44964496
assertSqlCanBeParsedAndDeparsed("SELECT * FROM in.tablename");
44974497
}
4498+
4499+
@Test
4500+
public void testFunctionOrderBy() throws JSQLParserException {
4501+
assertSqlCanBeParsedAndDeparsed("SELECT array_agg(DISTINCT s ORDER BY b)[1] FROM t");
4502+
}
44984503
}

0 commit comments

Comments
 (0)