Skip to content

Commit 321c880

Browse files
feat: RedShift specific Window function IGNORE | RESPECT NULLS
Signed-off-by: Andreas Reichel <andreas@manticore-projects.com>
1 parent 13e61a7 commit 321c880

4 files changed

Lines changed: 52 additions & 9 deletions

File tree

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ public String toString() {
277277
havingClause.appendTo(b);
278278
}
279279

280-
if (nullHandling != null) {
280+
if (nullHandling != null && !ignoreNullsOutside) {
281281
switch (nullHandling) {
282282
case IGNORE_NULLS:
283283
b.append(" IGNORE NULLS");
@@ -287,6 +287,7 @@ public String toString() {
287287
break;
288288
}
289289
}
290+
290291
if (funcOrderBy != null) {
291292
b.append(" ORDER BY ");
292293
b.append(funcOrderBy.stream().map(OrderByElement::toString).collect(joining(", ")));
@@ -310,8 +311,15 @@ public String toString() {
310311
}
311312
}
312313

313-
if (isIgnoreNullsOutside()) {
314-
b.append("IGNORE NULLS ");
314+
if (nullHandling != null && ignoreNullsOutside) {
315+
switch (nullHandling) {
316+
case IGNORE_NULLS:
317+
b.append(" IGNORE NULLS ");
318+
break;
319+
case RESPECT_NULLS:
320+
b.append(" RESPECT NULLS ");
321+
break;
322+
}
315323
}
316324

317325
switch (type) {

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ public void visit(AnalyticExpression aexpr) {
823823
havingClause.getExpression().accept(this);
824824
}
825825

826-
if (aexpr.getNullHandling() != null) {
826+
if (aexpr.getNullHandling() != null && !aexpr.isIgnoreNullsOutside()) {
827827
switch (aexpr.getNullHandling()) {
828828
case IGNORE_NULLS:
829829
buffer.append(" IGNORE NULLS");
@@ -858,8 +858,15 @@ public void visit(AnalyticExpression aexpr) {
858858
}
859859
}
860860

861-
if (aexpr.isIgnoreNullsOutside()) {
862-
buffer.append("IGNORE NULLS ");
861+
if (aexpr.getNullHandling() != null && aexpr.isIgnoreNullsOutside()) {
862+
switch (aexpr.getNullHandling()) {
863+
case IGNORE_NULLS:
864+
buffer.append(" IGNORE NULLS ");
865+
break;
866+
case RESPECT_NULLS:
867+
buffer.append(" RESPECT NULLS ");
868+
break;
869+
}
863870
}
864871

865872
switch (aexpr.getType()) {

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,14 @@ import net.sf.jsqlparser.statement.grant.*;
6969
import java.util.*;
7070
import java.util.AbstractMap.SimpleEntry;
7171

72+
import java.util.logging.Level;
73+
import java.util.logging.Logger;
74+
7275
/**
7376
* The parser generated by JavaCC
7477
*/
7578
public class CCJSqlParser extends AbstractJSqlParser<CCJSqlParser> {
79+
public final static Logger LOGGER = Logger.getLogger(CCJSqlParser.class.getName());
7680
public int bracketsCounter = 0;
7781
public int caseCounter = 0;
7882
public boolean interrupted = false;
@@ -5050,7 +5054,16 @@ void windowFun(AnalyticExpression retval):{
50505054
WindowDefinition winDef;
50515055
} {
50525056
(
5053-
[<K_IGNORE> <K_NULLS> { retval.setIgnoreNullsOutside(true); } ]
5057+
[
5058+
(
5059+
<K_IGNORE> <K_NULLS> { retval.setNullHandling(Function.NullHandling.IGNORE_NULLS); retval.setIgnoreNullsOutside(true); }
5060+
)
5061+
|
5062+
(
5063+
<K_RESPECT> <K_NULLS> { retval.setNullHandling(Function.NullHandling.RESPECT_NULLS); retval.setIgnoreNullsOutside(true); }
5064+
)
5065+
]
5066+
50545067
<K_OVER> {retval.setType(AnalyticType.OVER);}
50555068
|
50565069
<K_WITHIN> <K_GROUP> {retval.setType(AnalyticType.WITHIN_GROUP);}

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,23 @@ public class WindowFunctionTest {
1818
public void testListAggOverIssue1652() throws JSQLParserException {
1919
String sqlString =
2020
"SELECT\n" +
21-
" LISTAGG (d.COL_TO_AGG, ' / ') WITHIN GROUP (ORDER BY d.COL_TO_AGG) OVER (PARTITION BY d.PART_COL) AS MY_LISTAGG\n" +
22-
"FROM cte_dummy_data d";
21+
" LISTAGG (d.COL_TO_AGG, ' / ') WITHIN GROUP (ORDER BY d.COL_TO_AGG) OVER (PARTITION BY d.PART_COL) AS MY_LISTAGG\n"
22+
+
23+
"FROM cte_dummy_data d";
24+
25+
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlString, true);
26+
}
27+
28+
@Test
29+
public void RedshiftRespectIgnoreNulls() throws JSQLParserException {
30+
String sqlString =
31+
"select venuestate, venueseats, venuename,\n"
32+
+ "first_value(venuename) ignore nulls\n"
33+
+ "over(partition by venuestate\n"
34+
+ "order by venueseats desc\n"
35+
+ "rows between unbounded preceding and unbounded following) AS first\n"
36+
+ "from (select * from venue where venuestate='CA')\n"
37+
+ "order by venuestate;";
2338

2439
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlString, true);
2540
}

0 commit comments

Comments
 (0)