diff --git a/common/src/main/java/io/mycat/util/DateUtil.java b/common/src/main/java/io/mycat/util/DateUtil.java index 2004649e6f2b3bb9528f3211530686ac7e132381..835654142c782f8c47cd62c01a9361f6a19613d0 100644 --- a/common/src/main/java/io/mycat/util/DateUtil.java +++ b/common/src/main/java/io/mycat/util/DateUtil.java @@ -4,6 +4,7 @@ import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import java.text.ParseException; +import java.time.LocalDate; import java.util.Date; /** @@ -120,5 +121,15 @@ public class DateUtil { DateTime dt = new DateTime(date); return dt.getMillisOfSecond(); } - -} \ No newline at end of file + + /** + * 获取date对象毫秒数 + * + * @param date1 时间1 + * @param date2 时间2 + * @return 结果 + */ + public static boolean isSameYearMonth(LocalDate date1, LocalDate date2) { + return date1.getYear() == date2.getYear() && date1.getMonthValue() == date2.getMonthValue(); + } +} diff --git a/router/src/main/java/io/mycat/router/function/AutoFunction.java b/router/src/main/java/io/mycat/router/function/AutoFunction.java index 1cb46fa995d9c09d22ae9995ab3439082c9d0edb..d1dc1f2d2ed16a02598a210facdaf68de76f759a 100644 --- a/router/src/main/java/io/mycat/router/function/AutoFunction.java +++ b/router/src/main/java/io/mycat/router/function/AutoFunction.java @@ -23,6 +23,7 @@ import io.mycat.SimpleColumnInfo; import io.mycat.SimpleColumnInfo.Type; import io.mycat.router.CustomRuleFunction; import io.mycat.router.ShardingTableHandler; +import io.mycat.util.DateUtil; import org.jetbrains.annotations.NotNull; import java.text.MessageFormat; @@ -88,6 +89,7 @@ public abstract class AutoFunction extends CustomRuleFunction { case "YYYYDD": case "YYYYMM": case "YYYYWEEK": + case "YYYY": key = methodName; break; case "RANGE_HASH": { @@ -230,7 +232,9 @@ public abstract class AutoFunction extends CustomRuleFunction { Object end = SimpleColumnInfo.normalizeValueMethod(rangeVariable.getEnd(), columnType); if (begin != null && end != null) { - if ("MM".equalsIgnoreCase(name) || "YYYYMM".equalsIgnoreCase(name)) { + if ("YYYY".equalsIgnoreCase(name)) { + return enumYearValue(limit, intFunction, begin, end); + }else if ("MM".equalsIgnoreCase(name) || "YYYYMM".equalsIgnoreCase(name)) { return enumMonthValue(limit, intFunction, begin, end); } else if ("DD".equalsIgnoreCase(name) || "YYYYDD".equalsIgnoreCase(name) || "MMDD".equalsIgnoreCase(name)) { return enumDayValue(limit, intFunction, begin, end); @@ -263,7 +267,37 @@ public abstract class AutoFunction extends CustomRuleFunction { return Optional.empty(); } } - + + @NotNull + public Optional> enumYearValue(int size, ToIntFunction intFunction, Object begin, Object end) { + if (begin instanceof LocalDate && end instanceof LocalDate) { + return enumYearValue(size, intFunction, (LocalDate) begin, (LocalDate) end); + } else if (begin instanceof LocalDateTime && end instanceof LocalDateTime) { + return enumYearValue(size, intFunction, ((LocalDateTime) begin).toLocalDate(), ((LocalDateTime) end).toLocalDate()); + } else { + return Optional.empty(); + } + } + + @NotNull + public Optional> enumYearValue(int size, ToIntFunction intFunction, LocalDate begin, LocalDate end) { + Set res = new HashSet<>(); + + LocalDate cur = begin; + for (int i = 0; i < size && end.isAfter(cur) && res.size() < size;//优化 + i++) { + res.add((cur)); + cur = cur.plusMonths(1); + } + if (end.isAfter(cur)) { + return Optional.empty(); + } + if (DateUtil.isSameYearMonth(cur, end)) { + res.add((cur)); + } + return Optional.of(res); + } + @NotNull public Optional> enumMonthValue(int size, ToIntFunction intFunction, Object begin, Object end) { if (begin instanceof LocalDate && end instanceof LocalDate) { @@ -289,6 +323,9 @@ public abstract class AutoFunction extends CustomRuleFunction { if (end.isAfter(cur)) { return Optional.empty(); } + if (DateUtil.isSameYearMonth(cur, end)) { + res.add((cur)); + } return Optional.of(res); } diff --git a/router/src/main/java/io/mycat/router/function/AutoFunctionFactory.java b/router/src/main/java/io/mycat/router/function/AutoFunctionFactory.java index b369701382a2b181acfbbb76bc083ddbc0969443..d5b2c4a383c5e4708bc73f8885335c474aef0486 100644 --- a/router/src/main/java/io/mycat/router/function/AutoFunctionFactory.java +++ b/router/src/main/java/io/mycat/router/function/AutoFunctionFactory.java @@ -53,8 +53,8 @@ public class AutoFunctionFactory { int tableIndex; } - public static final ImmutableSet FLATTEN_MAPPING = ImmutableSet.of("MOD_HASH", "UNI_HASH", "RIGHT_SHIFT", "YYYYMM", "YYYYDD", "YYYYWEEK"); - public static final ImmutableSet ENUM_RANGE = ImmutableSet.of("MM", "DD", "WEEK", "MMDD", "YYYYDD", "YYYYMM", "YYYYWEEK"); + public static final ImmutableSet FLATTEN_MAPPING = ImmutableSet.of("MOD_HASH", "UNI_HASH", "RIGHT_SHIFT", "YYYY", "YYYYMM", "YYYYDD", "YYYYWEEK"); + public static final ImmutableSet ENUM_RANGE = ImmutableSet.of("YYYY", "MM", "DD", "WEEK", "MMDD", "YYYYDD", "YYYYMM", "YYYYWEEK"); @SneakyThrows public static final CustomRuleFunction @@ -161,6 +161,15 @@ public class AutoFunctionFactory { } dbFunction = specilizeSingleRangeHash(num, n, column1); } + if (SQLUtils.nameEquals("YYYY", methodInvokeExpr.getMethodName())) { + String shardingKey = getShardingKey(methodInvokeExpr); + dbShardingKeys.add(shardingKey); + SimpleColumnInfo column1 = Objects.requireNonNull( + tableHandler.getColumnByName(shardingKey) + ); + int startYear = Integer.parseInt(properties.getOrDefault("startYear", 1970).toString()); + dbFunction = specilizeyyyy(num, column1, startYear); + } if (SQLUtils.nameEquals("YYYYMM", methodInvokeExpr.getMethodName())) { String shardingKey = getShardingKey(methodInvokeExpr); dbShardingKeys.add(shardingKey); @@ -265,6 +274,15 @@ public class AutoFunctionFactory { ); tableFunction = specilizeSingleRangeHash(num, n, column1); } + if (SQLUtils.nameEquals("YYYY", methodInvokeExpr.getMethodName())) { + String shardingKey = getShardingKey(methodInvokeExpr); + tableShardingKeys.add(shardingKey); + SimpleColumnInfo column1 = Objects.requireNonNull( + tableHandler.getColumnByName(shardingKey) + ); + int startYear = Integer.parseInt(properties.getOrDefault("startYear", 1970).toString()); + tableFunction = specilizeyyyy(num, column1, startYear); + } if (SQLUtils.nameEquals("YYYYMM", methodInvokeExpr.getMethodName())) { String shardingKey = getShardingKey(methodInvokeExpr); tableShardingKeys.add(shardingKey); @@ -374,6 +392,11 @@ public class AutoFunctionFactory { ToIntFunction core = specilizeSingleRightShift(total, shift, tableColumn); tableFunction = core; dbFunction = value -> core.applyAsInt(value) / tableNum; + } else if (SQLUtils.nameEquals("YYYY", needMethodName)) { + int startYear = Integer.parseInt(properties.getOrDefault("startYear", 1970).toString()); + ToIntFunction core = specilizeyyyy(total, tableColumn, startYear); + tableFunction = core; + dbFunction = value -> core.applyAsInt(value) / tableNum; } else if (SQLUtils.nameEquals("YYYYMM", needMethodName)) { ToIntFunction core = specilizeyyyymm(total, tableColumn); tableFunction = core; @@ -648,7 +671,35 @@ public class AutoFunctionFactory { } return tableFunction; } - + + @NotNull + public static ToIntFunction specilizeyyyy(int num, SimpleColumnInfo column1,int startYear) { + ToIntFunction tableFunction; + switch (column1.getType()) { + case NUMBER: + tableFunction = o -> yyyy(num, column1.normalizeValue(o), startYear); + break; + case STRING: + tableFunction = o -> yyyy(num, column1.normalizeValue(o), startYear); + break; + case BLOB: + tableFunction = o -> yyyy(num, column1.normalizeValue(o), startYear); + break; + case TIME: + tableFunction = o -> yyyy(num, column1.normalizeValue(o), startYear); + break; + case DATE: + tableFunction = o -> yyyy(num, column1.normalizeValue(o), startYear); + break; + case TIMESTAMP: + tableFunction = o -> yyyy(num, column1.normalizeValue(o), startYear); + break; + default: + throw new IllegalStateException("Unexpected value: " + column1.getType()); + } + return tableFunction; + } + @NotNull public static ToIntFunction specilizeyyyymm(int num, SimpleColumnInfo column1) { ToIntFunction tableFunction; @@ -1032,7 +1083,28 @@ public class AutoFunctionFactory { } return (int) Math.abs(((YYYY * 366 + DD)) % num); } - + + public static int yyyy(int num, Object o,int startYear) { + if (o == null) return 0; + Integer YYYY = null; + if (o instanceof String) { + o = LocalDate.parse((String) o); + } + if (o instanceof LocalDate) { + LocalDate localDate = (LocalDate) o; + YYYY = localDate.getYear(); + } + if (o instanceof LocalDateTime) { + LocalDateTime localDateTime = (LocalDateTime) o; + YYYY = localDateTime.getYear(); + } + if (YYYY == null || YYYY < startYear) { + //找不到分库,放入第一个库 + return 0; + } + return Math.abs(YYYY - startYear); + } + public static int yyyymm(int num, Object o) { if (o == null) return 0; Integer YYYY = null;