Skip to content

Commit fbdc17f

Browse files
committed
Render DML RETURNING expressions through shared visitor handling
1 parent 0ecf096 commit fbdc17f

5 files changed

Lines changed: 69 additions & 9 deletions

File tree

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import net.sf.jsqlparser.expression.ExpressionVisitor;
1313
import net.sf.jsqlparser.statement.update.UpdateSet;
14+
import net.sf.jsqlparser.statement.ReturningClause;
1415

1516
import java.util.List;
1617

@@ -43,6 +44,14 @@ public static void deparseUpdateSets(List<UpdateSet> updateSets, StringBuilder b
4344
}
4445
}
4546

47+
protected void deparseReturningClause(ReturningClause clause,
48+
ExpressionVisitor<StringBuilder> visitor) {
49+
if (clause != null) {
50+
SelectDeParser selectItems = new SelectDeParser(visitor, builder);
51+
clause.appendTo(builder, item -> item.accept(selectItems, null));
52+
}
53+
}
54+
4655
public StringBuilder getBuilder() {
4756
return builder;
4857
}

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,7 @@ public void deParse(Delete delete) {
109109
builder.append(delete.getOption());
110110
}
111111

112-
if (delete.getReturningClause() != null) {
113-
delete.getReturningClause().appendTo(builder);
114-
}
112+
deparseReturningClause(delete.getReturningClause(), expressionVisitor);
115113

116114
}
117115

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,7 @@ public void deParse(Insert insert) {
153153
insert.getConflictAction().appendTo(builder);
154154
}
155155

156-
if (insert.getReturningClause() != null) {
157-
insert.getReturningClause().appendTo(builder);
158-
}
156+
deparseReturningClause(insert.getReturningClause(), expressionVisitor);
159157
}
160158

161159
public ExpressionVisitor<StringBuilder> getExpressionVisitor() {

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,7 @@ public void deParse(Update update) {
101101
builder.append(update.getOption());
102102
}
103103

104-
if (update.getReturningClause() != null) {
105-
update.getReturningClause().appendTo(builder);
106-
}
104+
deparseReturningClause(update.getReturningClause(), expressionVisitor);
107105
}
108106

109107
protected void deparseWhereClause(Update update) {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2019 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.util.deparser;
11+
12+
import static org.junit.jupiter.api.Assertions.assertEquals;
13+
import java.util.ArrayList;
14+
import java.util.List;
15+
import net.sf.jsqlparser.expression.LongValue;
16+
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
17+
import org.junit.jupiter.params.ParameterizedTest;
18+
import org.junit.jupiter.params.provider.ValueSource;
19+
20+
class DmlReturningExpressionTest {
21+
@ParameterizedTest
22+
@ValueSource(strings = {"UPDATE t SET a = 7 RETURNING a + 8 AS result",
23+
"DELETE FROM t WHERE a = 7 RETURNING a + 8 AS result",
24+
"INSERT INTO t(a) VALUES (7) RETURNING a + 8 AS result",
25+
"UPDATE t SET a = 7 RETURNING (SELECT b + 8 FROM source) AS result"})
26+
void visitsReturnedExpressionsExactlyOnce(String sql) throws Exception {
27+
var statement = CCJSqlParserUtil.parse(sql);
28+
String original = statement.toString();
29+
List<Long> seen = new ArrayList<>();
30+
ExpressionDeParser expressions = new ExpressionDeParser() {
31+
@Override
32+
public <S> StringBuilder visit(LongValue value, S context) {
33+
seen.add(value.getValue());
34+
return getBuilder().append(value.getValue() + 100);
35+
}
36+
};
37+
StringBuilder output = new StringBuilder();
38+
statement.accept(new StatementDeParser(expressions, new SelectDeParser(), output), null);
39+
assertEquals(List.of(7L, 8L), seen);
40+
assertEquals(original.replace("7", "107").replace("8", "108"), output.toString());
41+
assertEquals(original, statement.toString());
42+
assertEquals(output.toString(), CCJSqlParserUtil.parse(output.toString()).toString());
43+
}
44+
45+
@ParameterizedTest
46+
@ValueSource(strings = {"INSERT INTO t(a) VALUES (1) RETURNING *",
47+
"DELETE FROM t RETURNING t.*, a AS result",
48+
"UPDATE t SET a = 1 RETURNING a, b INTO x, y",
49+
"DELETE FROM t RETURNING WITH (OLD AS o, NEW AS n) o.*, n.id"})
50+
void preservesWildcardsAliasesAndOutputTargets(String sql) throws Exception {
51+
var statement = CCJSqlParserUtil.parse(sql);
52+
StringBuilder output = new StringBuilder();
53+
statement.accept(new StatementDeParser(output), null);
54+
assertEquals(statement.toString(), output.toString());
55+
assertEquals(statement.toString(), CCJSqlParserUtil.parse(output.toString()).toString());
56+
}
57+
}

0 commit comments

Comments
 (0)