Skip to content

Commit e7f7622

Browse files
committed
Stop rewriting item/index variables inside foreach
Although it is not the goal, this could improve performance when there are many foreach iterations.
1 parent 584990a commit e7f7622

File tree

3 files changed

+12
-79
lines changed

3 files changed

+12
-79
lines changed

src/main/java/org/apache/ibatis/scripting/xmltags/DynamicContext.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ public class DynamicContext {
4545

4646
protected final ContextMap bindings;
4747
private final StringJoiner sqlBuilder = new StringJoiner(" ");
48-
private int uniqueNumber = 0;
4948

5049
private final Configuration configuration;
5150
private final Object parameterObject;
@@ -91,10 +90,6 @@ public String getSql() {
9190
return sqlBuilder.toString().trim();
9291
}
9392

94-
public int getUniqueNumber() {
95-
return uniqueNumber++;
96-
}
97-
9893
public List<ParameterMapping> getParameterMappings() {
9994
return tokenHandler == null ? new ArrayList<>() : tokenHandler.getParameterMappings();
10095
}

src/main/java/org/apache/ibatis/scripting/xmltags/ForEachSqlNode.java

Lines changed: 12 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,12 @@
2020
import java.util.Optional;
2121

2222
import org.apache.ibatis.mapping.ParameterMapping;
23-
import org.apache.ibatis.parsing.GenericTokenParser;
2423
import org.apache.ibatis.session.Configuration;
2524

2625
/**
2726
* @author Clinton Begin
2827
*/
2928
public class ForEachSqlNode implements SqlNode {
30-
public static final String ITEM_PREFIX = "__frch_";
3129

3230
private final ExpressionEvaluator evaluator;
3331
private final String collectionExpression;
@@ -44,14 +42,16 @@ public class ForEachSqlNode implements SqlNode {
4442
* @deprecated Since 3.5.9, use the {@link #ForEachSqlNode(Configuration, SqlNode, String, Boolean, String, String, String, String, String)}.
4543
*/
4644
@Deprecated
47-
public ForEachSqlNode(Configuration configuration, SqlNode contents, String collectionExpression, String index, String item, String open, String close, String separator) {
45+
public ForEachSqlNode(Configuration configuration, SqlNode contents, String collectionExpression, String index,
46+
String item, String open, String close, String separator) {
4847
this(configuration, contents, collectionExpression, null, index, item, open, close, separator);
4948
}
5049

5150
/**
5251
* @since 3.5.9
5352
*/
54-
public ForEachSqlNode(Configuration configuration, SqlNode contents, String collectionExpression, Boolean nullable, String index, String item, String open, String close, String separator) {
53+
public ForEachSqlNode(Configuration configuration, SqlNode contents, String collectionExpression, Boolean nullable,
54+
String index, String item, String open, String close, String separator) {
5555
this.evaluator = new ExpressionEvaluator();
5656
this.collectionExpression = collectionExpression;
5757
this.nullable = nullable;
@@ -68,7 +68,7 @@ public ForEachSqlNode(Configuration configuration, SqlNode contents, String coll
6868
public boolean apply(DynamicContext context) {
6969
Map<String, Object> bindings = context.getBindings();
7070
final Iterable<?> iterable = evaluator.evaluateIterable(collectionExpression, bindings,
71-
Optional.ofNullable(nullable).orElseGet(configuration::isNullableOnForEach));
71+
Optional.ofNullable(nullable).orElseGet(configuration::isNullableOnForEach));
7272
if (iterable == null || !iterable.iterator().hasNext()) {
7373
return true;
7474
}
@@ -82,18 +82,17 @@ public boolean apply(DynamicContext context) {
8282
} else {
8383
scopedContext = new PrefixedContext(context, separator);
8484
}
85-
int uniqueNumber = scopedContext.getUniqueNumber();
8685
// Issue #709
8786
if (o instanceof Map.Entry) {
8887
@SuppressWarnings("unchecked")
8988
Map.Entry<Object, Object> mapEntry = (Map.Entry<Object, Object>) o;
90-
applyIndex(scopedContext, mapEntry.getKey(), uniqueNumber);
91-
applyItem(scopedContext, mapEntry.getValue(), uniqueNumber);
89+
applyIndex(scopedContext, mapEntry.getKey());
90+
applyItem(scopedContext, mapEntry.getValue());
9291
} else {
93-
applyIndex(scopedContext, i, uniqueNumber);
94-
applyItem(scopedContext, o, uniqueNumber);
92+
applyIndex(scopedContext, i);
93+
applyItem(scopedContext, o);
9594
}
96-
contents.apply(new FilteredDynamicContext(configuration, scopedContext, index, item, uniqueNumber));
95+
contents.apply(scopedContext);
9796
if (first) {
9897
first = !((PrefixedContext) scopedContext).isPrefixApplied();
9998
}
@@ -103,17 +102,15 @@ public boolean apply(DynamicContext context) {
103102
return true;
104103
}
105104

106-
private void applyIndex(DynamicContext context, Object o, int i) {
105+
private void applyIndex(DynamicContext context, Object o) {
107106
if (index != null) {
108107
context.bind(index, o);
109-
context.bind(itemizeItem(index, i), o);
110108
}
111109
}
112110

113-
private void applyItem(DynamicContext context, Object o, int i) {
111+
private void applyItem(DynamicContext context, Object o) {
114112
if (item != null) {
115113
context.bind(item, o);
116-
context.bind(itemizeItem(item, i), o);
117114
}
118115
}
119116

@@ -129,55 +126,6 @@ private void applyClose(DynamicContext context) {
129126
}
130127
}
131128

132-
private static String itemizeItem(String item, int i) {
133-
return ITEM_PREFIX + item + "_" + i;
134-
}
135-
136-
private static class FilteredDynamicContext extends DynamicContext {
137-
private final DynamicContext delegate;
138-
private final int index;
139-
private final String itemIndex;
140-
private final String item;
141-
142-
public FilteredDynamicContext(Configuration configuration,DynamicContext delegate, String itemIndex, String item, int i) {
143-
super(configuration, delegate.getParameterObject(), delegate.getParameterType(), delegate.isParamExists());
144-
this.delegate = delegate;
145-
this.index = i;
146-
this.itemIndex = itemIndex;
147-
this.item = item;
148-
this.bindings.putAll(delegate.getBindings());
149-
}
150-
151-
@Override
152-
public String getSql() {
153-
return delegate.getSql();
154-
}
155-
156-
@Override
157-
public void appendSql(String sql) {
158-
GenericTokenParser parser = new GenericTokenParser("#{", "}", content -> {
159-
String newContent = content.replaceFirst("^\\s*" + item + "(?![^.,:\\s])", itemizeItem(item, index));
160-
if (itemIndex != null && newContent.equals(content)) {
161-
newContent = content.replaceFirst("^\\s*" + itemIndex + "(?![^.,:\\s])", itemizeItem(itemIndex, index));
162-
}
163-
return "#{" + newContent + "}";
164-
});
165-
166-
delegate.appendSql(parser.parse(sql));
167-
}
168-
169-
@Override
170-
public int getUniqueNumber() {
171-
return delegate.getUniqueNumber();
172-
}
173-
174-
@Override
175-
public List<ParameterMapping> getParameterMappings() {
176-
return delegate.getParameterMappings();
177-
}
178-
}
179-
180-
181129
private class PrefixedContext extends DynamicContext {
182130
private final DynamicContext delegate;
183131
private final String prefix;
@@ -209,11 +157,6 @@ public String getSql() {
209157
return delegate.getSql();
210158
}
211159

212-
@Override
213-
public int getUniqueNumber() {
214-
return delegate.getUniqueNumber();
215-
}
216-
217160
@Override
218161
public List<ParameterMapping> getParameterMappings() {
219162
return delegate.getParameterMappings();

src/main/java/org/apache/ibatis/scripting/xmltags/TrimSqlNode.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,6 @@ public void applyAll() {
9494
delegate.appendSql(sqlBuffer.toString());
9595
}
9696

97-
@Override
98-
public int getUniqueNumber() {
99-
return delegate.getUniqueNumber();
100-
}
101-
10297
@Override
10398
public void appendSql(String sql) {
10499
sqlBuffer.append(sql);

0 commit comments

Comments
 (0)