You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by GitBox <gi...@apache.org> on 2021/02/01 03:39:44 UTC

[GitHub] [shardingsphere] jingshanglu commented on a change in pull request #9239: sql hint

jingshanglu commented on a change in pull request #9239:
URL: https://github.com/apache/shardingsphere/pull/9239#discussion_r567545921



##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/hint/AbstractHintSegment.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.sql.parser.sql.common.segment.dml.hint;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
+
+/**
+ * AbstractHintSegment.
+ */
+@RequiredArgsConstructor
+@Getter
+public abstract class AbstractHintSegment implements SQLSegment {
+
+    private final int startIndex;
+
+    private final int stopIndex;
+

Review comment:
       Delete the empty line.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/antlr4/imports/mysql/DMLStatement.g4
##########
@@ -237,6 +237,31 @@ withClause
     : WITH RECURSIVE? cteClause (COMMA_ cteClause)*
     ;
 
+hintComment
+    : SLASH_ ASTERISK_ NOT_ (databaseHintComment| shardingHintComment) ASTERISK_ SLASH_
+    ;
+
+databaseHintComment
+    : DATABASESHARDING LP_ identifier RP_
+    ;
+
+shardingHintComment
+    : shardingDatabaseHintComment? shardingTableHintComment?
+    | shardingTableHintComment? shardingDatabaseHintComment?
+    ;

Review comment:
       @jackyLqq There is a conflict between the two branches.

##########
File path: shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/hint/ShardingHintRoutingEngine.java
##########
@@ -0,0 +1,129 @@
+/*
+ * 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.sharding.route.engine.type.hint;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.base.Preconditions;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
+import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties;
+import org.apache.shardingsphere.infra.datanode.DataNode;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
+import org.apache.shardingsphere.infra.route.context.RouteMapper;
+import org.apache.shardingsphere.infra.route.context.RouteUnit;
+import org.apache.shardingsphere.sharding.api.config.strategy.sharding.ShardingStrategyConfiguration;
+import org.apache.shardingsphere.sharding.route.engine.condition.generator.ConditionValue;
+import org.apache.shardingsphere.sharding.route.engine.condition.value.ListShardingConditionValue;
+import org.apache.shardingsphere.sharding.route.engine.type.ShardingRouteEngine;
+import org.apache.shardingsphere.sharding.route.strategy.ShardingStrategy;
+import org.apache.shardingsphere.sharding.route.strategy.ShardingStrategyFactory;
+import org.apache.shardingsphere.sharding.route.strategy.type.none.NoneShardingStrategy;
+import org.apache.shardingsphere.sharding.rule.ShardingRule;
+import org.apache.shardingsphere.sharding.rule.TableRule;
+import org.apache.shardingsphere.sharding.spi.ShardingAlgorithm;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.hint.ShardingHintValueSegment;
+
+/**
+ * ShardingSqlHintRoutingEngine.
+ */
+
+@RequiredArgsConstructor
+public class ShardingHintRoutingEngine implements ShardingRouteEngine {
+
+    private final String logicTableName;
+
+    private final ConfigurationProperties properties;
+
+    private final SelectStatementContext selectStatementContext;
+
+    @Override
+    public void route(final RouteContext routeContext, final ShardingRule shardingRule) {
+        Collection<DataNode> dataNodes = getDataNodes(shardingRule, shardingRule.getTableRule(logicTableName), selectStatementContext);
+        for (DataNode each : dataNodes) {
+            routeContext.getRouteUnits().add(
+                    new RouteUnit(new RouteMapper(each.getDataSourceName(), each.getDataSourceName()), Collections.singletonList(new RouteMapper(logicTableName, each.getTableName()))));
+        }
+
+    }
+
+    private Collection<DataNode> route(final TableRule tableRule, final ShardingStrategy databaseShardingStrategy, final ShardingHintValueSegment shardingDatabaseHintValueSegment,
+                                       final ShardingStrategy tableShardingStrategy, final ShardingHintValueSegment shardingTableHintValueSegment) {
+        Collection<String> routedDataSources = routeDataSourcesByHint(tableRule, databaseShardingStrategy, shardingDatabaseHintValueSegment);
+        Collection<DataNode> result = new LinkedList<>();
+        for (String each : routedDataSources) {
+            result.addAll(routeTablesByHint(tableRule, each, tableShardingStrategy, shardingTableHintValueSegment));
+        }
+        return result;
+    }
+
+    private Collection<DataNode> getDataNodes(final ShardingRule shardingRule, final TableRule tableRule, final SelectStatementContext selectStatementContext) {
+        ShardingStrategy databaseShardingStrategy = createShardingStrategy(shardingRule.getDatabaseShardingStrategyConfiguration(tableRule), shardingRule.getShardingAlgorithms());
+        ShardingStrategy tableShardingStrategy = createShardingStrategy(shardingRule.getTableShardingStrategyConfiguration(tableRule), shardingRule.getShardingAlgorithms());
+        return route(tableRule, databaseShardingStrategy, selectStatementContext.getHintContext().getShardingHintSegment().getShardingDatabaseHintValueSegment(),
+                tableShardingStrategy, selectStatementContext.getHintContext().getShardingHintSegment().getShardingTableHintValueSegment());
+    }
+
+    private Collection<String> routeDataSourcesByHint(final TableRule tableRule, final ShardingStrategy databaseShardingStrategy, final ShardingHintValueSegment shardingDatabaseHintValueSegment) {
+        Collection<String> datasourceNames = tableRule.getActualDatasourceNames();
+        if (shardingDatabaseHintValueSegment != null) {
+            List<ExpressionSegment> databaseHintValueSegmentValues = shardingDatabaseHintValueSegment.getValues();
+            ListShardingConditionValue<Comparable<?>> listShardingValue = getListShardingValueFromHint(databaseHintValueSegmentValues, databaseShardingStrategy);
+            datasourceNames = new LinkedHashSet<>(databaseShardingStrategy.doSharding(datasourceNames, Collections.singletonList(listShardingValue), properties));
+        } 
+        Preconditions.checkState(!datasourceNames.isEmpty(), "no database route info");
+        Preconditions.checkState(tableRule.getActualDatasourceNames().containsAll(datasourceNames),
+                "Some routed data sources do not belong to configured data sources. routed data sources: `%s`, configured data sources: `%s`", datasourceNames, tableRule.getActualDatasourceNames());
+        return datasourceNames;
+    }
+
+    private ListShardingConditionValue<Comparable<?>> getListShardingValueFromHint(final List<ExpressionSegment> databaseHintValueSegmentValues, final ShardingStrategy shardingStrategy) {
+        Collection<Comparable<?>> shardingConditionValues = new LinkedHashSet<>();
+        for (ExpressionSegment expressionSegment : databaseHintValueSegmentValues) {
+            new ConditionValue(expressionSegment, Collections.emptyList()).getValue().ifPresent(shardingConditionValues::add);
+        }
+        return new ListShardingConditionValue<>(shardingStrategy.getShardingColumns().iterator().next(), logicTableName, shardingConditionValues);
+    }
+
+    private Collection<? extends DataNode> routeTablesByHint(final TableRule tableRule, final String routedDataSource,
+                                                             final ShardingStrategy tableShardingStrategy, final ShardingHintValueSegment shardingTableHintValueSegment) {
+        Collection<String> availableTargetTables = tableRule.getActualTableNames(routedDataSource);
+        if (shardingTableHintValueSegment != null) {
+            ListShardingConditionValue<Comparable<?>> listShardingValue = getListShardingValueFromHint(shardingTableHintValueSegment.getValues(), tableShardingStrategy);
+            availableTargetTables = tableShardingStrategy.doSharding(availableTargetTables, Collections.singletonList(listShardingValue), properties);
+        }
+        Collection<DataNode> result = new LinkedList<>();
+        for (String each : availableTargetTables) {
+            result.add(new DataNode(routedDataSource, each));
+        }
+        return result;
+    }
+
+    private ShardingStrategy createShardingStrategy(final ShardingStrategyConfiguration shardingStrategyConfig, final Map<String, ShardingAlgorithm> shardingAlgorithms) {
+        return null == shardingStrategyConfig ? new NoneShardingStrategy()
+                : ShardingStrategyFactory.newInstance(shardingStrategyConfig, shardingAlgorithms.get(shardingStrategyConfig.getShardingAlgorithmName()));
+    }
+

Review comment:
       Plz delete the empty line.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/test/java/org/apache/shardingsphere/sql/parser/mysql/MySQLFormatTest.java
##########
@@ -117,7 +117,7 @@
                 + "FROM t_order\n"
                 + "WHERE \n"
                 + "\torder_id = 1;"});
-        testUnits.add(new String[]{"only_comment", "/* c_zz_xdba_test_4 login */", ""});
+        // testUnits.add(new String[]{"only_comment", "/* c_zz_xdba_test_4 login */", ""});

Review comment:
       why delete the case?

##########
File path: shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/select/hint/HintContextEngineTest.java
##########
@@ -0,0 +1,64 @@
+/*
+ * 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.infra.binder.segment.select.hint;
+
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.hint.DataBaseHintSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.hint.HintSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.hint.ShardingHintSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.hint.ShardingHintValueSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLSelectStatement;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * HintContextEngineTest.
+ */
+public final class HintContextEngineTest {
+
+    @Test
+    public void testCreateHintContextForCommonSql() {
+        HintContext hintContext = new HintContextEngine().createHintContext(new MySQLSelectStatement());
+        Assert.assertEquals(HintType.NONE, hintContext.getHintType());
+    }
+
+    @Test
+    public void testCreateHintContextForDataBaseHint() {
+        MySQLSelectStatement mySQLSelectStatement = new MySQLSelectStatement();
+        mySQLSelectStatement.setHint(new HintSegment(0, 52, new DataBaseHintSegment(3, 50, new IdentifierValue("ds_0"))));
+        HintContext hintContext = new HintContextEngine().createHintContext(mySQLSelectStatement);
+        Assert.assertEquals(HintType.DATABASE_HINT, hintContext.getHintType());
+    }
+
+    @Test
+    public void testCreateHintContextForShardingValueHint() {
+        ShardingHintValueSegment shardingDatabaseHintValueSegment = new ShardingHintValueSegment(10, 50);
+        shardingDatabaseHintValueSegment.getValues().add(new LiteralExpressionSegment(20, 40, 1));
+        ShardingHintValueSegment shardingTableHintValueSegment = new ShardingHintValueSegment(50, 90);
+        shardingTableHintValueSegment.getValues().add(new LiteralExpressionSegment(60, 80, 1));
+        ShardingHintSegment shardingHintSegment = new ShardingHintSegment(10, 90);
+        shardingHintSegment.setShardingDatabaseHintValueSegment(shardingDatabaseHintValueSegment);
+        shardingHintSegment.setShardingTableHintValueSegment(shardingTableHintValueSegment);
+        MySQLSelectStatement mySQLSelectStatement = new MySQLSelectStatement();
+        mySQLSelectStatement.setHint(new HintSegment(0, 100, shardingHintSegment));
+        HintContext hintContext = new HintContextEngine().createHintContext(mySQLSelectStatement);
+        Assert.assertEquals(HintType.SHARDING_HINT, hintContext.getHintType());
+    }
+    

Review comment:
       Plz delete the empty line.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-test/src/main/resources/sql/supported/dml/select-comment.xml
##########
@@ -17,6 +17,6 @@
   -->
 
 <sql-cases>
-    <sql-case id="select_with_block_comment" value="SELECT * /* this is &#x000D;&#x000A; block comment */ FROM /* this is another &#x000A; block comment */ t_order where status='1'" db-types="MySQL" />
+   <!-- <sql-case id="select_with_block_comment" value="SELECT * /* this is &#x000D;&#x000A; block comment */ FROM /* this is another &#x000A; block comment */ t_order where status='1'" db-types="MySQL" />-->

Review comment:
       We should not delete exist test case.

##########
File path: shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-mysql/src/main/antlr4/imports/mysql/Keyword.g4
##########
@@ -115,3 +115,15 @@ INNODB
 REDO_LOG
     : 'REDO_LOG'
     ;
+
+DATABASESHARDING
+    : D A T A B A S E S H A R D I N G
+    ;
+
+SHARDINGDATABASEVALUE
+    : S H A R D I N G D A T A B A S E V A L U E
+    ;
+
+SHARDINGTABLEVALUE
+    : S H A R D I N G T A B L E V A L U E
+    ;

Review comment:
       A blank line is required at the end of the file.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org