Skip to content

Commit 9aae15b

Browse files
authored
Merge pull request #286 from domaframework/removable-clause
Support automatic removal of unnecessary ORDER BY and GROUP BY clauses
2 parents 3ba0eed + a1a6f87 commit 9aae15b

File tree

8 files changed

+105
-34
lines changed

8 files changed

+105
-34
lines changed

docs/sql.rst

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -463,11 +463,17 @@ You can nest condition directives as follows:
463463
/*%end*/
464464
/*%end*/
465465
466-
Removal of WHERE and HAVING clauses on condition directive
467-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
466+
Removal of clauses on the condition directive
467+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
468+
469+
Following clauses can become unnecessary on the condition directive:
470+
471+
* WHERE
472+
* HAVING
473+
* ORDER BY
474+
* GROUP BY
468475

469-
WHERE and HAVING clauses can be unnecessary on condition directive.
470-
Those clauses are removed automatically.
476+
In the case, they are removed automatically.
471477

472478
Suppose you have the following SQL template:
473479

@@ -488,11 +494,11 @@ the generated SQL statement is as follows:
488494
Because the SQL clause ``where`` followed by ``/*%if ...*/`` is unnecessary,
489495
it is removed automatically.
490496

491-
Removal of AND and OR keywords on condition directives
492-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
497+
Removal of AND and OR keywords on the condition directives
498+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
493499

494-
AND and OR keywords can be unnecessary on condition directive.
495-
Those clauses are removed automatically.
500+
AND and OR keywords can become unnecessary on the condition directive.
501+
In the case, they are removed automatically.
496502

497503
Suppose you have the following SQL template:
498504

@@ -588,11 +594,17 @@ the generated SQL statement is as follows:
588594
or
589595
employee_name like ?
590596
591-
Removal of WHERE and HAVING clauses on loop directive
592-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
597+
Removal of clauses on the loop directive
598+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
599+
600+
Following clauses can become unnecessary on the loop directive:
601+
602+
* WHERE
603+
* HAVING
604+
* ORDER BY
605+
* GROUP BY
593606

594-
WHERE and HAVING clauses can be unnecessary on loop directive.
595-
Those clauses are removed automatically.
607+
In the case, they are removed automatically.
596608

597609
Suppose you have the following SQL template:
598610

@@ -616,11 +628,11 @@ the generated SQL statement is as follows:
616628
Because the SQL clause ``where`` followed by ``/*%for ...*/`` is unnecessary,
617629
it is removed automatically.
618630

619-
Removal of AND and OR keywords on loop directive
620-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
631+
Removal of AND and OR keywords on the loop directive
632+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
621633

622-
AND and OR keywords can be unnecessary on loop directive.
623-
Those keywords are removed automatically.
634+
AND and OR keywords can become unnecessary on the loop directive.
635+
In the case, they are removed automatically.
624636

625637
Suppose you have the following SQL template:
626638

src/main/java/org/seasar/doma/internal/jdbc/sql/NodePreparedSqlBuilder.java

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.seasar.doma.internal.jdbc.scalar.Scalars;
2525
import org.seasar.doma.internal.jdbc.sql.node.AnonymousNode;
2626
import org.seasar.doma.internal.jdbc.sql.node.BindVariableNode;
27-
import org.seasar.doma.internal.jdbc.sql.node.ClauseNode;
2827
import org.seasar.doma.internal.jdbc.sql.node.CommentNode;
2928
import org.seasar.doma.internal.jdbc.sql.node.ElseNode;
3029
import org.seasar.doma.internal.jdbc.sql.node.ElseifNode;
@@ -48,6 +47,7 @@
4847
import org.seasar.doma.internal.jdbc.sql.node.OtherNode;
4948
import org.seasar.doma.internal.jdbc.sql.node.ParensNode;
5049
import org.seasar.doma.internal.jdbc.sql.node.PopulateNode;
50+
import org.seasar.doma.internal.jdbc.sql.node.RemovableClauseNode;
5151
import org.seasar.doma.internal.jdbc.sql.node.SelectClauseNode;
5252
import org.seasar.doma.internal.jdbc.sql.node.SelectStatementNode;
5353
import org.seasar.doma.internal.jdbc.sql.node.SetClauseNode;
@@ -541,23 +541,19 @@ public Void visitFromClauseNode(FromClauseNode node, Context p) {
541541

542542
@Override
543543
public Void visitWhereClauseNode(WhereClauseNode node, Context p) {
544-
handleConditionalClauseNode(node, p);
544+
handleRemovableClauseNode(node, p);
545545
return null;
546546
}
547547

548548
@Override
549549
public Void visitGroupByClauseNode(GroupByClauseNode node, Context p) {
550-
WordNode wordNode = node.getWordNode();
551-
wordNode.accept(this, p);
552-
for (SqlNode child : node.getChildren()) {
553-
child.accept(this, p);
554-
}
550+
handleRemovableClauseNode(node, p);
555551
return null;
556552
}
557553

558554
@Override
559555
public Void visitHavingClauseNode(HavingClauseNode node, Context p) {
560-
handleConditionalClauseNode(node, p);
556+
handleRemovableClauseNode(node, p);
561557
return null;
562558
}
563559

@@ -573,11 +569,7 @@ public Void visitOptionClauseNode(OptionClauseNode node, Context p) {
573569

574570
@Override
575571
public Void visitOrderByClauseNode(OrderByClauseNode node, Context p) {
576-
WordNode wordNode = node.getWordNode();
577-
wordNode.accept(this, p);
578-
for (SqlNode child : node.getChildren()) {
579-
child.accept(this, p);
580-
}
572+
handleRemovableClauseNode(node, p);
581573
return null;
582574
}
583575

@@ -591,7 +583,7 @@ public Void visitForUpdateClauseNode(ForUpdateClauseNode node, Context p) {
591583
return null;
592584
}
593585

594-
protected void handleConditionalClauseNode(ClauseNode node, Context p) {
586+
protected void handleRemovableClauseNode(RemovableClauseNode node, Context p) {
595587
Context context = new Context(p);
596588
for (SqlNode child : node.getChildren()) {
597589
child.accept(this, context);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import org.seasar.doma.DomaNullPointerException;
44
import org.seasar.doma.jdbc.SqlNodeVisitor;
55

6-
public class GroupByClauseNode extends AbstractClauseNode {
6+
public class GroupByClauseNode extends AbstractClauseNode implements RemovableClauseNode {
77

88
public GroupByClauseNode(String word) {
99
super(word);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import org.seasar.doma.DomaNullPointerException;
44
import org.seasar.doma.jdbc.SqlNodeVisitor;
55

6-
public class HavingClauseNode extends AbstractClauseNode {
6+
public class HavingClauseNode extends AbstractClauseNode implements RemovableClauseNode {
77

88
public HavingClauseNode(String word) {
99
super(word);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import org.seasar.doma.DomaNullPointerException;
44
import org.seasar.doma.jdbc.SqlNodeVisitor;
55

6-
public class OrderByClauseNode extends AbstractClauseNode {
6+
public class OrderByClauseNode extends AbstractClauseNode implements RemovableClauseNode {
77

88
public OrderByClauseNode(String word) {
99
super(word);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package org.seasar.doma.internal.jdbc.sql.node;
2+
3+
public interface RemovableClauseNode extends ClauseNode {}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import org.seasar.doma.DomaNullPointerException;
44
import org.seasar.doma.jdbc.SqlNodeVisitor;
55

6-
public class WhereClauseNode extends AbstractClauseNode {
6+
public class WhereClauseNode extends AbstractClauseNode implements RemovableClauseNode {
77

88
public WhereClauseNode(String word) {
99
super(word);

src/test/java/org/seasar/doma/internal/jdbc/sql/SqlParserTest.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,36 @@ public void testIf_removeWhere() throws Exception {
448448
assertEquals(0, sql.getParameters().size());
449449
}
450450

451+
public void testIf_removeOrderBy() throws Exception {
452+
ExpressionEvaluator evaluator = new ExpressionEvaluator();
453+
evaluator.add("name", new Value(String.class, null));
454+
String testSql = "select * from aaa order by /*%if name != null*/bbb/*%end*/";
455+
SqlParser parser = new SqlParser(testSql);
456+
SqlNode sqlNode = parser.parse();
457+
PreparedSql sql =
458+
new NodePreparedSqlBuilder(
459+
config, SqlKind.SELECT, "dummyPath", evaluator, SqlLogType.FORMATTED)
460+
.build(sqlNode, Function.identity());
461+
assertEquals("select * from aaa", sql.getRawSql());
462+
assertEquals("select * from aaa", sql.getFormattedSql());
463+
assertEquals(0, sql.getParameters().size());
464+
}
465+
466+
public void testIf_removeGroupBy() throws Exception {
467+
ExpressionEvaluator evaluator = new ExpressionEvaluator();
468+
evaluator.add("name", new Value(String.class, null));
469+
String testSql = "select * from aaa group by /*%if name != null*/bbb/*%end*/";
470+
SqlParser parser = new SqlParser(testSql);
471+
SqlNode sqlNode = parser.parse();
472+
PreparedSql sql =
473+
new NodePreparedSqlBuilder(
474+
config, SqlKind.SELECT, "dummyPath", evaluator, SqlLogType.FORMATTED)
475+
.build(sqlNode, Function.identity());
476+
assertEquals("select * from aaa", sql.getRawSql());
477+
assertEquals("select * from aaa", sql.getFormattedSql());
478+
assertEquals(0, sql.getParameters().size());
479+
}
480+
451481
public void testIf_removeAnd() throws Exception {
452482
ExpressionEvaluator evaluator = new ExpressionEvaluator();
453483
evaluator.add("name", new Value(String.class, null));
@@ -628,6 +658,40 @@ public void testFor_removeWhere() throws Exception {
628658
assertEquals(0, sql.getParameters().size());
629659
}
630660

661+
public void testFor_removeOrderBy() throws Exception {
662+
ExpressionEvaluator evaluator = new ExpressionEvaluator();
663+
ArrayList<String> list = new ArrayList<String>();
664+
evaluator.add("names", new Value(List.class, list));
665+
String testSql =
666+
"select * from aaa order by /*%for n : names*/name = /*n*/'a' /*%if n_has_next */, /*%end*//*%end*/";
667+
SqlParser parser = new SqlParser(testSql);
668+
SqlNode sqlNode = parser.parse();
669+
PreparedSql sql =
670+
new NodePreparedSqlBuilder(
671+
config, SqlKind.SELECT, "dummyPath", evaluator, SqlLogType.FORMATTED)
672+
.build(sqlNode, Function.identity());
673+
assertEquals("select * from aaa", sql.getRawSql());
674+
assertEquals("select * from aaa", sql.getFormattedSql());
675+
assertEquals(0, sql.getParameters().size());
676+
}
677+
678+
public void testFor_removeGroupBy() throws Exception {
679+
ExpressionEvaluator evaluator = new ExpressionEvaluator();
680+
ArrayList<String> list = new ArrayList<String>();
681+
evaluator.add("names", new Value(List.class, list));
682+
String testSql =
683+
"select * from aaa group by /*%for n : names*/name = /*n*/'a' /*%if n_has_next */, /*%end*//*%end*/";
684+
SqlParser parser = new SqlParser(testSql);
685+
SqlNode sqlNode = parser.parse();
686+
PreparedSql sql =
687+
new NodePreparedSqlBuilder(
688+
config, SqlKind.SELECT, "dummyPath", evaluator, SqlLogType.FORMATTED)
689+
.build(sqlNode, Function.identity());
690+
assertEquals("select * from aaa", sql.getRawSql());
691+
assertEquals("select * from aaa", sql.getFormattedSql());
692+
assertEquals(0, sql.getParameters().size());
693+
}
694+
631695
public void testFor_removeOr() throws Exception {
632696
ExpressionEvaluator evaluator = new ExpressionEvaluator();
633697
ArrayList<String> list = new ArrayList<String>();

0 commit comments

Comments
 (0)