Skip to content

Commit 209f95a

Browse files
authored
Merge pull request #329 from domaframework/issue-327
Replace table aliases in the ORDER BY clause.
2 parents 7a6cdc6 + 016a57a commit 209f95a

File tree

7 files changed

+136
-24
lines changed

7 files changed

+136
-24
lines changed

src/main/java/org/seasar/doma/internal/jdbc/dialect/StandardPagingTransformer.java

Lines changed: 79 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,17 @@
33
import static org.seasar.doma.internal.Constants.ROWNUMBER_COLUMN_NAME;
44
import static org.seasar.doma.internal.util.AssertionUtil.assertTrue;
55

6+
import java.util.function.Function;
67
import org.seasar.doma.internal.jdbc.sql.SimpleSqlNodeVisitor;
7-
import org.seasar.doma.internal.jdbc.sql.node.AnonymousNode;
8-
import org.seasar.doma.internal.jdbc.sql.node.FragmentNode;
9-
import org.seasar.doma.internal.jdbc.sql.node.FromClauseNode;
10-
import org.seasar.doma.internal.jdbc.sql.node.OrderByClauseNode;
11-
import org.seasar.doma.internal.jdbc.sql.node.SelectClauseNode;
12-
import org.seasar.doma.internal.jdbc.sql.node.SelectStatementNode;
13-
import org.seasar.doma.internal.jdbc.sql.node.WhereClauseNode;
14-
import org.seasar.doma.internal.jdbc.sql.node.WordNode;
8+
import org.seasar.doma.internal.jdbc.sql.node.*;
159
import org.seasar.doma.jdbc.JdbcException;
1610
import org.seasar.doma.jdbc.SqlNode;
1711
import org.seasar.doma.message.Message;
1812

1913
public class StandardPagingTransformer extends SimpleSqlNodeVisitor<SqlNode, Void> {
2014

15+
private final AliasReplacer replacer = new AliasReplacer();
16+
2117
protected final long offset;
2218

2319
protected final long limit;
@@ -58,18 +54,8 @@ public SqlNode visitSelectStatementNode(SelectStatementNode node, Void p) {
5854

5955
OrderByClauseNode orderBy = new OrderByClauseNode(originalOrderBy.getWordNode());
6056
for (SqlNode child : originalOrderBy.getChildren()) {
61-
if (child instanceof WordNode) {
62-
WordNode wordNode = (WordNode) child;
63-
String word = wordNode.getWord();
64-
String[] names = word.split("\\.");
65-
if (names.length == 2) {
66-
orderBy.appendNode(new WordNode("temp_." + names[1]));
67-
} else {
68-
orderBy.appendNode(child);
69-
}
70-
} else {
71-
orderBy.appendNode(child);
72-
}
57+
SqlNode newChild = child.accept(replacer, null);
58+
orderBy.appendNode(newChild);
7359
}
7460

7561
SelectClauseNode select = new SelectClauseNode("select");
@@ -108,4 +94,77 @@ public SqlNode visitSelectStatementNode(SelectStatementNode node, Void p) {
10894
protected SqlNode defaultAction(SqlNode node, Void p) {
10995
return node;
11096
}
97+
98+
protected static class AliasReplacer extends SimpleSqlNodeVisitor<SqlNode, Void> {
99+
100+
@Override
101+
public SqlNode visitWordNode(WordNode node, Void aVoid) {
102+
String word = node.getWord();
103+
String[] names = word.split("\\.");
104+
if (names.length == 2) {
105+
return new WordNode("temp_." + names[1]);
106+
}
107+
return node;
108+
}
109+
110+
@Override
111+
public SqlNode visitIfBlockNode(IfBlockNode node, Void aVoid) {
112+
IfBlockNode ifBlockNode = new IfBlockNode();
113+
IfNode originalIfNode = node.getIfNode();
114+
IfNode ifNode =
115+
buildNode(
116+
originalIfNode, o -> new IfNode(o.getLocation(), o.getExpression(), o.getText()));
117+
ifBlockNode.setIfNode(ifNode);
118+
for (ElseifNode originalElseifNode : node.getElseifNodes()) {
119+
ElseifNode elseifNode =
120+
buildNode(
121+
originalElseifNode,
122+
o -> new ElseifNode(o.getLocation(), o.getExpression(), o.getText()));
123+
ifBlockNode.addElseifNode(elseifNode);
124+
}
125+
ElseNode originalElseNode = node.getElseNode();
126+
if (originalElseNode != null) {
127+
ElseNode elseNode = buildNode(originalElseNode, o -> new ElseNode(o.getText()));
128+
ifBlockNode.setElseNode(elseNode);
129+
}
130+
EndNode originalEndNode = node.getEndNode();
131+
if (originalEndNode != null) {
132+
EndNode endNode = buildNode(originalEndNode, o -> new EndNode(o.getText()));
133+
ifBlockNode.setEndNode(endNode);
134+
}
135+
return ifBlockNode;
136+
}
137+
138+
@Override
139+
public SqlNode visitForBlockNode(ForBlockNode node, Void aVoid) {
140+
ForBlockNode forBlockNode = new ForBlockNode();
141+
ForNode originalForNode = node.getForNode();
142+
ForNode forNode =
143+
buildNode(
144+
originalForNode,
145+
o -> new ForNode(o.getLocation(), o.getIdentifier(), o.getExpression(), o.getText()));
146+
forBlockNode.setForNode(forNode);
147+
EndNode originalEndNode = node.getEndNode();
148+
if (originalEndNode != null) {
149+
EndNode endNode = buildNode(originalEndNode, o -> new EndNode(o.getText()));
150+
forBlockNode.setEndNode(endNode);
151+
}
152+
return forBlockNode;
153+
}
154+
155+
private <NODE extends AppendableSqlNode> NODE buildNode(
156+
NODE originalNode, Function<NODE, NODE> factory) {
157+
NODE newNode = factory.apply(originalNode);
158+
for (SqlNode child : originalNode.getChildren()) {
159+
SqlNode newChild = child.accept(this, null);
160+
newNode.appendNode(newChild);
161+
}
162+
return newNode;
163+
}
164+
165+
@Override
166+
protected SqlNode defaultAction(SqlNode node, Void p) {
167+
return node;
168+
}
169+
}
111170
}

src/main/java/org/seasar/doma/internal/jdbc/sql/node/ElseNode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ public ElseNode(String text) {
1414
this.text = text;
1515
}
1616

17+
public String getText() {
18+
return text;
19+
}
20+
1721
@Override
1822
public void clearChildren() {
1923
children.clear();

src/main/java/org/seasar/doma/internal/jdbc/sql/node/ElseifNode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ public String getExpression() {
2828
return expression;
2929
}
3030

31+
public String getText() {
32+
return text;
33+
}
34+
3135
@Override
3236
public void clearChildren() {
3337
children.clear();

src/main/java/org/seasar/doma/internal/jdbc/sql/node/EndNode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ public EndNode(String text) {
1111
this.text = text;
1212
}
1313

14+
public String getText() {
15+
return text;
16+
}
17+
1418
@Override
1519
public void clearChildren() {
1620
children.clear();

src/main/java/org/seasar/doma/internal/jdbc/sql/node/ForNode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ public String getExpression() {
3535
return expression;
3636
}
3737

38+
public String getText() {
39+
return text;
40+
}
41+
3842
@Override
3943
public void clearChildren() {
4044
children.clear();

src/main/java/org/seasar/doma/internal/jdbc/sql/node/IfNode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ public String getExpression() {
2828
return expression;
2929
}
3030

31+
public String getText() {
32+
return text;
33+
}
34+
3135
@Override
3236
public void clearChildren() {
3337
children.clear();

src/test/java/org/seasar/doma/internal/jdbc/dialect/StandardPagingTransformerTest.java

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@
33
import static org.junit.jupiter.api.Assertions.assertEquals;
44
import static org.junit.jupiter.api.Assertions.fail;
55

6+
import java.util.Arrays;
7+
import java.util.List;
68
import java.util.function.Function;
79
import org.junit.jupiter.api.Test;
10+
import org.seasar.doma.internal.expr.ExpressionEvaluator;
11+
import org.seasar.doma.internal.expr.Value;
812
import org.seasar.doma.internal.jdbc.mock.MockConfig;
913
import org.seasar.doma.internal.jdbc.sql.NodePreparedSqlBuilder;
1014
import org.seasar.doma.internal.jdbc.sql.SqlParser;
11-
import org.seasar.doma.jdbc.JdbcException;
12-
import org.seasar.doma.jdbc.PreparedSql;
13-
import org.seasar.doma.jdbc.SqlKind;
14-
import org.seasar.doma.jdbc.SqlNode;
15+
import org.seasar.doma.jdbc.*;
1516
import org.seasar.doma.message.Message;
1617

1718
public class StandardPagingTransformerTest {
@@ -29,6 +30,38 @@ public void testOffsetLimit() throws Exception {
2930
assertEquals(expected, sql.getRawSql());
3031
}
3132

33+
@Test
34+
public void testOffsetLimit_ifNode() throws Exception {
35+
String expected =
36+
"select * from ( select temp_.*, row_number() over( order by temp_.name desc, temp_.id ) as doma_rownumber_ from ( select emp.id from emp ) as temp_ ) as temp2_ where doma_rownumber_ > 5 and doma_rownumber_ <= 15";
37+
StandardPagingTransformer transformer = new StandardPagingTransformer(5, 10);
38+
SqlParser parser =
39+
new SqlParser("select emp.id from emp order by /*%if true*/emp.name desc,/*%end*/ emp.id");
40+
SqlNode sqlNode = transformer.transform(parser.parse());
41+
NodePreparedSqlBuilder sqlBuilder =
42+
new NodePreparedSqlBuilder(new MockConfig(), SqlKind.SELECT, "dummyPath");
43+
PreparedSql sql = sqlBuilder.build(sqlNode, Function.identity());
44+
assertEquals(expected, sql.getRawSql());
45+
}
46+
47+
@Test
48+
public void testOffsetLimit_forNode() throws Exception {
49+
String expected =
50+
"select * from ( select temp_.*, row_number() over( order by temp_.name1, temp_.name2, temp_.id ) as doma_rownumber_ from ( select emp.id from emp ) as temp_ ) as temp2_ where doma_rownumber_ > 5 and doma_rownumber_ <= 15";
51+
StandardPagingTransformer transformer = new StandardPagingTransformer(5, 10);
52+
SqlParser parser =
53+
new SqlParser(
54+
"select emp.id from emp order by /*%for e: values*/emp.name/*#e*/, /*%end*/emp.id");
55+
SqlNode sqlNode = transformer.transform(parser.parse());
56+
ExpressionEvaluator evaluator = new ExpressionEvaluator();
57+
evaluator.add("values", new Value(List.class, Arrays.asList(1, 2)));
58+
NodePreparedSqlBuilder sqlBuilder =
59+
new NodePreparedSqlBuilder(
60+
new MockConfig(), SqlKind.SELECT, "dummyPath", evaluator, SqlLogType.FORMATTED);
61+
PreparedSql sql = sqlBuilder.build(sqlNode, Function.identity());
62+
assertEquals(expected, sql.getRawSql());
63+
}
64+
3265
@Test
3366
public void testOffsetOnly() throws Exception {
3467
String expected =

0 commit comments

Comments
 (0)