未验证 提交 7aeded68 编写于 作者: J Juan Pan(Trista) 提交者: GitHub

handle unclosed range query for DatetimeShardingAlgorithm (#5994)

* handle unclosed range query for DatetimeShardingAlgorithm

* check style
上级 c1a7ae28
......@@ -18,6 +18,7 @@
package org.apache.shardingsphere.sharding.strategy.algorithm.sharding;
import com.google.common.base.Preconditions;
import com.google.common.collect.Range;
import lombok.Getter;
import lombok.Setter;
import org.apache.shardingsphere.sharding.api.sharding.ShardingAutoTableAlgorithm;
......@@ -25,6 +26,7 @@ import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingV
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import java.text.DecimalFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
......@@ -44,9 +46,9 @@ public final class DatetimeShardingAlgorithm implements StandardShardingAlgorith
private static final String PARTITION_SECONDS = "partition.seconds";
private static final String EPOCH = "epoch";
private static final String DATETIME_LOWER = "datetime.lower";
private static final String TOP_DATETIME = "top.datetime";
private static final String DATETIME_UPPER = "datetime.upper";
private static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
......@@ -56,12 +58,16 @@ public final class DatetimeShardingAlgorithm implements StandardShardingAlgorith
@Setter
private Properties properties = new Properties();
@Getter
private int autoTablesAmount;
@Override
public void init() {
Preconditions.checkNotNull(properties.get(PARTITION_SECONDS), "Sharding partition volume cannot be null.");
Preconditions.checkState(null != properties.get(EPOCH) && checkDatetimePattern(properties.get(EPOCH).toString()), "%s pattern is required.", DATETIME_PATTERN);
Preconditions.checkState(null != properties.get(TOP_DATETIME) && checkDatetimePattern(properties.get(TOP_DATETIME).toString()),
Preconditions.checkState(null != properties.get(DATETIME_LOWER) && checkDatetimePattern(properties.get(DATETIME_LOWER).toString()), "%s pattern is required.", DATETIME_PATTERN);
Preconditions.checkState(null != properties.get(DATETIME_UPPER) && checkDatetimePattern(properties.get(DATETIME_UPPER).toString()),
"%s pattern is required.", DATETIME_PATTERN);
autoTablesAmount = (int) (Math.ceil(parseDate(properties.get(DATETIME_UPPER).toString()) / getPartitionValue()) + 2);
}
@Override
......@@ -77,8 +83,8 @@ public final class DatetimeShardingAlgorithm implements StandardShardingAlgorith
@Override
public Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Comparable<?>> shardingValue) {
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
int firstPartition = doSharding(parseDate(shardingValue.getValueRange().lowerEndpoint()));
int lastPartition = doSharding(parseDate(shardingValue.getValueRange().upperEndpoint()));
int firstPartition = getFirstPartition(shardingValue.getValueRange());
int lastPartition = getLastPartition(shardingValue.getValueRange());
for (int i = firstPartition; i <= lastPartition; i++) {
for (String each : availableTargetNames) {
if (each.endsWith(i + "")) {
......@@ -91,12 +97,21 @@ public final class DatetimeShardingAlgorithm implements StandardShardingAlgorith
}
return result;
}
private int doSharding(final long shardingValue) {
int position = (int) (Math.floor(shardingValue / getPartitionValue()));
return Math.max(0, position);
DecimalFormat df = new DecimalFormat("0.00");
String position = df.format((float) shardingValue / getPartitionValue());
return Math.max(0, (int) Math.ceil(Float.parseFloat(position)));
}
private int getFirstPartition(final Range<Comparable<?>> valueRange) {
return valueRange.hasLowerBound() ? doSharding(parseDate(valueRange.lowerEndpoint())) : 0;
}
private int getLastPartition(final Range<Comparable<?>> valueRange) {
return valueRange.hasUpperBound() ? doSharding(parseDate(valueRange.upperEndpoint())) : autoTablesAmount - 1;
}
private boolean checkDatetimePattern(final String datetime) {
try {
DATE_FORMAT.parse(datetime);
......@@ -108,7 +123,7 @@ public final class DatetimeShardingAlgorithm implements StandardShardingAlgorith
private long parseDate(final Comparable<?> shardingValue) {
LocalDateTime dateValue = LocalDateTime.parse(shardingValue.toString(), DATE_FORMAT);
LocalDateTime sinceDate = LocalDateTime.parse(properties.get(EPOCH).toString(), DATE_FORMAT);
LocalDateTime sinceDate = LocalDateTime.parse(properties.get(DATETIME_LOWER).toString(), DATE_FORMAT);
return Duration.between(sinceDate, dateValue).toMillis() / 1000;
}
......@@ -120,9 +135,4 @@ public final class DatetimeShardingAlgorithm implements StandardShardingAlgorith
public String getType() {
return "DATETIME";
}
@Override
public int getAutoTablesAmount() {
return (int) (Math.ceil(parseDate(properties.get(TOP_DATETIME).toString()) / getPartitionValue()));
}
}
......@@ -44,8 +44,8 @@ public final class DatetimeShardingAlgorithmTest {
public void setup() {
DatetimeShardingAlgorithm shardingAlgorithm = new DatetimeShardingAlgorithm();
shardingAlgorithm.getProperties().setProperty("partition.seconds", "4");
shardingAlgorithm.getProperties().setProperty("epoch", "2020-01-01 00:00:00");
shardingAlgorithm.getProperties().setProperty("top.datetime", "2022-01-01 00:00:00");
shardingAlgorithm.getProperties().setProperty("datetime.lower", "2020-01-01 00:00:00");
shardingAlgorithm.getProperties().setProperty("datetime.upper", "2020-01-01 00:00:16");
shardingAlgorithm.init();
StandardShardingStrategyConfiguration shardingStrategyConfig = new StandardShardingStrategyConfiguration("create_time", shardingAlgorithm);
shardingStrategy = new StandardShardingStrategy(shardingStrategyConfig);
......@@ -58,36 +58,73 @@ public final class DatetimeShardingAlgorithmTest {
Lists.newArrayList("2020-01-01 00:00:01", "2020-01-01 00:00:02")));
Collection<String> actual = shardingStrategy.doSharding(availableTargetNames, shardingValues, new ConfigurationProperties(new Properties()));
assertThat(actual.size(), is(1));
assertTrue(actual.contains("t_order_1"));
}
@Test
public void assertPreciseDoShardingWithFirstPartition() {
List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3");
List<RouteValue> shardingValues = Lists.newArrayList(new ListRouteValue<>("create_time", "t_order",
Lists.newArrayList("2019-12-01 00:00:01", "2020-01-01 00:00:02")));
Collection<String> actual = shardingStrategy.doSharding(availableTargetNames, shardingValues, new ConfigurationProperties(new Properties()));
assertThat(actual.size(), is(2));
assertTrue(actual.contains("t_order_0"));
assertTrue(actual.contains("t_order_1"));
}
@Test
public void assertDoShardingWithAllRange() {
List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3");
Range<String> rangeValue = Range.closed("2020-01-01 00:00:00", "2020-01-01 00:00:15");
public void assertRangeDoShardingWithAllRange() {
List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3", "t_order_4");
Range<String> rangeValue = Range.closed("2019-01-01 00:00:00", "2020-01-01 00:00:15");
List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("create_time", "t_order", rangeValue));
Collection<String> actual = shardingStrategy.doSharding(availableTargetNames, shardingValues, new ConfigurationProperties(new Properties()));
assertThat(actual.size(), is(4));
assertThat(actual.size(), is(5));
}
@Test
public void assertDoShardingWithPartRange() {
public void assertRangeDoShardingWithPartRange() {
List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3");
Range<String> rangeValue = Range.closed("2020-01-01 00:00:04", "2020-01-01 00:00:10");
List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("create_time", "t_order", rangeValue));
Collection<String> actual = shardingStrategy.doSharding(availableTargetNames, shardingValues, new ConfigurationProperties(new Properties()));
assertThat(actual.size(), is(2));
assertThat(actual.size(), is(3));
assertTrue(actual.contains("t_order_1"));
assertTrue(actual.contains("t_order_2"));
assertTrue(actual.contains("t_order_3"));
}
@Test
public void assertPreciseDoShardingWithoutLowerBound() {
List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3");
Range<String> rangeValue = Range.lessThan("2020-01-01 00:00:11");
List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("create_time", "t_order", rangeValue));
Collection<String> actual = shardingStrategy.doSharding(availableTargetNames, shardingValues, new ConfigurationProperties(new Properties()));
assertThat(actual.size(), is(4));
assertTrue(actual.contains("t_order_0"));
assertTrue(actual.contains("t_order_1"));
assertTrue(actual.contains("t_order_2"));
assertTrue(actual.contains("t_order_3"));
}
@Test
public void assertPreciseDoShardingWithoutUpperBound() {
List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3", "t_order_4", "t_order_5");
Range<String> rangeValue = Range.greaterThan("2020-01-01 00:00:09");
List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("create_time", "t_order", rangeValue));
Collection<String> actual = shardingStrategy.doSharding(availableTargetNames, shardingValues, new ConfigurationProperties(new Properties()));
assertThat(actual.size(), is(3));
assertTrue(actual.contains("t_order_3"));
assertTrue(actual.contains("t_order_4"));
assertTrue(actual.contains("t_order_5"));
}
@Test
public void assertGetAutoTablesAmount() {
DatetimeShardingAlgorithm shardingAlgorithm = new DatetimeShardingAlgorithm();
shardingAlgorithm.getProperties().setProperty("partition.seconds", "86400");
shardingAlgorithm.getProperties().setProperty("epoch", "2020-01-01 00:00:00");
shardingAlgorithm.getProperties().setProperty("top.datetime", "2021-01-01 00:00:00");
shardingAlgorithm.getProperties().setProperty("datetime.lower", "2020-01-01 00:00:00");
shardingAlgorithm.getProperties().setProperty("datetime.upper", "2021-01-01 00:00:00");
shardingAlgorithm.init();
assertThat(shardingAlgorithm.getAutoTablesAmount(), is(366));
assertThat(shardingAlgorithm.getAutoTablesAmount(), is(368));
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册