From a515d93f8a25bde0ccd8616bc2ebe6e1e0539571 Mon Sep 17 00:00:00 2001 From: Pramy Date: Fri, 11 Oct 2019 22:38:50 +0800 Subject: [PATCH] support now() for sharding value (#3217) Change-Id: I3fb454efc9089e10f1e3a8c5d4eb575327816548 --- .../condition/ExpressionConditionUtils.java | 38 +++++++ .../InsertClauseShardingConditionEngine.java | 11 +- ...onditionValueBetweenOperatorGenerator.java | 16 ++- ...onditionValueCompareOperatorGenerator.java | 10 +- .../ConditionValueInOperatorGenerator.java | 7 ++ .../core/route/spi/DefaultTimeService.java | 34 ++++++ .../core/route/spi/SPITimeService.java | 49 +++++++++ .../core/route/spi/TimeService.java | 34 ++++++ ....shardingsphere.core.route.spi.TimeService | 18 ++++ .../route/fixture/TimeServiceFixture.java | 36 +++++++ .../ExpressionConditionUtilsTest.java | 35 ++++++ ...tionValueBetweenOperatorGeneratorTest.java | 102 ++++++++++++++++++ ...tionValueCompareOperatorGeneratorTest.java | 74 +++++++++++++ ...ConditionValueInOperatorGeneratorTest.java | 55 ++++++++++ .../core/route/spi/SPITimeServiceTest.java | 71 ++++++++++++ ....shardingsphere.core.route.spi.TimeService | 18 ++++ 16 files changed, 604 insertions(+), 4 deletions(-) create mode 100644 sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/ExpressionConditionUtils.java create mode 100644 sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/DefaultTimeService.java create mode 100644 sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/SPITimeService.java create mode 100644 sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/TimeService.java create mode 100644 sharding-core/sharding-core-route/src/main/resources/META-INF/services/org.apache.shardingsphere.core.route.spi.TimeService create mode 100644 sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/fixture/TimeServiceFixture.java create mode 100644 sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/ExpressionConditionUtilsTest.java create mode 100644 sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueBetweenOperatorGeneratorTest.java create mode 100644 sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueCompareOperatorGeneratorTest.java create mode 100644 sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueInOperatorGeneratorTest.java create mode 100644 sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/spi/SPITimeServiceTest.java create mode 100644 sharding-core/sharding-core-route/src/test/resources/META-INF/services/org.apache.shardingsphere.core.route.spi.TimeService diff --git a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/ExpressionConditionUtils.java b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/ExpressionConditionUtils.java new file mode 100644 index 0000000000..5cf5a5f6c5 --- /dev/null +++ b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/ExpressionConditionUtils.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.core.route.router.sharding.condition; + +import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.ExpressionSegment; +import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.complex.ComplexExpressionSegment; + +/** + * Expression judgment tool for route. + * + * @author chenchuangliu + */ +public final class ExpressionConditionUtils { + + /** + * Judge now() expression. + * @param segment ExpressionSegment + * @return true or false + */ + public static boolean isNowExpression(final ExpressionSegment segment) { + return segment instanceof ComplexExpressionSegment && "now()".equals(((ComplexExpressionSegment) segment).getText().toLowerCase()); + } +} diff --git a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/engine/InsertClauseShardingConditionEngine.java b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/engine/InsertClauseShardingConditionEngine.java index 74cf1d5f81..88f1799e35 100644 --- a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/engine/InsertClauseShardingConditionEngine.java +++ b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/engine/InsertClauseShardingConditionEngine.java @@ -25,8 +25,10 @@ import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.ExpressionSegme import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.simple.LiteralExpressionSegment; import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.simple.ParameterMarkerExpressionSegment; import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.simple.SimpleExpressionSegment; +import org.apache.shardingsphere.core.route.router.sharding.condition.ExpressionConditionUtils; import org.apache.shardingsphere.core.route.router.sharding.condition.ShardingCondition; import org.apache.shardingsphere.core.route.router.sharding.keygen.GeneratedKey; +import org.apache.shardingsphere.core.route.spi.SPITimeService; import org.apache.shardingsphere.core.rule.ShardingRule; import org.apache.shardingsphere.core.strategy.route.value.ListRouteValue; @@ -78,10 +80,15 @@ public final class InsertClauseShardingConditionEngine { private ShardingCondition createShardingCondition(final String tableName, final Iterator columnNames, final InsertValueContext insertValueContext, final List parameters) { ShardingCondition result = new ShardingCondition(); + SPITimeService timeService = new SPITimeService(); for (ExpressionSegment each : insertValueContext.getValueExpressions()) { String columnName = columnNames.next(); - if (each instanceof SimpleExpressionSegment && shardingRule.isShardingColumn(columnName, tableName)) { - result.getRouteValues().add(new ListRouteValue<>(columnName, tableName, Collections.singletonList(getRouteValue((SimpleExpressionSegment) each, parameters)))); + if (shardingRule.isShardingColumn(columnName, tableName)) { + if (each instanceof SimpleExpressionSegment) { + result.getRouteValues().add(new ListRouteValue<>(columnName, tableName, Collections.singletonList(getRouteValue((SimpleExpressionSegment) each, parameters)))); + } else if (ExpressionConditionUtils.isNowExpression(each)) { + result.getRouteValues().add(new ListRouteValue<>(columnName, tableName, Collections.singletonList(timeService.getTime()))); + } } } return result; diff --git a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueBetweenOperatorGenerator.java b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueBetweenOperatorGenerator.java index a98e1d3072..ba5f97f2d8 100644 --- a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueBetweenOperatorGenerator.java +++ b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueBetweenOperatorGenerator.java @@ -20,12 +20,15 @@ package org.apache.shardingsphere.core.route.router.sharding.condition.generator import com.google.common.base.Optional; import com.google.common.collect.Range; import org.apache.shardingsphere.core.route.router.sharding.condition.Column; +import org.apache.shardingsphere.core.route.router.sharding.condition.ExpressionConditionUtils; import org.apache.shardingsphere.core.route.router.sharding.condition.generator.ConditionValue; import org.apache.shardingsphere.core.route.router.sharding.condition.generator.ConditionValueGenerator; import org.apache.shardingsphere.core.parse.sql.segment.dml.predicate.value.PredicateBetweenRightValue; +import org.apache.shardingsphere.core.route.spi.SPITimeService; import org.apache.shardingsphere.core.strategy.route.value.RangeRouteValue; import org.apache.shardingsphere.core.strategy.route.value.RouteValue; +import java.util.Date; import java.util.List; /** @@ -39,7 +42,18 @@ public final class ConditionValueBetweenOperatorGenerator implements ConditionVa public Optional generate(final PredicateBetweenRightValue predicateRightValue, final Column column, final List parameters) { Optional betweenRouteValue = new ConditionValue(predicateRightValue.getBetweenExpression(), parameters).getValue(); Optional andRouteValue = new ConditionValue(predicateRightValue.getAndExpression(), parameters).getValue(); + if (betweenRouteValue.isPresent() && andRouteValue.isPresent()) { + return Optional.of(new RangeRouteValue<>(column.getName(), column.getTableName(), Range.closed(betweenRouteValue.get(), andRouteValue.get()))); + } + Date date = new SPITimeService().getTime(); + if (!betweenRouteValue.isPresent() && ExpressionConditionUtils.isNowExpression(predicateRightValue.getBetweenExpression())) { + betweenRouteValue = Optional.of((Comparable) date); + } + if (!andRouteValue.isPresent() && ExpressionConditionUtils.isNowExpression(predicateRightValue.getAndExpression())) { + andRouteValue = Optional.of((Comparable) date); + } return betweenRouteValue.isPresent() && andRouteValue.isPresent() - ? Optional.of(new RangeRouteValue<>(column.getName(), column.getTableName(), Range.closed(betweenRouteValue.get(), andRouteValue.get()))) : Optional.absent(); + ? Optional.of(new RangeRouteValue<>(column.getName(), column.getTableName(), Range.closed(betweenRouteValue.get(), andRouteValue.get()))) + : Optional.absent(); } } diff --git a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueCompareOperatorGenerator.java b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueCompareOperatorGenerator.java index 5a7fbedf89..071e45ea67 100644 --- a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueCompareOperatorGenerator.java +++ b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueCompareOperatorGenerator.java @@ -20,9 +20,11 @@ package org.apache.shardingsphere.core.route.router.sharding.condition.generator import com.google.common.base.Optional; import com.google.common.collect.Lists; import org.apache.shardingsphere.core.route.router.sharding.condition.Column; +import org.apache.shardingsphere.core.route.router.sharding.condition.ExpressionConditionUtils; import org.apache.shardingsphere.core.route.router.sharding.condition.generator.ConditionValue; import org.apache.shardingsphere.core.route.router.sharding.condition.generator.ConditionValueGenerator; import org.apache.shardingsphere.core.parse.sql.segment.dml.predicate.value.PredicateCompareRightValue; +import org.apache.shardingsphere.core.route.spi.SPITimeService; import org.apache.shardingsphere.core.strategy.route.value.ListRouteValue; import org.apache.shardingsphere.core.strategy.route.value.RouteValue; @@ -41,7 +43,13 @@ public final class ConditionValueCompareOperatorGenerator implements ConditionVa return Optional.absent(); } Optional routeValue = new ConditionValue(predicateRightValue.getExpression(), parameters).getValue(); - return routeValue.isPresent() ? Optional.of(new ListRouteValue<>(column.getName(), column.getTableName(), Lists.newArrayList(routeValue.get()))) : Optional.absent(); + if (routeValue.isPresent()) { + return Optional.of(new ListRouteValue<>(column.getName(), column.getTableName(), Lists.newArrayList(routeValue.get()))); + } + if (ExpressionConditionUtils.isNowExpression(predicateRightValue.getExpression())) { + return Optional.of(new ListRouteValue<>(column.getName(), column.getTableName(), Lists.newArrayList(new SPITimeService().getTime()))); + } + return Optional.absent(); } private boolean isSupportedOperator(final String operator) { diff --git a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueInOperatorGenerator.java b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueInOperatorGenerator.java index 13771fef41..6e6a345136 100644 --- a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueInOperatorGenerator.java +++ b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueInOperatorGenerator.java @@ -19,10 +19,12 @@ package org.apache.shardingsphere.core.route.router.sharding.condition.generator import com.google.common.base.Optional; import org.apache.shardingsphere.core.route.router.sharding.condition.Column; +import org.apache.shardingsphere.core.route.router.sharding.condition.ExpressionConditionUtils; import org.apache.shardingsphere.core.route.router.sharding.condition.generator.ConditionValue; import org.apache.shardingsphere.core.route.router.sharding.condition.generator.ConditionValueGenerator; import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.ExpressionSegment; import org.apache.shardingsphere.core.parse.sql.segment.dml.predicate.value.PredicateInRightValue; +import org.apache.shardingsphere.core.route.spi.SPITimeService; import org.apache.shardingsphere.core.strategy.route.value.ListRouteValue; import org.apache.shardingsphere.core.strategy.route.value.RouteValue; @@ -39,10 +41,15 @@ public final class ConditionValueInOperatorGenerator implements ConditionValueGe @Override public Optional generate(final PredicateInRightValue predicateRightValue, final Column column, final List parameters) { List routeValues = new LinkedList<>(); + SPITimeService timeService = new SPITimeService(); for (ExpressionSegment each : predicateRightValue.getSqlExpressions()) { Optional routeValue = new ConditionValue(each, parameters).getValue(); if (routeValue.isPresent()) { routeValues.add(routeValue.get()); + continue; + } + if (ExpressionConditionUtils.isNowExpression(each)) { + routeValues.add(timeService.getTime()); } } return routeValues.isEmpty() ? Optional.absent() : Optional.of(new ListRouteValue<>(column.getName(), column.getTableName(), routeValues)); diff --git a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/DefaultTimeService.java b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/DefaultTimeService.java new file mode 100644 index 0000000000..33841d9795 --- /dev/null +++ b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/DefaultTimeService.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.core.route.spi; + +import java.util.Date; + +/** + * Default time service. + * + * @author chenchuangliu + */ +public final class DefaultTimeService implements TimeService { + + @Override + public Date getTime() { + return new Date(); + } +} + diff --git a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/SPITimeService.java b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/SPITimeService.java new file mode 100644 index 0000000000..6a2201b8c5 --- /dev/null +++ b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/SPITimeService.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.core.route.spi; + +import org.apache.shardingsphere.core.spi.NewInstanceServiceLoader; + +import java.util.Collection; +import java.util.Date; + +/** + * Time service for SPI. + * + * @author chenchuangliu + */ +public final class SPITimeService implements TimeService { + + private final Collection timeServices = NewInstanceServiceLoader.newServiceInstances(TimeService.class); + + static { + NewInstanceServiceLoader.register(TimeService.class); + } + + @Override + public Date getTime() { + Date date = null; + for (TimeService server : timeServices) { + date = server.getTime(); + if (!(server instanceof DefaultTimeService) && null != date) { + return date; + } + } + return date; + } +} diff --git a/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/TimeService.java b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/TimeService.java new file mode 100644 index 0000000000..f4281359af --- /dev/null +++ b/sharding-core/sharding-core-route/src/main/java/org/apache/shardingsphere/core/route/spi/TimeService.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.core.route.spi; + +import java.util.Date; + +/** + * Time service. + * + * @author chenchuangliu + */ +public interface TimeService { + + /** + * Get date from time server. + * @return date + */ + Date getTime(); +} diff --git a/sharding-core/sharding-core-route/src/main/resources/META-INF/services/org.apache.shardingsphere.core.route.spi.TimeService b/sharding-core/sharding-core-route/src/main/resources/META-INF/services/org.apache.shardingsphere.core.route.spi.TimeService new file mode 100644 index 0000000000..2c2a1b0f77 --- /dev/null +++ b/sharding-core/sharding-core-route/src/main/resources/META-INF/services/org.apache.shardingsphere.core.route.spi.TimeService @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +org.apache.shardingsphere.core.route.spi.DefaultTimeService diff --git a/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/fixture/TimeServiceFixture.java b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/fixture/TimeServiceFixture.java new file mode 100644 index 0000000000..3cebd60ab2 --- /dev/null +++ b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/fixture/TimeServiceFixture.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.core.route.fixture; + +import lombok.Getter; +import lombok.Setter; +import org.apache.shardingsphere.core.route.spi.TimeService; + +import java.util.Date; + +public final class TimeServiceFixture implements TimeService { + + @Getter + @Setter + private Date date; + + @Override + public Date getTime() { + return date; + } +} diff --git a/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/ExpressionConditionUtilsTest.java b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/ExpressionConditionUtilsTest.java new file mode 100644 index 0000000000..ce23a1bad9 --- /dev/null +++ b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/ExpressionConditionUtilsTest.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.core.route.router.sharding.condition; + +import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.complex.CommonExpressionSegment; +import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.simple.LiteralExpressionSegment; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public final class ExpressionConditionUtilsTest { + + @Test + public void assertIsNowExpression() { + assertFalse(ExpressionConditionUtils.isNowExpression(new LiteralExpressionSegment(0, 0, new Object()))); + assertFalse(ExpressionConditionUtils.isNowExpression(new CommonExpressionSegment(0, 0, "shardingsphere"))); + assertTrue(ExpressionConditionUtils.isNowExpression(new CommonExpressionSegment(0, 0, "NOW()"))); + } +} diff --git a/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueBetweenOperatorGeneratorTest.java b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueBetweenOperatorGeneratorTest.java new file mode 100644 index 0000000000..0657d36346 --- /dev/null +++ b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueBetweenOperatorGeneratorTest.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.core.route.router.sharding.condition.generator.impl; + +import com.google.common.base.Optional; +import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.ExpressionSegment; +import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.complex.CommonExpressionSegment; +import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.simple.LiteralExpressionSegment; +import org.apache.shardingsphere.core.parse.sql.segment.dml.predicate.value.PredicateBetweenRightValue; +import org.apache.shardingsphere.core.route.router.sharding.condition.Column; +import org.apache.shardingsphere.core.strategy.route.value.RangeRouteValue; +import org.apache.shardingsphere.core.strategy.route.value.RouteValue; +import org.junit.Test; + +import java.util.Calendar; +import java.util.Date; +import java.util.LinkedList; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertThat; + +public final class ConditionValueBetweenOperatorGeneratorTest { + + private ConditionValueBetweenOperatorGenerator generator = new ConditionValueBetweenOperatorGenerator(); + + private Column column = new Column("shardsphere", "apache"); + + @Test + public void assertGenerateConditionValue() { + int between = 1; + int and = 2; + ExpressionSegment betweenSegment = new LiteralExpressionSegment(0, 0, between); + ExpressionSegment andSegment = new LiteralExpressionSegment(0, 0, and); + PredicateBetweenRightValue value = new PredicateBetweenRightValue(betweenSegment, andSegment); + Optional optional = generator.generate(value, column, new LinkedList<>()); + assertTrue(optional.isPresent()); + assertTrue(optional.get() instanceof RangeRouteValue); + RangeRouteValue rangeRouteValue = (RangeRouteValue) optional.get(); + assertEquals(rangeRouteValue.getColumnName(), column.getName()); + assertEquals(rangeRouteValue.getTableName(), column.getTableName()); + assertTrue(rangeRouteValue.getValueRange().contains(between)); + assertTrue(rangeRouteValue.getValueRange().contains(and)); + } + + @Test(expected = ClassCastException.class) + public void assertGenerateErrorConditionValue() { + int between = 1; + ExpressionSegment betweenSegment = new LiteralExpressionSegment(0, 0, between); + ExpressionSegment andSegment = new CommonExpressionSegment(0, 0, "now()"); + PredicateBetweenRightValue value = new PredicateBetweenRightValue(betweenSegment, andSegment); + generator.generate(value, column, new LinkedList<>()); + } + + @Test + public void assertGenerateOneNowConditionValue() { + Date date = new Date(); + ExpressionSegment betweenSegment = new LiteralExpressionSegment(0, 0, date); + ExpressionSegment andSegment = new CommonExpressionSegment(0, 0, "now()"); + PredicateBetweenRightValue value = new PredicateBetweenRightValue(betweenSegment, andSegment); + Optional optional = generator.generate(value, column, new LinkedList<>()); + assertTrue(optional.isPresent()); + assertTrue(optional.get() instanceof RangeRouteValue); + RangeRouteValue rangeRouteValue = (RangeRouteValue) optional.get(); + assertEquals(rangeRouteValue.getColumnName(), column.getName()); + assertEquals(rangeRouteValue.getTableName(), column.getTableName()); + assertThat(rangeRouteValue.getValueRange().lowerEndpoint(), is(date)); + } + + @Test + public void assertGenerateNowConditionValue() { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DATE, 1); + final Date after = calendar.getTime(); + ExpressionSegment betweenSegment = new CommonExpressionSegment(0, 0, "now()"); + ExpressionSegment andSegment = new CommonExpressionSegment(0, 0, "now()"); + PredicateBetweenRightValue value = new PredicateBetweenRightValue(betweenSegment, andSegment); + Optional optional = generator.generate(value, column, new LinkedList<>()); + assertTrue(optional.isPresent()); + assertTrue(optional.get() instanceof RangeRouteValue); + RangeRouteValue rangeRouteValue = (RangeRouteValue) optional.get(); + assertEquals(rangeRouteValue.getColumnName(), column.getName()); + assertEquals(rangeRouteValue.getTableName(), column.getTableName()); + assertTrue(rangeRouteValue.getValueRange().upperEndpoint().before(after)); + } +} diff --git a/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueCompareOperatorGeneratorTest.java b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueCompareOperatorGeneratorTest.java new file mode 100644 index 0000000000..a01ee79e72 --- /dev/null +++ b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueCompareOperatorGeneratorTest.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.core.route.router.sharding.condition.generator.impl; + +import com.google.common.base.Optional; +import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.complex.CommonExpressionSegment; +import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.simple.LiteralExpressionSegment; +import org.apache.shardingsphere.core.parse.sql.segment.dml.predicate.value.PredicateCompareRightValue; +import org.apache.shardingsphere.core.route.router.sharding.condition.Column; +import org.apache.shardingsphere.core.strategy.route.value.ListRouteValue; +import org.apache.shardingsphere.core.strategy.route.value.RouteValue; +import org.junit.Test; + +import java.util.LinkedList; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public final class ConditionValueCompareOperatorGeneratorTest { + + private ConditionValueCompareOperatorGenerator generator = new ConditionValueCompareOperatorGenerator(); + + private Column column = new Column("shardsphere", "apache"); + + @Test + public void assertGenerateConditionValue() { + int value = 1; + PredicateCompareRightValue rightValue = new PredicateCompareRightValue("=", new LiteralExpressionSegment(0, 0, value)); + Optional routeValueOptional = generator.generate(rightValue, column, new LinkedList<>()); + assertTrue(routeValueOptional.isPresent()); + assertTrue(routeValueOptional.get() instanceof ListRouteValue); + ListRouteValue listRouteValue = (ListRouteValue) routeValueOptional.get(); + assertTrue(listRouteValue.getValues().contains(value)); + } + + @Test + public void assertGenerateConditionValueWithErrorOperator() { + PredicateCompareRightValue rightValue = new PredicateCompareRightValue("<", new LiteralExpressionSegment(0, 0, 1)); + Optional routeValueOptional = generator.generate(rightValue, column, new LinkedList<>()); + assertFalse(routeValueOptional.isPresent()); + } + + @Test + public void assertGenerateConditionValueWithoutNowExpression() { + PredicateCompareRightValue rightValue = new PredicateCompareRightValue("=", new CommonExpressionSegment(0, 0, "value")); + Optional routeValueOptional = generator.generate(rightValue, column, new LinkedList<>()); + assertFalse(routeValueOptional.isPresent()); + } + + @Test + public void assertGenerateConditionValueWithNowExpression() { + PredicateCompareRightValue rightValue = new PredicateCompareRightValue("=", new CommonExpressionSegment(0, 0, "now()")); + Optional routeValueOptional = generator.generate(rightValue, column, new LinkedList<>()); + assertTrue(routeValueOptional.isPresent()); + assertTrue(routeValueOptional.get() instanceof ListRouteValue); + ListRouteValue listRouteValue = (ListRouteValue) routeValueOptional.get(); + assertFalse(listRouteValue.getValues().isEmpty()); + } +} diff --git a/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueInOperatorGeneratorTest.java b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueInOperatorGeneratorTest.java new file mode 100644 index 0000000000..a497af5061 --- /dev/null +++ b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/router/sharding/condition/generator/impl/ConditionValueInOperatorGeneratorTest.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.core.route.router.sharding.condition.generator.impl; + +import com.google.common.base.Optional; +import com.google.common.collect.Lists; +import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.ExpressionSegment; +import org.apache.shardingsphere.core.parse.sql.segment.dml.expr.complex.CommonExpressionSegment; +import org.apache.shardingsphere.core.parse.sql.segment.dml.predicate.value.PredicateInRightValue; +import org.apache.shardingsphere.core.route.router.sharding.condition.Column; +import org.apache.shardingsphere.core.strategy.route.value.ListRouteValue; +import org.apache.shardingsphere.core.strategy.route.value.RouteValue; +import org.junit.Test; + +import java.util.Collection; +import java.util.Date; +import java.util.LinkedList; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public final class ConditionValueInOperatorGeneratorTest { + + private ConditionValueInOperatorGenerator generator = new ConditionValueInOperatorGenerator(); + + private Column column = new Column("shardsphere", "apache"); + + @Test + public void assertNowExpression() { + Collection segmentCollection = Lists.newArrayList(); + segmentCollection.add(new CommonExpressionSegment(0, 0, "now()")); + PredicateInRightValue inRightValue = new PredicateInRightValue(segmentCollection); + Optional optional = generator.generate(inRightValue, column, new LinkedList<>()); + assertTrue(optional.isPresent()); + assertTrue(optional.get() instanceof ListRouteValue); + ListRouteValue listRouteValue = (ListRouteValue) optional.get(); + assertFalse(listRouteValue.getValues().isEmpty()); + assertTrue(listRouteValue.getValues().iterator().next() instanceof Date); + } +} diff --git a/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/spi/SPITimeServiceTest.java b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/spi/SPITimeServiceTest.java new file mode 100644 index 0000000000..2bcef50f8c --- /dev/null +++ b/sharding-core/sharding-core-route/src/test/java/org/apache/shardingsphere/core/route/spi/SPITimeServiceTest.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.core.route.spi; + +import com.google.common.base.Optional; +import lombok.SneakyThrows; +import org.apache.shardingsphere.core.route.fixture.TimeServiceFixture; +import org.junit.Test; + +import java.lang.reflect.Field; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertThat; + +public class SPITimeServiceTest { + + private SPITimeService timeService = new SPITimeService(); + + @Test + public void assertGetTime() { + Optional optional = getFixtureHook(); + assertTrue(optional.isPresent()); + Date date = new Date(); + optional.get().setDate(date); + Date time = timeService.getTime(); + assertThat(date, is(time)); + } + + @Test + public void assertGetTimeWithDefault() { + Optional optional = getFixtureHook(); + assertTrue(optional.isPresent()); + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DATE, -1); + Date date = calendar.getTime(); + Date time = timeService.getTime(); + assertTrue(time.after(date)); + } + + @SneakyThrows + private Optional getFixtureHook() { + Field routingHooksField = SPITimeService.class.getDeclaredField("timeServices"); + routingHooksField.setAccessible(true); + Collection timeServices = (Collection) routingHooksField.get(timeService); + for (TimeService timeService : timeServices) { + if (timeService instanceof TimeServiceFixture) { + return Optional.of((TimeServiceFixture) timeService); + } + } + return Optional.absent(); + } +} diff --git a/sharding-core/sharding-core-route/src/test/resources/META-INF/services/org.apache.shardingsphere.core.route.spi.TimeService b/sharding-core/sharding-core-route/src/test/resources/META-INF/services/org.apache.shardingsphere.core.route.spi.TimeService new file mode 100644 index 0000000000..266fa7c4bb --- /dev/null +++ b/sharding-core/sharding-core-route/src/test/resources/META-INF/services/org.apache.shardingsphere.core.route.spi.TimeService @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +org.apache.shardingsphere.core.route.fixture.TimeServiceFixture -- GitLab