Skip to content

Commit 528dd72

Browse files
davyboyhayesDavid Hayes
andauthored
Fix[2312] - Fixes issue with array<double> in function declaration (#2313)
* Fix[2312] - Fixes issue with array<double> in function declaration ```sql WITH FUNCTION takesArray(x array<double>) RETURNS double RETURN x[1] + x[2] + x[3] SELECT takesArray(array[1.0, 2.0, 3.0]); ``` Is unable to be parsed as we're not able to capture the array<double> correctly. This PR fixes that, as well as some missing visitor changes from my previous PR. * Fix spotlessJavaCheck --------- Co-authored-by: David Hayes <[email protected]>
1 parent 9dfa0d6 commit 528dd72

File tree

9 files changed

+102
-7
lines changed

9 files changed

+102
-7
lines changed

src/main/java/net/sf/jsqlparser/statement/select/WithFunctionDeclaration.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package net.sf.jsqlparser.statement.select;
1111

1212
import net.sf.jsqlparser.expression.Expression;
13+
import net.sf.jsqlparser.expression.ExpressionVisitor;
1314

1415
import java.io.Serializable;
1516
import java.util.List;
@@ -100,6 +101,13 @@ public StringBuilder appendTo(StringBuilder builder) {
100101
.append(returnExpression);
101102
}
102103

104+
public <T, S> T accept(ExpressionVisitor<T> expressionVisitor, S context) {
105+
if (returnExpression != null) {
106+
return returnExpression.accept(expressionVisitor, context);
107+
}
108+
return null;
109+
}
110+
103111
@Override
104112
public String toString() {
105113
return appendTo(new StringBuilder()).toString();

src/main/java/net/sf/jsqlparser/statement/select/WithItem.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,10 @@ public <T, S> T accept(SelectVisitor<T> selectVisitor, S context) {
171171
}
172172

173173
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
174-
return statement.accept(statementVisitor, context);
174+
if (statement != null) {
175+
return statement.accept(statementVisitor, context);
176+
}
177+
return null;
175178
}
176179

177180
public WithItem<?> withWithItemList(List<SelectItem<?>> withItemList) {

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,12 @@ public Set<String> getTables(Expression expr) {
318318

319319
@Override
320320
public <S> Void visit(WithItem<?> withItem, S context) {
321-
otherItemNames.add(withItem.getAlias().getName());
322-
withItem.getSelect().accept((SelectVisitor<?>) this, context);
321+
if (withItem.getAlias() != null) {
322+
otherItemNames.add(withItem.getAlias().getName());
323+
}
324+
if (withItem.getSelect() != null) {
325+
withItem.getSelect().accept((SelectVisitor<?>) this, context);
326+
}
323327
return null;
324328
}
325329

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4405,11 +4405,20 @@ WithFunctionDeclaration WithFunctionDeclaration() #WithFunctionDeclaration:
44054405
WithFunctionParameter WithFunctionParameter() #WithFunctionParameter:
44064406
{
44074407
String name;
4408-
String type;
4408+
String type = null;
4409+
String arrayType = null;
44094410
}
44104411
{
4411-
name = RelObjectName() type = RelObjectName()
4412+
name = RelObjectName()
4413+
(
4414+
LOOKAHEAD(2) <K_ARRAY_LITERAL> "<" arrayType = RelObjectName() ">"
4415+
|
4416+
type = RelObjectName()
4417+
)
44124418
{
4419+
if (arrayType != null) {
4420+
type = "ARRAY<" + arrayType + ">";
4421+
}
44134422
return new WithFunctionParameter(name, type);
44144423
}
44154424
}

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2025 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
110
package net.sf.jsqlparser.statement.select;
211

312
import net.sf.jsqlparser.expression.Expression;
13+
import net.sf.jsqlparser.expression.ExpressionVisitor;
414
import org.junit.jupiter.api.Test;
515
import org.junit.jupiter.api.extension.ExtendWith;
616
import org.mockito.Mock;
@@ -10,6 +20,8 @@
1020

1121
import static org.assertj.core.api.Assertions.assertThat;
1222
import static org.mockito.ArgumentMatchers.any;
23+
import static org.mockito.Mockito.verify;
24+
import static org.mockito.Mockito.verifyNoInteractions;
1325
import static org.mockito.Mockito.when;
1426

1527
@ExtendWith(MockitoExtension.class)
@@ -93,4 +105,26 @@ void toStringTestWithNoParameters() {
93105
assertThat(withFunctionDeclaration.toString())
94106
.isEqualTo("FUNCTION func1() RETURNS integer RETURN 1 + 1");
95107
}
108+
109+
@Test
110+
void expressionVisitorIsNotCalledWhenNoReturnExpressionDeclared(
111+
@Mock ExpressionVisitor<Void> expressionVisitor) {
112+
withFunctionDeclaration = new WithFunctionDeclaration();
113+
114+
withFunctionDeclaration.accept(expressionVisitor, "RANDOM_CONTEXT");
115+
116+
verifyNoInteractions(expressionVisitor);
117+
}
118+
119+
@Test
120+
void expressionVisitorCalledWhenReturnExpressionDeclared(
121+
@Mock ExpressionVisitor<Void> expressionVisitor) {
122+
String context = "RANDOM_CONTEXT";
123+
withFunctionDeclaration = new WithFunctionDeclaration()
124+
.withReturnExpression(expression);
125+
126+
withFunctionDeclaration.accept(expressionVisitor, context);
127+
128+
verify(expression).accept(expressionVisitor, context);
129+
}
96130
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2025 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
110
package net.sf.jsqlparser.statement.select;
211

312
import org.junit.jupiter.api.Test;

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,13 @@ void testNotMaterializedIssue2251() throws JSQLParserException {
4242
" FUNCTION doubleupplusone(x integer)\n" +
4343
" RETURNS integer\n" +
4444
" RETURN doubleup(x) + 1\n" +
45-
"SELECT doubleupplusone(21);"
45+
"SELECT doubleupplusone(21);",
46+
"WITH\n" +
47+
" FUNCTION takesArray(x array<double>)\n" +
48+
" RETURNS double\n" +
49+
" RETURN x[1] + x[2] + x[3]\n" +
50+
"SELECT takesArray(ARRAY[1.0, 2.0, 3.0]);"
51+
4652
})
4753
void testWithFunction(String sqlStr) throws JSQLParserException {
4854
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);

src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.Set;
2727

2828
import static org.assertj.core.api.Assertions.assertThat;
29+
import static org.assertj.core.api.Assertions.assertThatCode;
2930
import static org.assertj.core.api.Assertions.assertThatThrownBy;
3031
import static org.junit.jupiter.api.Assertions.assertEquals;
3132
import static org.junit.jupiter.api.Assertions.assertNull;
@@ -697,5 +698,20 @@ void testIssue2305() throws JSQLParserException {
697698
Set<String> tables = TablesNamesFinder.findTables(sqlStr);
698699
assertThat(tables).containsExactlyInAnyOrder("tbl");
699700
}
701+
702+
@Test
703+
void assertWithItemWithFunctionDeclarationDoesNotThrowException() throws JSQLParserException {
704+
String sqlStr =
705+
"WITH FUNCTION my_with_item(param1 INT) RETURNS INT RETURN param1 + 1 SELECT * FROM my_table;";
706+
assertThatCode(() -> TablesNamesFinder.findTables(sqlStr))
707+
.doesNotThrowAnyException();
708+
}
709+
710+
@Test
711+
void assertWithItemWithFunctionDeclarationReturnsTableInSelect() throws JSQLParserException {
712+
String sqlStr =
713+
"WITH FUNCTION my_with_item(param1 INT) RETURNS INT RETURN param1 + 1 SELECT * FROM my_table;";
714+
assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactly("my_table");
715+
}
700716
}
701717

src/test/resources/simple_parsing.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,10 @@ WITH
242242
FUNCTION bye(name varchar)
243243
RETURNS varchar
244244
RETURN format('Bye %s!', 'name')
245-
SELECT hello('Finn') || ' and ' || bye('Joe');
245+
SELECT hello('Finn') || ' and ' || bye('Joe');
246+
247+
WITH
248+
FUNCTION takesArray(x array<double>)
249+
RETURNS double
250+
RETURN x[1] + x[2] + x[3]
251+
SELECT takesArray(array[1.0, 2.0, 3.0]);

0 commit comments

Comments
 (0)