Skip to content

Commit 8825143

Browse files
committed
fix: visit pipe expressions through shared deparser paths
1 parent 0ecf096 commit 8825143

2 files changed

Lines changed: 83 additions & 8 deletions

File tree

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@
7979
import net.sf.jsqlparser.statement.select.UnPivot;
8080
import net.sf.jsqlparser.statement.select.Values;
8181
import net.sf.jsqlparser.statement.select.WithItem;
82-
import net.sf.jsqlparser.statement.update.UpdateSet;
8382

8483
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
8584
public class SelectDeParser extends AbstractDeParser<PlainSelect>
@@ -1159,9 +1158,11 @@ public StringBuilder visit(JoinPipeOperator join, Void context) {
11591158

11601159
@Override
11611160
public StringBuilder visit(LimitPipeOperator limit, Void context) {
1162-
builder.append("|> ").append("LIMIT ").append(limit.getLimitExpression());
1161+
builder.append("|> LIMIT ");
1162+
limit.getLimitExpression().accept(expressionVisitor, context);
11631163
if (limit.getOffsetExpression() != null) {
1164-
builder.append(" OFFSET ").append(limit.getOffsetExpression());
1164+
builder.append(" OFFSET ");
1165+
limit.getOffsetExpression().accept(expressionVisitor, context);
11651166
}
11661167
return builder;
11671168
}
@@ -1206,18 +1207,19 @@ public StringBuilder visit(SelectPipeOperator select, Void context) {
12061207

12071208
int i = 0;
12081209
for (SelectItem<?> selectItem : select.getSelectItems()) {
1209-
builder.append(i++ > 0 ? ", " : " ").append(selectItem);
1210+
builder.append(i++ > 0 ? ", " : " ");
1211+
selectItem.accept(this, context);
12101212
}
12111213
builder.append("\n");
12121214
return builder;
12131215
}
12141216

12151217
@Override
12161218
public StringBuilder visit(SetPipeOperator set, Void context) {
1217-
builder.append("|> ").append("SET");
1218-
int i = 0;
1219-
for (UpdateSet updateSet : set.getUpdateSets()) {
1220-
builder.append(i++ > 0 ? ", " : " ").append(updateSet);
1219+
builder.append("|> SET");
1220+
if (!set.getUpdateSets().isEmpty()) {
1221+
builder.append(' ');
1222+
deparseUpdateSets(set.getUpdateSets(), builder, expressionVisitor);
12211223
}
12221224
builder.append("\n");
12231225
return builder;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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+
*/
10+
package net.sf.jsqlparser.statement.piped;
11+
12+
import static org.junit.jupiter.api.Assertions.assertEquals;
13+
import java.util.ArrayList;
14+
import java.util.Arrays;
15+
import java.util.List;
16+
import net.sf.jsqlparser.expression.LongValue;
17+
import net.sf.jsqlparser.expression.StringValue;
18+
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
19+
import net.sf.jsqlparser.util.deparser.ExpressionDeParser;
20+
import net.sf.jsqlparser.util.deparser.SelectDeParser;
21+
import net.sf.jsqlparser.util.deparser.StatementDeParser;
22+
import org.junit.jupiter.api.Test;
23+
import org.junit.jupiter.params.ParameterizedTest;
24+
import org.junit.jupiter.params.provider.ValueSource;
25+
26+
class PipeExpressionDeParserTest {
27+
@Test
28+
void customPrinterVisitsEveryValueOnceAcrossThePipeline() throws Exception {
29+
String sql = "FROM t |> SELECT 1 AS a, 'secret' AS b |> EXTEND a + 2 AS c "
30+
+ "|> SET a = 3, b = 'hidden' |> LIMIT 4 OFFSET 5";
31+
var statement = CCJSqlParserUtil.parse(sql);
32+
String original = statement.toString();
33+
List<Long> visited = new ArrayList<>();
34+
List<String> strings = new ArrayList<>();
35+
StringBuilder output = new StringBuilder();
36+
ExpressionDeParser expressions = new ExpressionDeParser() {
37+
@Override
38+
public <S> StringBuilder visit(LongValue value, S context) {
39+
visited.add(value.getValue());
40+
return getBuilder().append(value.getValue() + 100);
41+
}
42+
43+
@Override
44+
public <S> StringBuilder visit(StringValue value, S context) {
45+
strings.add(value.getValue());
46+
return getBuilder().append("'masked'");
47+
}
48+
};
49+
statement.accept(new StatementDeParser(expressions, new SelectDeParser(), output), null);
50+
assertEquals(Arrays.asList(1L, 2L, 3L, 4L, 5L), visited);
51+
assertEquals(Arrays.asList("secret", "hidden"), strings);
52+
assertEquals("FROM t\n|> SELECT 101 AS a, 'masked' AS b\n"
53+
+ "|> EXTEND a + 102 AS c\n|> SET a = 103, b = 'masked'\n"
54+
+ "|> LIMIT 104 OFFSET 105", output.toString());
55+
assertEquals(original, statement.toString());
56+
assertEquals(output.toString(), CCJSqlParserUtil.parse(output.toString()).toString());
57+
}
58+
59+
@ParameterizedTest
60+
@ValueSource(strings = {"FROM t |> SELECT DISTINCT a + 1 AS b, a * 2 AS c",
61+
"FROM t |> EXTEND COALESCE(a, 1) AS b",
62+
"FROM t |> SET a = 1, b = (SELECT 2)",
63+
"FROM t |> SET (a, b) = (1, 2)",
64+
"FROM t |> LIMIT 1", "FROM t |> LIMIT 1 OFFSET 2"})
65+
void defaultPrinterPreservesAliasesSubqueriesAndAssignmentBrackets(String sql)
66+
throws Exception {
67+
var statement = CCJSqlParserUtil.parse(sql);
68+
StringBuilder output = new StringBuilder();
69+
statement.accept(new StatementDeParser(output), null);
70+
assertEquals(statement.toString(), output.toString());
71+
assertEquals(statement.toString(), CCJSqlParserUtil.parse(output.toString()).toString());
72+
}
73+
}

0 commit comments

Comments
 (0)