Skip to content

Commit 44106f9

Browse files
committed
SQLのリテラルを埋め込むためのリテラル変数コメント /*^〜*/ を追加
1 parent 74a9808 commit 44106f9

File tree

16 files changed

+404
-96
lines changed

16 files changed

+404
-96
lines changed

src/main/java/org/seasar/doma/internal/apt/SqlValidator.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@
4646
import org.seasar.doma.internal.jdbc.sql.node.ForBlockNode;
4747
import org.seasar.doma.internal.jdbc.sql.node.ForNode;
4848
import org.seasar.doma.internal.jdbc.sql.node.IfNode;
49+
import org.seasar.doma.internal.jdbc.sql.node.LiteralVariableNode;
4950
import org.seasar.doma.internal.jdbc.sql.node.PopulateNode;
5051
import org.seasar.doma.internal.jdbc.sql.node.SqlLocation;
52+
import org.seasar.doma.internal.jdbc.sql.node.ValueNode;
5153
import org.seasar.doma.jdbc.SqlNode;
5254
import org.seasar.doma.message.Message;
5355

@@ -115,20 +117,29 @@ public void validate(SqlNode sqlNode) {
115117

116118
@Override
117119
public Void visitBindVariableNode(BindVariableNode node, Void p) {
120+
return visitValueNode(node, p);
121+
}
122+
123+
@Override
124+
public Void visitLiteralVariableNode(LiteralVariableNode node, Void p) {
125+
return visitValueNode(node, p);
126+
}
127+
128+
protected Void visitValueNode(ValueNode node, Void p) {
118129
SqlLocation location = node.getLocation();
119130
String variableName = node.getVariableName();
120131
TypeDeclaration typeDeclaration = validateExpressionVariable(location,
121132
variableName);
122133
if (node.getWordNode() != null) {
123-
if (!isBindable(typeDeclaration)) {
134+
if (!isScalar(typeDeclaration)) {
124135
String sql = getSql(location);
125136
throw new AptException(Message.DOMA4153, env, methodElement,
126137
new Object[] { path, sql, location.getLineNumber(),
127138
location.getPosition(), variableName,
128139
typeDeclaration.getBinaryName() });
129140
}
130141
} else {
131-
if (!isBindableIterable(typeDeclaration)) {
142+
if (!isScalarIterable(typeDeclaration)) {
132143
String sql = getSql(location);
133144
env.getMessager().printMessage(Kind.NOTE,
134145
parameterTypeMap.toString());
@@ -142,13 +153,13 @@ public Void visitBindVariableNode(BindVariableNode node, Void p) {
142153
return null;
143154
}
144155

145-
protected boolean isBindable(TypeDeclaration typeDeclaration) {
156+
protected boolean isScalar(TypeDeclaration typeDeclaration) {
146157
TypeMirror typeMirror = typeDeclaration.getType();
147158
return BasicCtType.newInstance(typeMirror, env) != null
148159
|| DomainCtType.newInstance(typeMirror, env) != null;
149160
}
150161

151-
protected boolean isBindableIterable(TypeDeclaration typeDeclaration) {
162+
protected boolean isScalarIterable(TypeDeclaration typeDeclaration) {
152163
TypeMirror typeMirror = typeDeclaration.getType();
153164
IterableCtType iterableCtType = IterableCtType.newInstance(typeMirror,
154165
env);

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

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.List;
2424
import java.util.StringJoiner;
2525
import java.util.function.BiConsumer;
26+
import java.util.function.Consumer;
2627
import java.util.function.Function;
2728
import java.util.function.Supplier;
2829
import java.util.regex.Matcher;
@@ -56,6 +57,7 @@
5657
import org.seasar.doma.internal.jdbc.sql.node.HavingClauseNode;
5758
import org.seasar.doma.internal.jdbc.sql.node.IfBlockNode;
5859
import org.seasar.doma.internal.jdbc.sql.node.IfNode;
60+
import org.seasar.doma.internal.jdbc.sql.node.LiteralVariableNode;
5961
import org.seasar.doma.internal.jdbc.sql.node.LogicalOperatorNode;
6062
import org.seasar.doma.internal.jdbc.sql.node.OptionClauseNode;
6163
import org.seasar.doma.internal.jdbc.sql.node.OrderByClauseNode;
@@ -68,6 +70,7 @@
6870
import org.seasar.doma.internal.jdbc.sql.node.SqlLocation;
6971
import org.seasar.doma.internal.jdbc.sql.node.UpdateClauseNode;
7072
import org.seasar.doma.internal.jdbc.sql.node.UpdateStatementNode;
73+
import org.seasar.doma.internal.jdbc.sql.node.ValueNode;
7174
import org.seasar.doma.internal.jdbc.sql.node.WhereClauseNode;
7275
import org.seasar.doma.internal.jdbc.sql.node.WhitespaceNode;
7376
import org.seasar.doma.internal.jdbc.sql.node.WordNode;
@@ -81,6 +84,7 @@
8184
import org.seasar.doma.jdbc.SqlNode;
8285
import org.seasar.doma.jdbc.SqlNodeVisitor;
8386
import org.seasar.doma.message.Message;
87+
import org.seasar.doma.wrapper.WrapperVisitor;
8488

8589
/**
8690
* @author taedium
@@ -199,21 +203,45 @@ public Void visitCommentNode(CommentNode node, Context p) {
199203

200204
@Override
201205
public Void visitBindVariableNode(BindVariableNode node, Context p) {
206+
return visitValueNode(node, p, p::addBindValue);
207+
}
208+
209+
@Override
210+
public Void visitLiteralVariableNode(final LiteralVariableNode node,
211+
Context p) {
212+
Consumer<Scalar<?, ?>> validator = (scalar) -> {
213+
Object value = scalar.get();
214+
if (value == null) {
215+
return;
216+
}
217+
String text = value.toString();
218+
if (text.indexOf('\'') > -1) {
219+
SqlLocation location = node.getLocation();
220+
throw new JdbcException(Message.DOMA2224, location.getSql(),
221+
location.getLineNumber(), location.getPosition(),
222+
node.getText());
223+
}
224+
};
225+
return visitValueNode(node, p, validator.andThen(p::addLiteralValue));
226+
}
227+
228+
protected Void visitValueNode(ValueNode node, Context p,
229+
Consumer<Scalar<?, ?>> valueHandler) {
202230
SqlLocation location = node.getLocation();
203231
String name = node.getVariableName();
204232
EvaluationResult result = p.evaluate(location, name);
205233
Object value = result.getValue();
206234
Class<?> valueClass = result.getValueClass();
207235
p.setAvailable(true);
208236
if (node.isWordNodeIgnored()) {
209-
handleSingleBindVarialbeNode(node, p, value, valueClass);
237+
handleSingleValueNode(node, p, value, valueClass, valueHandler);
210238
} else if (node.isParensNodeIgnored()) {
211239
ParensNode parensNode = node.getParensNode();
212240
OtherNode openedFragmentNode = parensNode.getOpenedFragmentNode();
213241
openedFragmentNode.accept(this, p);
214242
if (Iterable.class.isAssignableFrom(valueClass)) {
215-
handleIterableBindVarialbeNode(node, p, (Iterable<?>) value,
216-
valueClass);
243+
handleIterableValueNode(node, p, (Iterable<?>) value,
244+
valueClass, valueHandler);
217245
} else {
218246
throw new JdbcException(Message.DOMA2112, location.getSql(),
219247
location.getLineNumber(), location.getPosition(),
@@ -273,16 +301,17 @@ protected boolean startsWithClauseKeyword(String fragment) {
273301
return matcher.lookingAt();
274302
}
275303

276-
protected Void handleSingleBindVarialbeNode(BindVariableNode node,
277-
Context p, Object value, Class<?> valueClass) {
304+
protected Void handleSingleValueNode(ValueNode node, Context p,
305+
Object value, Class<?> valueClass, Consumer<Scalar<?, ?>> consumer) {
278306
Supplier<Scalar<?, ?>> supplier = wrap(node.getLocation(),
279307
node.getText(), value, valueClass);
280-
p.addBindValue(supplier.get());
308+
consumer.accept(supplier.get());
281309
return null;
282310
}
283311

284-
protected void handleIterableBindVarialbeNode(BindVariableNode node,
285-
Context p, Iterable<?> values, Class<?> valueClass) {
312+
protected void handleIterableValueNode(ValueNode node, Context p,
313+
Iterable<?> values, Class<?> valueClass,
314+
Consumer<Scalar<?, ?>> consumer) {
286315
int index = 0;
287316
for (Object v : values) {
288317
if (v == null) {
@@ -293,7 +322,7 @@ protected void handleIterableBindVarialbeNode(BindVariableNode node,
293322
}
294323
Supplier<Scalar<?, ?>> supplier = wrap(node.getLocation(),
295324
node.getText(), v, v.getClass());
296-
p.addBindValue(supplier.get());
325+
consumer.accept(supplier.get());
297326
p.appendRawSql(", ");
298327
p.appendFormattedSql(", ");
299328
index++;
@@ -635,7 +664,7 @@ public Void visitFragmentNode(FragmentNode node, Context p) {
635664

636665
@Override
637666
public Void visitParensNode(ParensNode node, Context p) {
638-
if (node.isAttachedWithBindVariable()) {
667+
if (node.isAttachedWithValue()) {
639668
return null;
640669
}
641670
Context context = new Context(p);
@@ -758,6 +787,15 @@ protected CharSequence getFormattedSqlBuf() {
758787
return formattedSqlBuf;
759788
}
760789

790+
protected <BASIC, CONTAINER> void addLiteralValue(
791+
Scalar<BASIC, CONTAINER> scalar) {
792+
String literal = scalar.getWrapper().accept(
793+
config.getDialect().getSqlLogFormattingVisitor(),
794+
formattingFunction, null);
795+
rawSqlBuf.append(literal);
796+
formattedSqlBuf.append(literal);
797+
}
798+
761799
protected <BASIC, CONTAINER> void addBindValue(
762800
Scalar<BASIC, CONTAINER> scalar) {
763801
appendParameterInternal(new ScalarInParameter<BASIC, CONTAINER>(
@@ -819,4 +857,9 @@ public String toString() {
819857
return rawSqlBuf.toString();
820858
}
821859
}
860+
861+
protected static class LiteralValueVisitor implements
862+
WrapperVisitor<String, Void, Void, RuntimeException> {
863+
864+
}
822865
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.seasar.doma.internal.jdbc.sql.node.HavingClauseNode;
3434
import org.seasar.doma.internal.jdbc.sql.node.IfBlockNode;
3535
import org.seasar.doma.internal.jdbc.sql.node.IfNode;
36+
import org.seasar.doma.internal.jdbc.sql.node.LiteralVariableNode;
3637
import org.seasar.doma.internal.jdbc.sql.node.LogicalOperatorNode;
3738
import org.seasar.doma.internal.jdbc.sql.node.OptionClauseNode;
3839
import org.seasar.doma.internal.jdbc.sql.node.OrderByClauseNode;
@@ -150,6 +151,11 @@ public R visitIfNode(IfNode node, P p) {
150151
return defaultAction(node, p);
151152
}
152153

154+
@Override
155+
public R visitLiteralVariableNode(LiteralVariableNode node, P p) {
156+
return defaultAction(node, p);
157+
}
158+
153159
@Override
154160
public R visitLogicalOperatorNode(LogicalOperatorNode node, P p) {
155161
return defaultAction(node, p);

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

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.seasar.doma.internal.jdbc.sql.node.HavingClauseNode;
4343
import org.seasar.doma.internal.jdbc.sql.node.IfBlockNode;
4444
import org.seasar.doma.internal.jdbc.sql.node.IfNode;
45+
import org.seasar.doma.internal.jdbc.sql.node.LiteralVariableNode;
4546
import org.seasar.doma.internal.jdbc.sql.node.LogicalOperatorNode;
4647
import org.seasar.doma.internal.jdbc.sql.node.OptionClauseNode;
4748
import org.seasar.doma.internal.jdbc.sql.node.OrderByClauseNode;
@@ -54,6 +55,7 @@
5455
import org.seasar.doma.internal.jdbc.sql.node.SqlLocation;
5556
import org.seasar.doma.internal.jdbc.sql.node.UpdateClauseNode;
5657
import org.seasar.doma.internal.jdbc.sql.node.UpdateStatementNode;
58+
import org.seasar.doma.internal.jdbc.sql.node.ValueNode;
5759
import org.seasar.doma.internal.jdbc.sql.node.WhereClauseAwareNode;
5860
import org.seasar.doma.internal.jdbc.sql.node.WhereClauseNode;
5961
import org.seasar.doma.internal.jdbc.sql.node.WhitespaceNode;
@@ -163,6 +165,10 @@ public SqlNode parse() {
163165
parseBindVariableBlockComment();
164166
break;
165167
}
168+
case LITERAL_VARIABLE_BLOCK_COMMENT: {
169+
parseLiteralVariableBlockComment();
170+
break;
171+
}
166172
case EMBEDDED_VARIABLE_BLOCK_COMMENT: {
167173
parseEmbeddedVariableBlockComment();
168174
break;
@@ -416,6 +422,18 @@ protected void parseBindVariableBlockComment() {
416422
push(node);
417423
}
418424

425+
protected void parseLiteralVariableBlockComment() {
426+
String varialbeName = tokenType.extract(token);
427+
if (varialbeName.isEmpty()) {
428+
throw new JdbcException(Message.DOMA2228, sql,
429+
tokenizer.getLineNumber(), tokenizer.getPosition(), token);
430+
}
431+
LiteralVariableNode node = new LiteralVariableNode(getLocation(),
432+
varialbeName, token);
433+
appendNode(node);
434+
push(node);
435+
}
436+
419437
protected void parseEmbeddedVariableBlockComment() {
420438
String varialbeName = tokenType.extract(token);
421439
if (varialbeName.isEmpty()) {
@@ -639,8 +657,8 @@ protected boolean isInBlockNode() {
639657
return false;
640658
}
641659

642-
protected boolean isAfterBindVariableNode() {
643-
return peek() instanceof BindVariableNode;
660+
protected boolean isAfterValueNode() {
661+
return peek() instanceof ValueNode;
644662
}
645663

646664
protected boolean isAfterExpandNode() {
@@ -652,27 +670,27 @@ protected boolean isAfterOrderByClauseNode() {
652670
}
653671

654672
protected void appendNode(SqlNode node) {
655-
if (isAfterBindVariableNode()) {
656-
BindVariableNode bindVariableNode = pop();
673+
if (isAfterValueNode()) {
674+
ValueNode valueNode = pop();
657675
if (node instanceof WordNode) {
658676
WordNode wordNode = (WordNode) node;
659677
String word = wordNode.getWord();
660678
Matcher matcher = LITERAL_PATTERN.matcher(word);
661679
if (matcher.lookingAt()) {
662-
bindVariableNode.setWordNode(wordNode);
680+
valueNode.setWordNode(wordNode);
663681
} else {
664682
throw new JdbcException(Message.DOMA2142, sql,
665683
tokenizer.getLineNumber(), tokenizer.getPosition(),
666-
bindVariableNode.getText(), word);
684+
valueNode.getText(), word);
667685
}
668686
} else if (node instanceof ParensNode) {
669687
ParensNode parensNode = (ParensNode) node;
670-
parensNode.setAttachedWithBindVariable(true);
671-
bindVariableNode.setParensNode(parensNode);
688+
parensNode.setAttachedWithValue(true);
689+
valueNode.setParensNode(parensNode);
672690
} else {
673691
throw new JdbcException(Message.DOMA2110, sql,
674692
tokenizer.getLineNumber(), tokenizer.getPosition(),
675-
bindVariableNode.getText());
693+
valueNode.getText());
676694
}
677695
} else if (isAfterExpandNode()) {
678696
ExpandNode expandNode = pop();
@@ -713,7 +731,7 @@ protected SqlLocation getLocation() {
713731
}
714732

715733
protected void validate() {
716-
if (isAfterBindVariableNode()) {
734+
if (isAfterValueNode()) {
717735
BindVariableNode bindVariableNode = pop();
718736
throw new JdbcException(Message.DOMA2110, sql,
719737
tokenizer.getLineNumber(), tokenizer.getPosition(),

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,17 @@ public String extract(String token) {
4747
}
4848
},
4949

50+
LITERAL_VARIABLE_BLOCK_COMMENT {
51+
52+
@Override
53+
public String extract(String token) {
54+
assertNotNull(token);
55+
assertTrue(token.length() >= 5);
56+
String s = token.substring(3, token.length() - 2);
57+
return StringUtil.trimWhitespace(s);
58+
}
59+
},
60+
5061
EMBEDDED_VARIABLE_BLOCK_COMMENT {
5162

5263
@Override

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import static org.seasar.doma.internal.jdbc.sql.SqlTokenType.IF_BLOCK_COMMENT;
3737
import static org.seasar.doma.internal.jdbc.sql.SqlTokenType.INTERSECT_WORD;
3838
import static org.seasar.doma.internal.jdbc.sql.SqlTokenType.LINE_COMMENT;
39+
import static org.seasar.doma.internal.jdbc.sql.SqlTokenType.LITERAL_VARIABLE_BLOCK_COMMENT;
3940
import static org.seasar.doma.internal.jdbc.sql.SqlTokenType.MINUS_WORD;
4041
import static org.seasar.doma.internal.jdbc.sql.SqlTokenType.OPENED_PARENS;
4142
import static org.seasar.doma.internal.jdbc.sql.SqlTokenType.OPTION_WORD;
@@ -360,6 +361,8 @@ protected void peekTwoChars(char c, char c2) {
360361
char c3 = buf.get();
361362
if (ExpressionUtil.isExpressionIdentifierStart(c3)) {
362363
type = BIND_VARIABLE_BLOCK_COMMENT;
364+
} else if (c3 == '^') {
365+
type = LITERAL_VARIABLE_BLOCK_COMMENT;
363366
} else if (c3 == '#') {
364367
type = EMBEDDED_VARIABLE_BLOCK_COMMENT;
365368
} else if (c3 == '%') {

0 commit comments

Comments
 (0)