This is an automated email from the ASF dual-hosted git repository.
terrymanu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 7ea8b8ce0fb Preserve numeric identity when merging heterogeneous
sharding conditions (#39902)
7ea8b8ce0fb is described below
commit 7ea8b8ce0fbe42472b185a4f45abf84ff278547f
Author: Gimin Kim <[email protected]>
AuthorDate: Tue Sep 22 00:38:47 2026 +0900
Preserve numeric identity when merging heterogeneous sharding conditions
(#39902)
* Preserve numeric identity when merging heterogeneous sharding conditions
* Preserve numeric identity when merging heterogeneous sharding conditions
* Avoid streams in high-frequency condition merge
---------
Co-authored-by: Gimin Kim <[email protected]>
---
.../engine/WhereClauseShardingConditionEngine.java | 61 +++++++++++++++++++++
.../util/ShardingValueTypeConvertUtils.java | 3 +
.../WhereClauseShardingConditionEngineTest.java | 64 ++++++++++++++++++++++
.../util/ShardingValueTypeConvertUtilsTest.java | 5 +-
.../E2EStandardShardingAlgorithmFixture.java | 15 ++---
.../test/e2e/sql/it/sql/dql/GeneralDQLE2EIT.java | 45 ++++++++++++---
.../test/resources/cases/dql/e2e-dql-select.xml | 7 +++
7 files changed, 183 insertions(+), 17 deletions(-)
diff --git
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
index 25b11d24135..8c439624827 100644
---
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
+++
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngine.java
@@ -20,6 +20,7 @@ package
org.apache.shardingsphere.sharding.route.engine.condition.engine;
import com.cedarsoftware.util.CaseInsensitiveSet;
import com.google.common.collect.Range;
import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation;
import
org.apache.shardingsphere.infra.binder.context.available.WhereContextAvailable;
import
org.apache.shardingsphere.infra.binder.context.extractor.SQLStatementContextExtractor;
import
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
@@ -49,11 +50,13 @@ import
org.apache.shardingsphere.sql.parser.statement.core.util.SafeNumberOperat
import
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
import org.apache.shardingsphere.timeservice.core.rule.TimestampServiceRule;
+import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -179,10 +182,28 @@ public final class WhereClauseShardingConditionEngine {
: new ListShardingConditionValue<>(column.getName(),
column.getTableName(), listValue, new ArrayList<>(parameterMarkerIndexes));
}
+ @HighFrequencyInvocation
private Collection<Comparable<?>> mergeListShardingValues(final HashColumn
column, final Collection<Comparable<?>> value1, final Collection<Comparable<?>>
value2) {
if (null == value2) {
return value1;
}
+ if (areAllNumbers(value1) && areAllNumbers(value2)) {
+ if (isSameType(value1, value2)) {
+ value1.retainAll(value2);
+ return value1;
+ }
+ Set<Comparable<?>> normalizedValue2 = new HashSet<>(value2.size(),
1F);
+ for (Comparable<?> each : value2) {
+ normalizedValue2.add(normalizeNumber(each));
+ }
+ Iterator<Comparable<?>> iterator = value1.iterator();
+ while (iterator.hasNext()) {
+ if
(!normalizedValue2.contains(normalizeNumber(iterator.next()))) {
+ iterator.remove();
+ }
+ }
+ return value1;
+ }
Collection<Comparable<?>> convertedValue2 = value2;
if (!value1.isEmpty() && !value2.isEmpty() && isDifferentType(value1,
value2)) {
convertedValue2 =
ShardingValueTypeConvertUtils.convertCollectionType(value2,
value1.iterator().next().getClass());
@@ -197,6 +218,46 @@ public final class WhereClauseShardingConditionEngine {
return caseInSensitiveValue1;
}
+ private boolean areAllNumbers(final Collection<Comparable<?>> values) {
+ for (Comparable<?> each : values) {
+ if (!(each instanceof Number)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isSameType(final Collection<Comparable<?>> value1, final
Collection<Comparable<?>> value2) {
+ if (value1.isEmpty() || value2.isEmpty()) {
+ return true;
+ }
+ Class<?> valueType = value1.iterator().next().getClass();
+ for (Comparable<?> each : value1) {
+ if (valueType != each.getClass()) {
+ return false;
+ }
+ }
+ for (Comparable<?> each : value2) {
+ if (valueType != each.getClass()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private Comparable<?> normalizeNumber(final Comparable<?> value) {
+ Number number = (Number) value;
+ if (!isFiniteNumber(number)) {
+ return number.doubleValue();
+ }
+ BigDecimal result =
ShardingValueTypeConvertUtils.convertToTargetType(value, BigDecimal.class);
+ return result.stripTrailingZeros();
+ }
+
+ private boolean isFiniteNumber(final Number value) {
+ return (!(value instanceof Double) ||
Double.isFinite(value.doubleValue())) && (!(value instanceof Float) ||
Float.isFinite(value.floatValue()));
+ }
+
private boolean isDifferentType(final Collection<Comparable<?>> value1,
final Collection<Comparable<?>> value2) {
return value1.iterator().next().getClass() !=
value2.iterator().next().getClass();
}
diff --git
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/util/ShardingValueTypeConvertUtils.java
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/util/ShardingValueTypeConvertUtils.java
index 5d8d2cff64b..7347a0a30c4 100644
---
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/util/ShardingValueTypeConvertUtils.java
+++
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/util/ShardingValueTypeConvertUtils.java
@@ -174,6 +174,9 @@ public final class ShardingValueTypeConvertUtils {
if (value instanceof BigInteger) {
return new BigDecimal((BigInteger) value);
}
+ if (value instanceof Byte || value instanceof Short || value
instanceof Integer || value instanceof Long) {
+ return BigDecimal.valueOf(((Number) value).longValue());
+ }
if (value instanceof Number) {
return BigDecimal.valueOf(((Number) value).doubleValue());
}
diff --git
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngineTest.java
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngineTest.java
index 816b5ddbf9e..06d4ea43a11 100644
---
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngineTest.java
+++
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/WhereClauseShardingConditionEngineTest.java
@@ -22,6 +22,7 @@ import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
+import
org.apache.shardingsphere.sharding.route.engine.condition.AlwaysFalseShardingCondition;
import
org.apache.shardingsphere.sharding.route.engine.condition.ShardingCondition;
import
org.apache.shardingsphere.sharding.route.engine.condition.value.ListShardingConditionValue;
import
org.apache.shardingsphere.sharding.route.engine.condition.value.RangeShardingConditionValue;
@@ -34,18 +35,26 @@ import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.InEx
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ListExpression;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.UnaryOperationExpression;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
import org.apache.shardingsphere.timeservice.core.rule.TimestampServiceRule;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
+import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@@ -117,6 +126,61 @@ class WhereClauseShardingConditionEngineTest {
assertThat(actual.get(0).getValues().get(0),
isA(ListShardingConditionValue.class));
}
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("heterogeneousNumberArguments")
+ void assertCreateShardingConditionsForHeterogeneousNumbers(final String
name, final Comparable<?> firstValue, final Comparable<?> secondValue) {
+ ColumnSegment column = new ColumnSegment(0, 0, new
IdentifierValue("foo_sharding_col"));
+ BinaryOperationExpression firstPredicate = new
BinaryOperationExpression(0, 0, column, new ParameterMarkerExpressionSegment(0,
0, 0), "=", null);
+ BinaryOperationExpression secondPredicate = new
BinaryOperationExpression(0, 0, column, new ParameterMarkerExpressionSegment(0,
0, 1), "=", null);
+ when(whereSegment.getExpr()).thenReturn(new
BinaryOperationExpression(0, 0, firstPredicate, secondPredicate, "AND", null));
+ when(rule.findShardingColumn("foo_sharding_col",
"")).thenReturn(Optional.of("foo_sharding_col"));
+ List<Object> params = Arrays.asList(firstValue, secondValue);
+ List<ShardingCondition> actual =
shardingConditionEngine.createShardingConditions(sqlStatementContext, params);
+ assertThat(actual.size(), is(1));
+ assertThat(actual.get(0).getValues().size(), is(1));
+ assertThat(actual.get(0).getValues().get(0),
isA(ListShardingConditionValue.class));
+ ListShardingConditionValue<?> actualValue =
(ListShardingConditionValue<?>) actual.get(0).getValues().get(0);
+ assertThat(actualValue.getValues().size(), is(1));
+ Number actualNumber = (Number)
actualValue.getValues().iterator().next();
+ assertThat(new BigDecimal(actualNumber.toString()).compareTo(new
BigDecimal("9007199254740993")), is(0));
+ }
+
+ private static Stream<Arguments> heterogeneousNumberArguments() {
+ return Stream.of(
+ Arguments.of("Long then BigDecimal", 9007199254740993L, new
BigDecimal("9007199254740993")),
+ Arguments.of("BigDecimal then Long", new
BigDecimal("9007199254740993"), 9007199254740993L),
+ Arguments.of("Long then scaled BigDecimal", 9007199254740993L,
new BigDecimal("9007199254740993.0")),
+ Arguments.of("Scaled BigDecimal then Long", new
BigDecimal("9007199254740993.0"), 9007199254740993L));
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("finiteAndInfiniteNumberArguments")
+ void
assertCreateAlwaysFalseShardingConditionForFiniteAndInfiniteNumbers(final
String name, final Comparable<?> firstValue, final Comparable<?> secondValue) {
+ ColumnSegment column = new ColumnSegment(0, 0, new
IdentifierValue("foo_sharding_col"));
+ BinaryOperationExpression firstPredicate = new
BinaryOperationExpression(0, 0, column, new ParameterMarkerExpressionSegment(0,
0, 0), "=", null);
+ BinaryOperationExpression secondPredicate = new
BinaryOperationExpression(0, 0, column, new ParameterMarkerExpressionSegment(0,
0, 1), "=", null);
+ when(whereSegment.getExpr()).thenReturn(new
BinaryOperationExpression(0, 0, firstPredicate, secondPredicate, "AND", null));
+ when(rule.findShardingColumn("foo_sharding_col",
"")).thenReturn(Optional.of("foo_sharding_col"));
+ List<Object> params = Arrays.asList(firstValue, secondValue);
+ List<ShardingCondition> actual =
shardingConditionEngine.createShardingConditions(sqlStatementContext, params);
+ assertThat(actual.size(), is(1));
+ assertThat(actual.get(0), isA(AlwaysFalseShardingCondition.class));
+ }
+
+ private static Stream<Arguments> finiteAndInfiniteNumberArguments() {
+ BigDecimal largeDecimal = new BigDecimal("1E10000");
+ BigInteger largeInteger = BigInteger.TEN.pow(10000);
+ return Stream.of(
+ Arguments.of("Positive BigDecimal then positive infinity",
largeDecimal, Double.POSITIVE_INFINITY),
+ Arguments.of("Positive infinity then positive BigDecimal",
Double.POSITIVE_INFINITY, largeDecimal),
+ Arguments.of("Negative BigDecimal then negative infinity",
largeDecimal.negate(), Double.NEGATIVE_INFINITY),
+ Arguments.of("Negative infinity then negative BigDecimal",
Double.NEGATIVE_INFINITY, largeDecimal.negate()),
+ Arguments.of("Positive BigInteger then positive infinity",
largeInteger, Double.POSITIVE_INFINITY),
+ Arguments.of("Positive infinity then positive BigInteger",
Double.POSITIVE_INFINITY, largeInteger),
+ Arguments.of("Negative BigInteger then negative infinity",
largeInteger.negate(), Double.NEGATIVE_INFINITY),
+ Arguments.of("Negative infinity then negative BigInteger",
Double.NEGATIVE_INFINITY, largeInteger.negate()));
+ }
+
@Test
void assertCreateEmptyShardingConditionsForBinaryOperatorRangeStatement() {
ColumnSegment left = new ColumnSegment(0, 0, new
IdentifierValue("foo_sharding_col"));
diff --git
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/util/ShardingValueTypeConvertUtilsTest.java
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/util/ShardingValueTypeConvertUtilsTest.java
index a282a5652d7..a20d2e3c350 100644
---
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/util/ShardingValueTypeConvertUtilsTest.java
+++
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/util/ShardingValueTypeConvertUtilsTest.java
@@ -92,8 +92,9 @@ class ShardingValueTypeConvertUtilsTest {
Arguments.of("Float <- Integer", 234, Float.class, 234.0F),
Arguments.of("Float <- Double", 56.78D, Float.class, 56.78F),
Arguments.of("Float <- String", "78.9", Float.class, 78.9F),
- Arguments.of("BigDecimal <- Integer", 999, BigDecimal.class,
BigDecimal.valueOf(999D)),
- Arguments.of("BigDecimal <- Long", 888L, BigDecimal.class,
BigDecimal.valueOf(888D)),
+ Arguments.of("BigDecimal <- Integer", 999, BigDecimal.class,
BigDecimal.valueOf(999L)),
+ Arguments.of("BigDecimal <- Long", 888L, BigDecimal.class,
BigDecimal.valueOf(888L)),
+ Arguments.of("BigDecimal <- large Long", 9007199254740993L,
BigDecimal.class, new BigDecimal("9007199254740993")),
Arguments.of("BigDecimal <- Double", 123.456D,
BigDecimal.class, BigDecimal.valueOf(123.456D)),
Arguments.of("BigDecimal <- BigInteger",
BigInteger.valueOf(12345), BigDecimal.class, new BigDecimal("12345")),
Arguments.of("BigDecimal <- String", "999.888",
BigDecimal.class, new BigDecimal("999.888")),
diff --git
a/test/e2e/fixture/src/test/java/org/apache/shardingsphere/test/e2e/fixture/E2EStandardShardingAlgorithmFixture.java
b/test/e2e/fixture/src/test/java/org/apache/shardingsphere/test/e2e/fixture/E2EStandardShardingAlgorithmFixture.java
index 800eaac9c60..db707d39c36 100644
---
a/test/e2e/fixture/src/test/java/org/apache/shardingsphere/test/e2e/fixture/E2EStandardShardingAlgorithmFixture.java
+++
b/test/e2e/fixture/src/test/java/org/apache/shardingsphere/test/e2e/fixture/E2EStandardShardingAlgorithmFixture.java
@@ -25,12 +25,13 @@ import java.math.BigInteger;
import java.util.Collection;
import java.util.LinkedHashSet;
-public final class E2EStandardShardingAlgorithmFixture implements
StandardShardingAlgorithm<Integer> {
+public final class E2EStandardShardingAlgorithmFixture implements
StandardShardingAlgorithm<Comparable<?>> {
@Override
- public String doSharding(final Collection<String> availableTargetNames,
final PreciseShardingValue<Integer> shardingValue) {
+ public String doSharding(final Collection<String> availableTargetNames,
final PreciseShardingValue<Comparable<?>> shardingValue) {
+ long value = ((Number) shardingValue.getValue()).longValue();
for (String each : availableTargetNames) {
- if (each.endsWith(String.valueOf(shardingValue.getValue() % 10))) {
+ if (each.endsWith(String.valueOf(value % 10L))) {
return each;
}
}
@@ -38,12 +39,12 @@ public final class E2EStandardShardingAlgorithmFixture
implements StandardShardi
}
@Override
- public Collection<String> doSharding(final Collection<String>
availableTargetNames, final RangeShardingValue<Integer> shardingValue) {
+ public Collection<String> doSharding(final Collection<String>
availableTargetNames, final RangeShardingValue<Comparable<?>> shardingValue) {
Collection<String> result = new
LinkedHashSet<>(availableTargetNames.size(), 1F);
- int minValue = shardingValue.getValueRange().hasLowerBound() ?
shardingValue.getValueRange().lowerEndpoint() : Integer.MIN_VALUE;
- int maxValue = shardingValue.getValueRange().hasUpperBound() ?
shardingValue.getValueRange().upperEndpoint() : Integer.MAX_VALUE;
+ long minValue = shardingValue.getValueRange().hasLowerBound() ?
((Number) shardingValue.getValueRange().lowerEndpoint()).longValue() :
Integer.MIN_VALUE;
+ long maxValue = shardingValue.getValueRange().hasUpperBound() ?
((Number) shardingValue.getValueRange().upperEndpoint()).longValue() :
Integer.MAX_VALUE;
long range =
BigInteger.valueOf(maxValue).subtract(BigInteger.valueOf(minValue)).longValue();
- int begin = Math.abs(minValue) % 10;
+ int begin = (int) (Math.abs(minValue) % 10L);
if (range > 9L) {
return availableTargetNames;
}
diff --git
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/sql/it/sql/dql/GeneralDQLE2EIT.java
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/sql/it/sql/dql/GeneralDQLE2EIT.java
index 994529e38d5..b0e197a1b9f 100644
---
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/sql/it/sql/dql/GeneralDQLE2EIT.java
+++
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/sql/it/sql/dql/GeneralDQLE2EIT.java
@@ -17,7 +17,9 @@
package org.apache.shardingsphere.test.e2e.sql.it.sql.dql;
+import com.google.common.base.Splitter;
import org.apache.shardingsphere.test.e2e.env.runtime.E2ETestEnvironment;
+import
org.apache.shardingsphere.test.e2e.sql.cases.casse.assertion.SQLE2ETestCaseAssertionSQL;
import org.apache.shardingsphere.test.e2e.sql.cases.value.SQLValue;
import
org.apache.shardingsphere.test.e2e.sql.framework.SQLE2EITArgumentsProvider;
import org.apache.shardingsphere.test.e2e.sql.framework.SQLE2EITSettings;
@@ -50,10 +52,7 @@ class GeneralDQLE2EIT extends BaseDQLE2EIT {
@ArgumentsSource(SQLE2EITArgumentsProvider.class)
void assertExecuteQuery(final AssertionTestParameter testParam) throws
SQLException, IOException, JAXBException {
SQLE2EITContext context = new SQLE2EITContext(testParam);
- executeDQL(context, () -> {
- init(testParam, context);
- assertExecuteQuery(testParam, context);
- });
+ executeDQLWithLifecycleSQL(testParam, context, () ->
assertExecuteQuery(testParam, context));
}
private void assertExecuteQuery(final AssertionTestParameter testParam,
final SQLE2EITContext context) throws SQLException {
@@ -150,10 +149,7 @@ class GeneralDQLE2EIT extends BaseDQLE2EIT {
@ArgumentsSource(SQLE2EITArgumentsProvider.class)
void assertExecute(final AssertionTestParameter testParam) throws
SQLException, JAXBException, IOException {
SQLE2EITContext context = new SQLE2EITContext(testParam);
- executeDQL(context, () -> {
- init(testParam, context);
- assertExecute(testParam, context);
- });
+ executeDQLWithLifecycleSQL(testParam, context, () ->
assertExecute(testParam, context));
}
private void assertExecute(final AssertionTestParameter testParam, final
SQLE2EITContext context) throws SQLException {
@@ -164,6 +160,39 @@ class GeneralDQLE2EIT extends BaseDQLE2EIT {
}
}
+ private void executeDQLWithLifecycleSQL(final AssertionTestParameter
testParam, final SQLE2EITContext context,
+ final DQLExecutionCallback
callback) throws SQLException, IOException, JAXBException {
+ executeDQL(context, () -> {
+ init(testParam, context);
+ try {
+ executeLifecycleSQL(context.getAssertion().getInitialSQL());
+ callback.execute();
+ } finally {
+ executeLifecycleSQL(context.getAssertion().getDestroySQL());
+ }
+ });
+ }
+
+ private void executeLifecycleSQL(final SQLE2ETestCaseAssertionSQL
lifecycleSQL) throws SQLException {
+ if (null == lifecycleSQL || null == lifecycleSQL.getSql()) {
+ return;
+ }
+ try (
+ Connection actualConnection =
getEnvironmentEngine().getTargetDataSource().getConnection();
+ Connection expectedConnection =
getExpectedDataSource().getConnection()) {
+ executeLifecycleSQL(lifecycleSQL.getSql(), actualConnection);
+ executeLifecycleSQL(lifecycleSQL.getSql(), expectedConnection);
+ }
+ }
+
+ private void executeLifecycleSQL(final String sql, final Connection
connection) throws SQLException {
+ for (String each :
Splitter.on(";").trimResults().omitEmptyStrings().splitToList(sql)) {
+ try (Statement statement = connection.createStatement()) {
+ statement.executeUpdate(each);
+ }
+ }
+ }
+
private void assertExecuteWithXmlExpected(final AssertionTestParameter
testParam, final SQLE2EITContext context) throws SQLException {
// TODO Fix jdbc adapter
if (isNeedSkipExecuteWithXmlExcepted(testParam)) {
diff --git a/test/e2e/sql/src/test/resources/cases/dql/e2e-dql-select.xml
b/test/e2e/sql/src/test/resources/cases/dql/e2e-dql-select.xml
index 9a0a441aead..ca6021682ba 100644
--- a/test/e2e/sql/src/test/resources/cases/dql/e2e-dql-select.xml
+++ b/test/e2e/sql/src/test/resources/cases/dql/e2e-dql-select.xml
@@ -44,6 +44,13 @@
<assertion parameters="1000:int, 1001:int"
expected-data-source-name="read_dataset" />
</test-case>
+ <test-case sql="SELECT * FROM t_order WHERE order_id = ? AND order_id = ?
FOR UPDATE" db-types="PostgreSQL" scenario-types="tbl" adapters="proxy">
+ <assertion parameters="9007199254740993:long,
9007199254740993.0:decimal">
+ <initial-sql sql="INSERT INTO t_order (order_id, user_id, status,
merchant_id, remark, creation_date) VALUES (9007199254740993, 21, 'init', 21,
'test', '2017-08-08')" />
+ <destroy-sql sql="DELETE FROM t_order WHERE order_id =
9007199254740993" />
+ </assertion>
+ </test-case>
+
<test-case sql="SELECT * /* this is 
 block comment */ FROM
/* this is another 
 block comment */ t_order where status='1'"
db-types="MySQL"
scenario-types="db,tbl,dbtbl_with_readwrite_splitting,readwrite_splitting">
<assertion expected-data-source-name="read_dataset" />
</test-case>