Skip to content

Commit d61020c

Browse files
author
David Hayes
committed
Add support for function parameter clauses
Adding support for clauses in function parameters. Fixes #2368 Before: Result "net.sf.jsqlparser.benchmark.JSQLParserBenchmark.parseSQLStatements": 33.555 ±(99.9%) 2.650 ms/op [Average] (min, avg, max) = (31.657, 33.555, 37.077), stdev = 2.479 CI (99.9%): [30.905, 36.205] (assumes normal distribution) After: Result "net.sf.jsqlparser.benchmark.JSQLParserBenchmark.parseSQLStatements": 33.814 ±(99.9%) 1.761 ms/op [Average] (min, avg, max) = (31.568, 33.814, 37.126), stdev = 2.351 CI (99.9%): [32.053, 35.575] (assumes normal distribution)
1 parent ededd86 commit d61020c

File tree

21 files changed

+520
-12
lines changed

21 files changed

+520
-12
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ default void visit(Function function) {
176176
this.visit(function, null);
177177
}
178178

179+
<S> T visit(FunctionParameterClauseExpression functionParameterClauseExpression, S context);
180+
181+
default void visit(FunctionParameterClauseExpression functionParameterClauseExpression) {
182+
this.visit(functionParameterClauseExpression, null);
183+
}
184+
179185
<S> T visit(SignedExpression signedExpression, S context);
180186

181187
default void visit(SignedExpression signedExpression) {

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ public <S> T visit(Function function, S context) {
123123
return visitExpressions(function, context, subExpressions);
124124
}
125125

126+
@Override
127+
public <S> T visit(FunctionParameterClauseExpression functionParameterClauseExpression,
128+
S context) {
129+
return visitExpressions(functionParameterClauseExpression, context,
130+
functionParameterClauseExpression.getExpression());
131+
}
132+
126133
@Override
127134
public <S> T visit(SignedExpression signedExpression, S context) {
128135
return signedExpression.getExpression().accept(this, context);

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

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import net.sf.jsqlparser.statement.select.Limit;
1717
import net.sf.jsqlparser.statement.select.OrderByElement;
1818

19+
import java.util.ArrayList;
1920
import java.util.Arrays;
2021
import java.util.Collections;
2122
import java.util.List;
@@ -192,6 +193,58 @@ public void setParameters(ExpressionList<?> list) {
192193
parameters = list;
193194
}
194195

196+
/**
197+
* Returns the parameter expression at the given index without any attached clause wrapper.
198+
* Returns {@code null} if there are no parameters.
199+
*/
200+
public Expression getParameterExpression(int parameterIndex) {
201+
if (parameters == null) {
202+
return null;
203+
}
204+
205+
Expression parameter = parameters.get(parameterIndex);
206+
if (parameter instanceof FunctionParameterClauseExpression) {
207+
return ((FunctionParameterClauseExpression) parameter).getExpression();
208+
}
209+
return parameter;
210+
}
211+
212+
/**
213+
* Returns the trailing clause attached to a parameter, e.g. {@code ERROR ON ERROR}, or
214+
* {@code null} when no clause is attached.
215+
*/
216+
public String getParameterTrailingClause(int parameterIndex) {
217+
if (parameters == null) {
218+
return null;
219+
}
220+
221+
Object parameter = parameters.get(parameterIndex);
222+
if (parameter instanceof FunctionParameterClauseExpression) {
223+
return ((FunctionParameterClauseExpression) parameter).getClause();
224+
}
225+
return null;
226+
}
227+
228+
/**
229+
* Returns one entry per parameter with the attached trailing clause at that index, or
230+
* {@code null} when no clause is attached to that parameter.
231+
*/
232+
public List<String> getParameterTrailingClauses() {
233+
if (parameters == null) {
234+
return Collections.emptyList();
235+
}
236+
237+
List<String> clauses = new ArrayList<>(parameters.size());
238+
for (Object parameter : parameters) {
239+
if (parameter instanceof FunctionParameterClauseExpression) {
240+
clauses.add(((FunctionParameterClauseExpression) parameter).getClause());
241+
} else {
242+
clauses.add(null);
243+
}
244+
}
245+
return clauses;
246+
}
247+
195248
/**
196249
* the parameters might be named parameters, e.g. substring('foobar' from 2 for 3)
197250
*
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2026 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.expression;
11+
12+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
13+
14+
public class FunctionParameterClauseExpression extends ASTNodeAccessImpl implements Expression {
15+
private Expression expression;
16+
private String clause;
17+
18+
public FunctionParameterClauseExpression(Expression expression, String clause) {
19+
this.expression = expression;
20+
this.clause = clause;
21+
}
22+
23+
public Expression getExpression() {
24+
return expression;
25+
}
26+
27+
public FunctionParameterClauseExpression setExpression(Expression expression) {
28+
this.expression = expression;
29+
return this;
30+
}
31+
32+
public String getClause() {
33+
return clause;
34+
}
35+
36+
public FunctionParameterClauseExpression setClause(String clause) {
37+
this.clause = clause;
38+
return this;
39+
}
40+
41+
@Override
42+
public <T, S> T accept(ExpressionVisitor<T> expressionVisitor, S context) {
43+
return expressionVisitor.visit(this, context);
44+
}
45+
46+
@Override
47+
public String toString() {
48+
if (clause == null || clause.isEmpty()) {
49+
return expression != null ? expression.toString() : "";
50+
}
51+
return expression + " " + clause;
52+
}
53+
}

src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,15 @@ public <S> Void visit(Function function, S context) {
429429
return null;
430430
}
431431

432+
@Override
433+
public <S> Void visit(FunctionParameterClauseExpression functionParameterClauseExpression,
434+
S context) {
435+
if (functionParameterClauseExpression.getExpression() != null) {
436+
functionParameterClauseExpression.getExpression().accept(this, context);
437+
}
438+
return null;
439+
}
440+
432441
@Override
433442
public <S> Void visit(GreaterThan greaterThan, S context) {
434443
visitBinaryExpression(greaterThan);

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import net.sf.jsqlparser.expression.ExpressionVisitor;
3131
import net.sf.jsqlparser.expression.ExtractExpression;
3232
import net.sf.jsqlparser.expression.Function;
33+
import net.sf.jsqlparser.expression.FunctionParameterClauseExpression;
3334
import net.sf.jsqlparser.expression.HexValue;
3435
import net.sf.jsqlparser.expression.HighExpression;
3536
import net.sf.jsqlparser.expression.IntervalExpression;
@@ -939,6 +940,13 @@ public <S> StringBuilder visit(Function function, S context) {
939940
return builder;
940941
}
941942

943+
@Override
944+
public <S> StringBuilder visit(
945+
FunctionParameterClauseExpression functionParameterClauseExpression, S context) {
946+
builder.append(functionParameterClauseExpression);
947+
return builder;
948+
}
949+
942950
@Override
943951
public <S> StringBuilder visit(ParenthesedSelect selectBody, S context) {
944952
selectBody.getSelect().accept(this, context);

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import net.sf.jsqlparser.expression.Expression;
1313
import net.sf.jsqlparser.expression.ExpressionVisitor;
14+
import net.sf.jsqlparser.expression.FunctionParameterClauseExpression;
1415
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
1516
import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList;
1617
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
@@ -55,7 +56,11 @@ public void deParse(ExpressionList<?> expressionList) {
5556
builder.append(name);
5657
builder.append(" ");
5758
}
58-
expression.accept(expressionVisitor, null);
59+
if (expression instanceof FunctionParameterClauseExpression) {
60+
builder.append(expression);
61+
} else {
62+
expression.accept(expressionVisitor, null);
63+
}
5964
i++;
6065
}
6166

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import net.sf.jsqlparser.expression.ExpressionVisitor;
3030
import net.sf.jsqlparser.expression.ExtractExpression;
3131
import net.sf.jsqlparser.expression.Function;
32+
import net.sf.jsqlparser.expression.FunctionParameterClauseExpression;
3233
import net.sf.jsqlparser.expression.HexValue;
3334
import net.sf.jsqlparser.expression.HighExpression;
3435
import net.sf.jsqlparser.expression.IntervalExpression;
@@ -547,6 +548,13 @@ public <S> Void visit(Function function, S context) {
547548
return null;
548549
}
549550

551+
@Override
552+
public <S> Void visit(FunctionParameterClauseExpression functionParameterClauseExpression,
553+
S context) {
554+
validateOptionalExpression(functionParameterClauseExpression.getExpression(), this);
555+
return null;
556+
}
557+
550558
@Override
551559
public <S> Void visit(DateValue dateValue, S context) {
552560
// nothing to validate

0 commit comments

Comments
 (0)