This is an automated email from the ASF dual-hosted git repository.
panjuan 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 59bc2771eeb Refactor SingleSQLRouter code style and logic for schema
rewrite (#27349)
59bc2771eeb is described below
commit 59bc2771eeb016ba5d17b92486f55bb19ca3920e
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Fri Jul 21 12:56:13 2023 +0800
Refactor SingleSQLRouter code style and logic for schema rewrite (#27349)
---
.../single/decider/SingleSQLFederationDecider.java | 65 ++++------------
.../single/route/SingleSQLRouter.java | 75 +++++--------------
.../route/engine/SingleRouteEngineFactory.java | 10 +--
.../route/engine/SingleStandardRouteEngine.java | 51 +++++++++----
.../shardingsphere/single/rule/SingleRule.java | 86 ++++++++++++++--------
.../decider/SingleSQLFederationDeciderTest.java | 18 ++---
.../route/engine/SingleRouteEngineFactoryTest.java | 2 +-
.../shardingsphere/single/rule/SingleRuleTest.java | 27 +++----
.../query/ShowUnloadedSingleTableExecutor.java | 3 +-
9 files changed, 149 insertions(+), 188 deletions(-)
diff --git
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/decider/SingleSQLFederationDecider.java
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/decider/SingleSQLFederationDecider.java
index b70623aa359..b932bed815a 100644
---
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/decider/SingleSQLFederationDecider.java
+++
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/decider/SingleSQLFederationDecider.java
@@ -17,26 +17,18 @@
package org.apache.shardingsphere.single.decider;
-import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
import
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
-import org.apache.shardingsphere.infra.binder.type.IndexAvailable;
-import org.apache.shardingsphere.infra.database.spi.DatabaseType;
-import org.apache.shardingsphere.infra.database.DatabaseTypeEngine;
import org.apache.shardingsphere.infra.datanode.DataNode;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
import org.apache.shardingsphere.infra.metadata.database.schema.QualifiedTable;
-import
org.apache.shardingsphere.infra.metadata.database.schema.util.IndexMetaDataUtils;
import org.apache.shardingsphere.single.constant.SingleOrder;
import org.apache.shardingsphere.single.rule.SingleRule;
-import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
import org.apache.shardingsphere.sqlfederation.spi.SQLFederationDecider;
import java.util.Collection;
import java.util.HashSet;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Optional;
/**
* Single SQL federation decider.
@@ -46,39 +38,25 @@ public final class SingleSQLFederationDecider implements
SQLFederationDecider<Si
@Override
public boolean decide(final SelectStatementContext selectStatementContext,
final List<Object> parameters,
final ShardingSphereRuleMetaData globalRuleMetaData,
final ShardingSphereDatabase database, final SingleRule rule, final
Collection<DataNode> includedDataNodes) {
- Collection<QualifiedTable> singleTableNames =
getSingleTableNames(selectStatementContext, database, rule);
- if (singleTableNames.isEmpty()) {
+ Collection<QualifiedTable> singleTables =
getSingleTables(selectStatementContext, database, rule);
+ if (singleTables.isEmpty()) {
return false;
}
- if (containsView(database, singleTableNames)) {
+ if (containsView(database, singleTables)) {
return true;
}
- boolean isAllTablesInSameDataSource =
isAllTablesInSameDataSource(includedDataNodes, rule, singleTableNames);
- includedDataNodes.addAll(getTableDataNodes(rule, singleTableNames));
- return !isAllTablesInSameDataSource;
+ boolean isAllTablesInSameComputeNode =
rule.isAllTablesInSameComputeNode(includedDataNodes, singleTables);
+ includedDataNodes.addAll(getTableDataNodes(rule, singleTables));
+ return !isAllTablesInSameComputeNode;
}
- private Collection<QualifiedTable> getSingleTableNames(final
SQLStatementContext sqlStatementContext, final ShardingSphereDatabase database,
final SingleRule rule) {
- DatabaseType databaseType = sqlStatementContext.getDatabaseType();
- Collection<QualifiedTable> result = getQualifiedTables(database,
databaseType, sqlStatementContext.getTablesContext().getSimpleTableSegments());
- if (result.isEmpty() && sqlStatementContext instanceof IndexAvailable)
{
- result = IndexMetaDataUtils.getTableNames(database, databaseType,
((IndexAvailable) sqlStatementContext).getIndexes());
- }
- return rule.getSingleTableNames(result);
+ private Collection<QualifiedTable> getSingleTables(final
SelectStatementContext selectStatementContext, final ShardingSphereDatabase
database, final SingleRule rule) {
+ Collection<QualifiedTable> qualifiedTables =
rule.getQualifiedTables(selectStatementContext, database);
+ return rule.getSingleTables(qualifiedTables);
}
- private Collection<QualifiedTable> getQualifiedTables(final
ShardingSphereDatabase database, final DatabaseType databaseType, final
Collection<SimpleTableSegment> tableSegments) {
- Collection<QualifiedTable> result = new LinkedList<>();
- String schemaName =
DatabaseTypeEngine.getDefaultSchemaName(databaseType, database.getName());
- for (SimpleTableSegment each : tableSegments) {
- String actualSchemaName = each.getOwner().map(optional ->
optional.getIdentifier().getValue()).orElse(schemaName);
- result.add(new QualifiedTable(actualSchemaName,
each.getTableName().getIdentifier().getValue()));
- }
- return result;
- }
-
- private boolean containsView(final ShardingSphereDatabase database, final
Collection<QualifiedTable> singleTableNames) {
- for (QualifiedTable each : singleTableNames) {
+ private boolean containsView(final ShardingSphereDatabase database, final
Collection<QualifiedTable> singleTables) {
+ for (QualifiedTable each : singleTables) {
if
(database.getSchema(each.getSchemaName()).containsView(each.getTableName())) {
return true;
}
@@ -86,26 +64,9 @@ public final class SingleSQLFederationDecider implements
SQLFederationDecider<Si
return false;
}
- private boolean isAllTablesInSameDataSource(final Collection<DataNode>
includedDataNodes, final SingleRule rule, final Collection<QualifiedTable>
singleTableNames) {
- if (!rule.isSingleTablesInSameDataSource(singleTableNames)) {
- return false;
- }
- QualifiedTable sampleTable = singleTableNames.iterator().next();
- Optional<DataNode> dataNode =
rule.findTableDataNode(sampleTable.getSchemaName(), sampleTable.getTableName());
- if (!dataNode.isPresent()) {
- return true;
- }
- for (DataNode each : includedDataNodes) {
- if
(!each.getDataSourceName().equalsIgnoreCase(dataNode.get().getDataSourceName()))
{
- return false;
- }
- }
- return true;
- }
-
- private Collection<DataNode> getTableDataNodes(final SingleRule rule,
final Collection<QualifiedTable> singleTableNames) {
+ private Collection<DataNode> getTableDataNodes(final SingleRule rule,
final Collection<QualifiedTable> singleTables) {
Collection<DataNode> result = new HashSet<>();
- for (QualifiedTable each : singleTableNames) {
+ for (QualifiedTable each : singleTables) {
rule.findTableDataNode(each.getSchemaName(),
each.getTableName()).ifPresent(result::add);
}
return result;
diff --git
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/SingleSQLRouter.java
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/SingleSQLRouter.java
index 0162f7df33a..42797b6a071 100644
---
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/SingleSQLRouter.java
+++
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/SingleSQLRouter.java
@@ -17,17 +17,12 @@
package org.apache.shardingsphere.single.route;
-import com.google.common.base.Preconditions;
import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
-import org.apache.shardingsphere.infra.binder.type.IndexAvailable;
import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
import
org.apache.shardingsphere.infra.connection.validator.ShardingSphereMetaDataValidateUtils;
-import org.apache.shardingsphere.infra.database.spi.DatabaseType;
-import org.apache.shardingsphere.infra.database.DatabaseTypeEngine;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
import org.apache.shardingsphere.infra.metadata.database.schema.QualifiedTable;
-import
org.apache.shardingsphere.infra.metadata.database.schema.util.IndexMetaDataUtils;
import org.apache.shardingsphere.infra.route.SQLRouter;
import org.apache.shardingsphere.infra.route.context.RouteContext;
import org.apache.shardingsphere.infra.route.context.RouteMapper;
@@ -36,21 +31,13 @@ import
org.apache.shardingsphere.infra.session.connection.ConnectionContext;
import org.apache.shardingsphere.infra.session.query.QueryContext;
import org.apache.shardingsphere.single.constant.SingleOrder;
import org.apache.shardingsphere.single.route.engine.SingleRouteEngineFactory;
-import
org.apache.shardingsphere.single.route.validator.SingleMetaDataValidator;
import
org.apache.shardingsphere.single.route.validator.SingleMetaDataValidatorFactory;
import org.apache.shardingsphere.single.rule.SingleRule;
-import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateTableStatement;
-import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
-import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
-import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
-import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
+import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
import java.util.Collection;
import java.util.Collections;
-import java.util.LinkedList;
-import java.util.Optional;
/**
* Single SQL router.
@@ -65,30 +52,32 @@ public final class SingleSQLRouter implements
SQLRouter<SingleRule> {
}
RouteContext result = new RouteContext();
SQLStatementContext sqlStatementContext =
queryContext.getSqlStatementContext();
- SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
- Optional<SingleMetaDataValidator> validator =
SingleMetaDataValidatorFactory.newInstance(sqlStatement);
- validator.ifPresent(optional -> optional.validate(rule,
sqlStatementContext, database));
- Collection<QualifiedTable> singleTableNames =
getSingleTableNames(sqlStatementContext, database, rule, result);
- if (!singleTableNames.isEmpty()) {
- if (sqlStatement instanceof InsertStatement || sqlStatement
instanceof DeleteStatement || sqlStatement instanceof UpdateStatement ||
sqlStatement instanceof SelectStatement) {
-
ShardingSphereMetaDataValidateUtils.validateTableExist(sqlStatementContext,
database);
- }
- validateSameDataSource(rule, singleTableNames, result);
- }
- SingleRouteEngineFactory.newInstance(singleTableNames,
sqlStatement).ifPresent(optional -> optional.route(result, rule));
+
SingleMetaDataValidatorFactory.newInstance(sqlStatementContext.getSqlStatement()).ifPresent(optional
-> optional.validate(rule, sqlStatementContext, database));
+ Collection<QualifiedTable> singleTables = getSingleTables(database,
rule, result, sqlStatementContext);
+ validateSingleTableMetaData(database, sqlStatementContext,
singleTables);
+ SingleRouteEngineFactory.newInstance(singleTables,
sqlStatementContext.getSqlStatement()).ifPresent(optional ->
optional.route(result, rule));
return result;
}
+ private void validateSingleTableMetaData(final ShardingSphereDatabase
database, final SQLStatementContext sqlStatementContext, final
Collection<QualifiedTable> singleTables) {
+ // TODO move single table metadata validate logic to infra validator
+ if (!singleTables.isEmpty() && sqlStatementContext.getSqlStatement()
instanceof DMLStatement) {
+
ShardingSphereMetaDataValidateUtils.validateTableExist(sqlStatementContext,
database);
+ }
+ }
+
+ private Collection<QualifiedTable> getSingleTables(ShardingSphereDatabase
database, SingleRule rule, RouteContext result, SQLStatementContext
sqlStatementContext) {
+ Collection<QualifiedTable> qualifiedTables =
rule.getQualifiedTables(sqlStatementContext, database);
+ return result.getRouteUnits().isEmpty() &&
sqlStatementContext.getSqlStatement() instanceof CreateTableStatement ?
qualifiedTables : rule.getSingleTables(qualifiedTables);
+ }
+
@Override
public void decorateRouteContext(final RouteContext routeContext, final
QueryContext queryContext, final ShardingSphereDatabase database,
final SingleRule rule, final
ConfigurationProperties props, final ConnectionContext connectionContext) {
SQLStatementContext sqlStatementContext =
queryContext.getSqlStatementContext();
- Collection<QualifiedTable> singleTableNames =
getSingleTableNames(sqlStatementContext, database, rule, routeContext);
- if (singleTableNames.isEmpty()) {
- return;
- }
- validateSameDataSource(rule, singleTableNames, routeContext);
- SingleRouteEngineFactory.newInstance(singleTableNames,
sqlStatementContext.getSqlStatement()).ifPresent(optional ->
optional.route(routeContext, rule));
+ Collection<QualifiedTable> singleTables = getSingleTables(database,
rule, routeContext, sqlStatementContext);
+ validateSingleTableMetaData(database, sqlStatementContext,
singleTables);
+ SingleRouteEngineFactory.newInstance(singleTables,
sqlStatementContext.getSqlStatement()).ifPresent(optional ->
optional.route(routeContext, rule));
}
private RouteContext createSingleDataSourceRouteContext(final SingleRule
rule, final ShardingSphereDatabase database) {
@@ -99,30 +88,6 @@ public final class SingleSQLRouter implements
SQLRouter<SingleRule> {
return result;
}
- private Collection<QualifiedTable> getSingleTableNames(final
SQLStatementContext sqlStatementContext,
- final
ShardingSphereDatabase database, final SingleRule rule, final RouteContext
routeContext) {
- DatabaseType databaseType = sqlStatementContext.getDatabaseType();
- Collection<QualifiedTable> result = getQualifiedTables(database,
databaseType, sqlStatementContext.getTablesContext().getSimpleTableSegments());
- if (result.isEmpty() && sqlStatementContext instanceof IndexAvailable)
{
- result = IndexMetaDataUtils.getTableNames(database, databaseType,
((IndexAvailable) sqlStatementContext).getIndexes());
- }
- return routeContext.getRouteUnits().isEmpty() &&
sqlStatementContext.getSqlStatement() instanceof CreateTableStatement ? result
: rule.getSingleTableNames(result);
- }
-
- private Collection<QualifiedTable> getQualifiedTables(final
ShardingSphereDatabase database, final DatabaseType databaseType, final
Collection<SimpleTableSegment> tableSegments) {
- Collection<QualifiedTable> result = new LinkedList<>();
- String schemaName =
DatabaseTypeEngine.getDefaultSchemaName(databaseType, database.getName());
- for (SimpleTableSegment each : tableSegments) {
- String actualSchemaName = each.getOwner().map(optional ->
optional.getIdentifier().getValue()).orElse(schemaName);
- result.add(new QualifiedTable(actualSchemaName,
each.getTableName().getIdentifier().getValue()));
- }
- return result;
- }
-
- private void validateSameDataSource(final SingleRule rule, final
Collection<QualifiedTable> singleTableNames, final RouteContext routeContext) {
-
Preconditions.checkState(rule.isAllTablesInSameDataSource(routeContext,
singleTableNames), "All tables must be in the same datasource.");
- }
-
@Override
public int getOrder() {
return SingleOrder.ORDER;
diff --git
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/engine/SingleRouteEngineFactory.java
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/engine/SingleRouteEngineFactory.java
index 01983c4501b..53eba7bbace 100644
---
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/engine/SingleRouteEngineFactory.java
+++
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/engine/SingleRouteEngineFactory.java
@@ -37,15 +37,15 @@ public final class SingleRouteEngineFactory {
/**
* Create new instance of single route engine.
*
- * @param singleTableNames single table names
+ * @param singleTables single tables
* @param sqlStatement SQL statement
* @return created instance
*/
- public static Optional<SingleRouteEngine> newInstance(final
Collection<QualifiedTable> singleTableNames, final SQLStatement sqlStatement) {
- // TODO Consider to add route logic for more statements
- if (!singleTableNames.isEmpty()) {
- return Optional.of(new SingleStandardRouteEngine(singleTableNames,
sqlStatement));
+ public static Optional<SingleRouteEngine> newInstance(final
Collection<QualifiedTable> singleTables, final SQLStatement sqlStatement) {
+ if (!singleTables.isEmpty()) {
+ return Optional.of(new SingleStandardRouteEngine(singleTables,
sqlStatement));
}
+ // TODO move this logic to common route logic
if (isSchemaDDLStatement(sqlStatement)) {
return Optional.of(new SingleDatabaseBroadcastRouteEngine());
}
diff --git
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/engine/SingleStandardRouteEngine.java
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/engine/SingleStandardRouteEngine.java
index 26cc5edb06f..adf00977f8c 100644
---
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/engine/SingleStandardRouteEngine.java
+++
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/route/engine/SingleStandardRouteEngine.java
@@ -24,17 +24,21 @@ import
org.apache.shardingsphere.infra.metadata.database.schema.QualifiedTable;
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.infra.util.exception.ShardingSpherePreconditions;
+import
org.apache.shardingsphere.infra.util.exception.external.sql.type.generic.UnsupportedSQLOperationException;
import org.apache.shardingsphere.single.exception.SingleTableNotFoundException;
import org.apache.shardingsphere.single.rule.SingleRule;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.AlterTableStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateTableStatement;
+import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropTableStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
import
org.apache.shardingsphere.sql.parser.sql.dialect.handler.ddl.CreateTableStatementHandler;
import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
@@ -47,36 +51,42 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public final class SingleStandardRouteEngine implements SingleRouteEngine {
- private final Collection<QualifiedTable> singleTableNames;
+ private final Collection<QualifiedTable> singleTables;
private final SQLStatement sqlStatement;
@Override
public void route(final RouteContext routeContext, final SingleRule
singleRule) {
if (routeContext.getRouteUnits().isEmpty() || sqlStatement instanceof
SelectStatement) {
- route0(routeContext, singleRule);
+ routeStatement(routeContext, singleRule);
} else {
RouteContext newRouteContext = new RouteContext();
- route0(newRouteContext, singleRule);
+ routeStatement(newRouteContext, singleRule);
combineRouteContext(routeContext, newRouteContext);
}
}
- private void combineRouteContext(final RouteContext routeContext, final
RouteContext newRouteContext) {
- Map<String, RouteUnit> dataSourceRouteUnits =
getDataSourceRouteUnits(newRouteContext);
- routeContext.getRouteUnits().removeIf(each ->
!dataSourceRouteUnits.containsKey(each.getDataSourceMapper().getLogicName()));
- for (Entry<String, RouteUnit> entry : dataSourceRouteUnits.entrySet())
{
- routeContext.putRouteUnit(entry.getValue().getDataSourceMapper(),
entry.getValue().getTableMappers());
+ private void routeStatement(final RouteContext routeContext, final
SingleRule rule) {
+ if (sqlStatement instanceof DDLStatement) {
+ routeDDLStatement(routeContext, rule);
+ } else {
+ boolean allTablesInSameComputeNode =
rule.isAllTablesInSameComputeNode(getDataNodes(routeContext), singleTables);
+ ShardingSpherePreconditions.checkState(allTablesInSameComputeNode,
() -> new UnsupportedSQLOperationException("all tables must be in the same
compute node"));
+ fillRouteContext(rule, routeContext, singleTables);
}
}
- private Map<String, RouteUnit> getDataSourceRouteUnits(final RouteContext
newRouteContext) {
- return
newRouteContext.getRouteUnits().stream().collect(Collectors.toMap(each ->
each.getDataSourceMapper().getLogicName(), Function.identity()));
+ private Collection<DataNode> getDataNodes(final RouteContext routeContext)
{
+ Collection<DataNode> result = new LinkedList<>();
+ for (Collection<DataNode> each : routeContext.getOriginalDataNodes()) {
+ result.addAll(each);
+ }
+ return result;
}
- private void route0(final RouteContext routeContext, final SingleRule
rule) {
+ private void routeDDLStatement(final RouteContext routeContext, final
SingleRule rule) {
if (sqlStatement instanceof CreateTableStatement) {
- QualifiedTable table = singleTableNames.iterator().next();
+ QualifiedTable table = singleTables.iterator().next();
Optional<DataNode> dataNodeOptional =
rule.findTableDataNode(table.getSchemaName(), table.getTableName());
boolean containsIfNotExists =
CreateTableStatementHandler.ifNotExists((CreateTableStatement) sqlStatement);
if (dataNodeOptional.isPresent() && containsIfNotExists) {
@@ -88,8 +98,9 @@ public final class SingleStandardRouteEngine implements
SingleRouteEngine {
String dataSourceName = rule.assignNewDataSourceName();
routeContext.getRouteUnits().add(new RouteUnit(new
RouteMapper(dataSourceName, dataSourceName), Collections.singleton(new
RouteMapper(table.getTableName(), table.getTableName()))));
}
- } else if (sqlStatement instanceof AlterTableStatement || sqlStatement
instanceof DropTableStatement || rule.isAllTablesInSameDataSource(routeContext,
singleTableNames)) {
- fillRouteContext(rule, routeContext,
rule.getSingleTableNames(singleTableNames));
+ }
+ if (sqlStatement instanceof AlterTableStatement || sqlStatement
instanceof DropTableStatement) {
+ fillRouteContext(rule, routeContext, singleTables);
}
}
@@ -104,4 +115,16 @@ public final class SingleStandardRouteEngine implements
SingleRouteEngine {
routeContext.putRouteUnit(new RouteMapper(dataSource, dataSource),
Collections.singletonList(new RouteMapper(tableName, tableName)));
}
}
+
+ private void combineRouteContext(final RouteContext routeContext, final
RouteContext newRouteContext) {
+ Map<String, RouteUnit> dataSourceRouteUnits =
getDataSourceRouteUnits(newRouteContext);
+ routeContext.getRouteUnits().removeIf(each ->
!dataSourceRouteUnits.containsKey(each.getDataSourceMapper().getLogicName()));
+ for (Entry<String, RouteUnit> entry : dataSourceRouteUnits.entrySet())
{
+ routeContext.putRouteUnit(entry.getValue().getDataSourceMapper(),
entry.getValue().getTableMappers());
+ }
+ }
+
+ private Map<String, RouteUnit> getDataSourceRouteUnits(final RouteContext
newRouteContext) {
+ return
newRouteContext.getRouteUnits().stream().collect(Collectors.toMap(each ->
each.getDataSourceMapper().getLogicName(), Function.identity()));
+ }
}
diff --git
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/rule/SingleRule.java
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/rule/SingleRule.java
index 67af6345e08..065e2e78be9 100644
---
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/rule/SingleRule.java
+++
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/rule/SingleRule.java
@@ -18,14 +18,16 @@
package org.apache.shardingsphere.single.rule;
import lombok.Getter;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.binder.type.IndexAvailable;
import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
import org.apache.shardingsphere.infra.database.DatabaseTypeEngine;
import org.apache.shardingsphere.infra.database.spi.DatabaseType;
import org.apache.shardingsphere.infra.datanode.DataNode;
import org.apache.shardingsphere.infra.datasource.state.DataSourceStateManager;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.metadata.database.schema.QualifiedTable;
-import org.apache.shardingsphere.infra.route.context.RouteContext;
-import org.apache.shardingsphere.infra.route.context.RouteUnit;
+import
org.apache.shardingsphere.infra.metadata.database.schema.util.IndexMetaDataUtils;
import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
import org.apache.shardingsphere.infra.rule.identifier.scope.DatabaseRule;
import
org.apache.shardingsphere.infra.rule.identifier.type.DataNodeContainedRule;
@@ -37,6 +39,7 @@ import
org.apache.shardingsphere.infra.rule.identifier.type.exportable.constant.
import org.apache.shardingsphere.single.api.config.SingleRuleConfiguration;
import org.apache.shardingsphere.single.datanode.SingleTableDataNodeLoader;
import org.apache.shardingsphere.single.util.SingleTableLoadUtils;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
import javax.sql.DataSource;
import java.util.ArrayList;
@@ -90,14 +93,31 @@ public final class SingleRule implements DatabaseRule,
DataNodeContainedRule, Ta
}
/**
- * Judge whether single tables are in same data source or not.
- *
- * @param singleTableNames single table names
- * @return whether single tables are in same data source or not
+ * Judge whether all tables are in same compute node or not.
+ *
+ * @param dataNodes data nodes
+ * @param singleTables single tables
+ * @return whether all tables are in same compute node or not
*/
- public boolean isSingleTablesInSameDataSource(final
Collection<QualifiedTable> singleTableNames) {
+ public boolean isAllTablesInSameComputeNode(final Collection<DataNode>
dataNodes, final Collection<QualifiedTable> singleTables) {
+ if (!isSingleTablesInSameComputeNode(singleTables)) {
+ return false;
+ }
+ QualifiedTable sampleTable = singleTables.iterator().next();
+ Optional<DataNode> dataNode =
findTableDataNode(sampleTable.getSchemaName(), sampleTable.getTableName());
+ if (dataNode.isPresent()) {
+ for (DataNode each : dataNodes) {
+ if
(!each.getDataSourceName().equalsIgnoreCase(dataNode.get().getDataSourceName()))
{
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean isSingleTablesInSameComputeNode(final
Collection<QualifiedTable> singleTables) {
String firstFoundDataSourceName = null;
- for (QualifiedTable each : singleTableNames) {
+ for (QualifiedTable each : singleTables) {
Optional<DataNode> dataNode =
findTableDataNode(each.getSchemaName(), each.getTableName());
if (!dataNode.isPresent()) {
continue;
@@ -113,36 +133,13 @@ public final class SingleRule implements DatabaseRule,
DataNodeContainedRule, Ta
return true;
}
- /**
- * Judge whether all tables are in same data source or not.
- *
- * @param routeContext route context
- * @param singleTableNames single table names
- * @return whether all tables are in same data source or not
- */
- public boolean isAllTablesInSameDataSource(final RouteContext
routeContext, final Collection<QualifiedTable> singleTableNames) {
- if (!isSingleTablesInSameDataSource(singleTableNames)) {
- return false;
- }
- QualifiedTable sampleTable = singleTableNames.iterator().next();
- Optional<DataNode> dataNode =
findTableDataNode(sampleTable.getSchemaName(), sampleTable.getTableName());
- if (dataNode.isPresent()) {
- for (RouteUnit each : routeContext.getRouteUnits()) {
- if
(!each.getDataSourceMapper().getLogicName().equals(dataNode.get().getDataSourceName()))
{
- return false;
- }
- }
- }
- return true;
- }
-
/**
* Get single table names.
*
* @param qualifiedTables qualified tables
* @return single table names
*/
- public Collection<QualifiedTable> getSingleTableNames(final
Collection<QualifiedTable> qualifiedTables) {
+ public Collection<QualifiedTable> getSingleTables(final
Collection<QualifiedTable> qualifiedTables) {
Collection<QualifiedTable> result = new LinkedList<>();
for (QualifiedTable each : qualifiedTables) {
Collection<DataNode> dataNodes =
singleTableDataNodes.getOrDefault(each.getTableName().toLowerCase(), new
LinkedList<>());
@@ -162,6 +159,31 @@ public final class SingleRule implements DatabaseRule,
DataNodeContainedRule, Ta
return false;
}
+ /**
+ * Get qualified tables.
+ *
+ * @param sqlStatementContext sql statement context
+ * @param database database
+ * @return qualified tables
+ */
+ public Collection<QualifiedTable> getQualifiedTables(final
SQLStatementContext sqlStatementContext, final ShardingSphereDatabase database)
{
+ Collection<QualifiedTable> result = getQualifiedTables(database,
databaseType, sqlStatementContext.getTablesContext().getSimpleTableSegments());
+ if (result.isEmpty() && sqlStatementContext instanceof IndexAvailable)
{
+ result = IndexMetaDataUtils.getTableNames(database, databaseType,
((IndexAvailable) sqlStatementContext).getIndexes());
+ }
+ return result;
+ }
+
+ private Collection<QualifiedTable> getQualifiedTables(final
ShardingSphereDatabase database, final DatabaseType databaseType, final
Collection<SimpleTableSegment> tableSegments) {
+ Collection<QualifiedTable> result = new LinkedList<>();
+ String schemaName =
DatabaseTypeEngine.getDefaultSchemaName(databaseType, database.getName());
+ for (SimpleTableSegment each : tableSegments) {
+ String actualSchemaName = each.getOwner().map(optional ->
optional.getIdentifier().getValue()).orElse(schemaName);
+ result.add(new QualifiedTable(actualSchemaName,
each.getTableName().getIdentifier().getValue()));
+ }
+ return result;
+ }
+
@Override
public void put(final String dataSourceName, final String schemaName,
final String tableName) {
if (dataSourceNames.contains(dataSourceName)) {
diff --git
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/decider/SingleSQLFederationDeciderTest.java
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/decider/SingleSQLFederationDeciderTest.java
index f1061f24699..ddc20fb0ca2 100644
---
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/decider/SingleSQLFederationDeciderTest.java
+++
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/decider/SingleSQLFederationDeciderTest.java
@@ -54,52 +54,52 @@ class SingleSQLFederationDeciderTest {
}
@Test
- void assertDecideWhenAllSingleTablesInSameDataSource() {
+ void assertDecideWhenAllSingleTablesInSameComputeNode() {
Collection<QualifiedTable> qualifiedTables = Arrays.asList(new
QualifiedTable(DefaultDatabase.LOGIC_NAME, "t_order"), new
QualifiedTable(DefaultDatabase.LOGIC_NAME, "t_order_item"));
SingleRule rule = createSingleRule(qualifiedTables);
-
when(rule.isSingleTablesInSameDataSource(qualifiedTables)).thenReturn(true);
SelectStatementContext select = createStatementContext();
Collection<DataNode> includedDataNodes = new HashSet<>();
+ when(rule.isAllTablesInSameComputeNode(includedDataNodes,
qualifiedTables)).thenReturn(true);
assertFalse(new SingleSQLFederationDecider().decide(select,
Collections.emptyList(), mock(ShardingSphereRuleMetaData.class),
createDatabase(), rule, includedDataNodes));
assertThat(includedDataNodes.size(), is(2));
}
@Test
- void assertDecideWhenAllSingleTablesNotInSameDataSource() {
+ void assertDecideWhenAllSingleTablesNotInSameComputeNode() {
Collection<QualifiedTable> qualifiedTables = Arrays.asList(new
QualifiedTable(DefaultDatabase.LOGIC_NAME, "t_order"), new
QualifiedTable(DefaultDatabase.LOGIC_NAME, "t_order_item"));
SingleRule rule = createSingleRule(qualifiedTables);
-
when(rule.isSingleTablesInSameDataSource(qualifiedTables)).thenReturn(false);
SelectStatementContext select = createStatementContext();
Collection<DataNode> includedDataNodes = new HashSet<>();
+ when(rule.isAllTablesInSameComputeNode(includedDataNodes,
qualifiedTables)).thenReturn(false);
assertTrue(new SingleSQLFederationDecider().decide(select,
Collections.emptyList(), mock(ShardingSphereRuleMetaData.class),
createDatabase(), rule, includedDataNodes));
assertThat(includedDataNodes.size(), is(2));
}
@Test
- void assertDecideWhenAllTablesInSameDataSource() {
+ void assertDecideWhenAllTablesInSameComputeNode() {
Collection<QualifiedTable> qualifiedTables = Arrays.asList(new
QualifiedTable(DefaultDatabase.LOGIC_NAME, "t_order"), new
QualifiedTable(DefaultDatabase.LOGIC_NAME, "t_order_item"));
SingleRule rule = createSingleRule(qualifiedTables);
-
when(rule.isSingleTablesInSameDataSource(qualifiedTables)).thenReturn(true);
SelectStatementContext select = createStatementContext();
Collection<DataNode> includedDataNodes = new
HashSet<>(Collections.singleton(new DataNode("ds_0", "t_user")));
+ when(rule.isAllTablesInSameComputeNode(includedDataNodes,
qualifiedTables)).thenReturn(true);
assertFalse(new SingleSQLFederationDecider().decide(select,
Collections.emptyList(), mock(ShardingSphereRuleMetaData.class),
createDatabase(), rule, includedDataNodes));
assertThat(includedDataNodes.size(), is(3));
}
@Test
- void assertDecideWhenAllTablesNotInSameDataSource() {
+ void assertDecideWhenAllTablesNotInSameComputeNode() {
Collection<QualifiedTable> qualifiedTables = Arrays.asList(new
QualifiedTable(DefaultDatabase.LOGIC_NAME, "t_order"), new
QualifiedTable(DefaultDatabase.LOGIC_NAME, "t_order_item"));
SingleRule rule = createSingleRule(qualifiedTables);
-
when(rule.isSingleTablesInSameDataSource(qualifiedTables)).thenReturn(true);
SelectStatementContext select = createStatementContext();
Collection<DataNode> includedDataNodes = new
HashSet<>(Collections.singleton(new DataNode("ds_1", "t_user")));
+ when(rule.isAllTablesInSameComputeNode(includedDataNodes,
qualifiedTables)).thenReturn(false);
assertTrue(new SingleSQLFederationDecider().decide(select,
Collections.emptyList(), mock(ShardingSphereRuleMetaData.class),
createDatabase(), rule, includedDataNodes));
assertThat(includedDataNodes.size(), is(3));
}
private SingleRule createSingleRule(final Collection<QualifiedTable>
qualifiedTables) {
SingleRule result = mock(SingleRule.class);
- when(result.getSingleTableNames(any())).thenReturn(qualifiedTables);
+ when(result.getSingleTables(any())).thenReturn(qualifiedTables);
when(result.findTableDataNode(DefaultDatabase.LOGIC_NAME,
"t_order")).thenReturn(Optional.of(new DataNode("ds_0", "t_order")));
when(result.findTableDataNode(DefaultDatabase.LOGIC_NAME,
"t_order_item")).thenReturn(Optional.of(new DataNode("ds_0", "t_order_item")));
return result;
diff --git
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/route/engine/SingleRouteEngineFactoryTest.java
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/route/engine/SingleRouteEngineFactoryTest.java
index 35fe287b8bb..475563975ec 100644
---
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/route/engine/SingleRouteEngineFactoryTest.java
+++
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/route/engine/SingleRouteEngineFactoryTest.java
@@ -33,7 +33,7 @@ import static org.mockito.Mockito.mock;
class SingleRouteEngineFactoryTest {
@Test
- void assertNewInstanceWithNotEmptySingleTableNames() {
+ void assertNewInstanceWithNotEmptySingleTables() {
assertTrue(SingleRouteEngineFactory.newInstance(Collections.singleton(new
QualifiedTable("demo_ds", "t_order")), mock(SQLStatement.class)).isPresent());
}
diff --git
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/rule/SingleRuleTest.java
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/rule/SingleRuleTest.java
index 7af2dc3ca48..7bb44fbce66 100644
---
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/rule/SingleRuleTest.java
+++
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/rule/SingleRuleTest.java
@@ -141,19 +141,10 @@ class SingleRuleTest {
assertThat(actual.get().getTableName(), is("employee"));
}
- @Test
- void assertIsSingleTablesInSameDataSource() {
- DataNodeContainedRule dataNodeContainedRule =
mock(DataNodeContainedRule.class);
- SingleRule singleRule = new SingleRule(ruleConfig,
DefaultDatabase.LOGIC_NAME, dataSourceMap,
Collections.singleton(dataNodeContainedRule));
- Collection<QualifiedTable> singleTableNames = new LinkedList<>();
- singleTableNames.add(new QualifiedTable(DefaultDatabase.LOGIC_NAME,
"employee"));
-
assertTrue(singleRule.isSingleTablesInSameDataSource(singleTableNames));
- }
-
@Test
void assertIsAllTablesInSameDataSource() {
- Collection<QualifiedTable> singleTableNames = new LinkedList<>();
- singleTableNames.add(new QualifiedTable(DefaultDatabase.LOGIC_NAME,
"employee"));
+ Collection<QualifiedTable> singleTables = new LinkedList<>();
+ singleTables.add(new QualifiedTable(DefaultDatabase.LOGIC_NAME,
"employee"));
RouteMapper dataSourceMapper = new RouteMapper("foo_ds", null);
Collection<RouteMapper> tableMappers = new LinkedList<>();
tableMappers.add(dataSourceMapper);
@@ -161,7 +152,7 @@ class SingleRuleTest {
routeContext.putRouteUnit(dataSourceMapper, tableMappers);
DataNodeContainedRule dataNodeContainedRule =
mock(DataNodeContainedRule.class);
SingleRule singleRule = new SingleRule(ruleConfig,
DefaultDatabase.LOGIC_NAME, dataSourceMap,
Collections.singleton(dataNodeContainedRule));
- assertTrue(singleRule.isAllTablesInSameDataSource(routeContext,
singleTableNames));
+
assertTrue(singleRule.isAllTablesInSameComputeNode(routeContext.getOriginalDataNodes().stream().flatMap(Collection::stream).collect(Collectors.toList()),
singleTables));
}
@Test
@@ -174,13 +165,13 @@ class SingleRuleTest {
}
@Test
- void assertGetSingleTableNames() {
+ void assertGetSingleTables() {
DataNodeContainedRule dataNodeContainedRule =
mock(DataNodeContainedRule.class);
SingleRule singleRule = new SingleRule(ruleConfig,
DefaultDatabase.LOGIC_NAME, dataSourceMap,
Collections.singleton(dataNodeContainedRule));
Collection<QualifiedTable> tableNames = new LinkedList<>();
tableNames.add(new QualifiedTable(DefaultDatabase.LOGIC_NAME,
"employee"));
-
assertThat(singleRule.getSingleTableNames(tableNames).iterator().next().getSchemaName(),
is(DefaultDatabase.LOGIC_NAME));
-
assertThat(singleRule.getSingleTableNames(tableNames).iterator().next().getTableName(),
is("employee"));
+
assertThat(singleRule.getSingleTables(tableNames).iterator().next().getSchemaName(),
is(DefaultDatabase.LOGIC_NAME));
+
assertThat(singleRule.getSingleTables(tableNames).iterator().next().getTableName(),
is("employee"));
}
@Test
@@ -192,8 +183,8 @@ class SingleRuleTest {
singleRule.put(dataSourceName, DefaultDatabase.LOGIC_NAME, tableName);
Collection<QualifiedTable> tableNames = new LinkedList<>();
tableNames.add(new QualifiedTable(DefaultDatabase.LOGIC_NAME,
"teacher"));
-
assertThat(singleRule.getSingleTableNames(tableNames).iterator().next().getSchemaName(),
is(DefaultDatabase.LOGIC_NAME));
-
assertThat(singleRule.getSingleTableNames(tableNames).iterator().next().getTableName(),
is("teacher"));
+
assertThat(singleRule.getSingleTables(tableNames).iterator().next().getSchemaName(),
is(DefaultDatabase.LOGIC_NAME));
+
assertThat(singleRule.getSingleTables(tableNames).iterator().next().getTableName(),
is("teacher"));
assertTrue(singleRule.getLogicTableMapper().contains("employee"));
assertTrue(singleRule.getLogicTableMapper().contains("student"));
assertTrue(singleRule.getLogicTableMapper().contains("t_order_0"));
@@ -209,7 +200,7 @@ class SingleRuleTest {
singleRule.remove(DefaultDatabase.LOGIC_NAME, tableName);
Collection<QualifiedTable> tableNames = new LinkedList<>();
tableNames.add(new QualifiedTable(DefaultDatabase.LOGIC_NAME,
"employee"));
- assertTrue(singleRule.getSingleTableNames(tableNames).isEmpty());
+ assertTrue(singleRule.getSingleTables(tableNames).isEmpty());
assertTrue(singleRule.getLogicTableMapper().contains("student"));
assertTrue(singleRule.getLogicTableMapper().contains("t_order_0"));
assertTrue(singleRule.getLogicTableMapper().contains("t_order_1"));
diff --git
a/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/query/ShowUnloadedSingleTableExecutor.java
b/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/query/ShowUnloadedSingleTableExecutor.java
index 5d5890d898c..b20a22797ef 100644
---
a/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/query/ShowUnloadedSingleTableExecutor.java
+++
b/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/query/ShowUnloadedSingleTableExecutor.java
@@ -50,8 +50,7 @@ public final class ShowUnloadedSingleTableExecutor implements
RQLExecutor<ShowUn
Map<String, Collection<DataNode>> actualDataNodes =
getActualDataNodes(database);
Optional<SingleRule> singleRule =
database.getRuleMetaData().findSingleRule(SingleRule.class);
if (singleRule.isPresent()) {
- Collection<String> singleTableNames =
singleRule.get().getLogicTableMapper().getTableNames();
- for (String each : singleTableNames) {
+ for (String each :
singleRule.get().getLogicTableMapper().getTableNames()) {
actualDataNodes.remove(each);
}
}