Skip to content

Commit

Permalink
Spilt SQLRouter to EntranceSQLRouter and DecorateSQLRouter (#31962)
Browse files Browse the repository at this point in the history
* Remove useless dependencies declarations for feature pom

* Add TableAggregationSQLRouter

* Add TableAggregationSQLRouter

* Add DecorateSQLRouter

* Add DecorateSQLRouter
  • Loading branch information
terrymanu committed Jul 2, 2024
1 parent f085949 commit f1af66a
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 213 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import org.apache.shardingsphere.sql.parser.api.SQLParserEngine;
import org.apache.shardingsphere.sql.parser.api.SQLStatementVisitorEngine;
import org.apache.shardingsphere.sql.parser.core.ParseASTNode;
import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.statement.SQLStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement;

import java.util.Arrays;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
import org.apache.shardingsphere.infra.route.SQLRouter;
import org.apache.shardingsphere.infra.route.DecorateSQLRouter;
import org.apache.shardingsphere.infra.route.EntranceSQLRouter;
import org.apache.shardingsphere.infra.route.context.RouteContext;
import org.apache.shardingsphere.infra.route.context.RouteMapper;
import org.apache.shardingsphere.infra.route.context.RouteUnit;
Expand Down Expand Up @@ -61,7 +62,7 @@
* Broadcast SQL router.
*/
@HighFrequencyInvocation
public final class BroadcastSQLRouter implements SQLRouter<BroadcastRule> {
public final class BroadcastSQLRouter implements EntranceSQLRouter<BroadcastRule>, DecorateSQLRouter<BroadcastRule> {

@Override
public RouteContext createRouteContext(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation;
import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
import org.apache.shardingsphere.infra.route.SQLRouter;
import org.apache.shardingsphere.infra.route.DecorateSQLRouter;
import org.apache.shardingsphere.infra.route.context.RouteContext;
import org.apache.shardingsphere.infra.route.context.RouteMapper;
import org.apache.shardingsphere.infra.route.context.RouteUnit;
Expand All @@ -32,25 +31,14 @@
import org.apache.shardingsphere.readwritesplitting.rule.ReadwriteSplittingRule;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Optional;

/**
* Readwrite-splitting SQL router.
*/
@HighFrequencyInvocation
public final class ReadwriteSplittingSQLRouter implements SQLRouter<ReadwriteSplittingRule> {

@Override
public RouteContext createRouteContext(final QueryContext queryContext, final RuleMetaData globalRuleMetaData,
final ShardingSphereDatabase database, final ReadwriteSplittingRule rule, final ConfigurationProperties props, final ConnectionContext connectionContext) {
RouteContext result = new RouteContext();
ReadwriteSplittingDataSourceGroupRule dataSourceGroupRule = rule.getSingleDataSourceGroupRule();
String dataSourceName = new ReadwriteSplittingDataSourceRouter(dataSourceGroupRule, connectionContext).route(queryContext.getSqlStatementContext(), queryContext.getHintValueContext());
result.getRouteUnits().add(new RouteUnit(new RouteMapper(dataSourceGroupRule.getName(), dataSourceName), Collections.emptyList()));
return result;
}
public final class ReadwriteSplittingSQLRouter implements DecorateSQLRouter<ReadwriteSplittingRule> {

@Override
public void decorateRouteContext(final RouteContext routeContext, final QueryContext queryContext, final ShardingSphereDatabase database,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import org.apache.shardingsphere.infra.binder.context.statement.CommonSQLStatementContext;
import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
import org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
import org.apache.shardingsphere.infra.database.core.DefaultDatabase;
import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
Expand All @@ -39,9 +38,6 @@
import org.apache.shardingsphere.readwritesplitting.config.rule.ReadwriteSplittingDataSourceGroupRuleConfiguration;
import org.apache.shardingsphere.readwritesplitting.rule.ReadwriteSplittingRule;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.LockSegment;
import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.InsertStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.SelectStatement;
import org.apache.shardingsphere.sql.parser.statement.mysql.dml.MySQLInsertStatement;
import org.apache.shardingsphere.sql.parser.statement.mysql.dml.MySQLSelectStatement;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -85,22 +81,6 @@ void setUp() {
sqlRouter = (ReadwriteSplittingSQLRouter) OrderedSPILoader.getServices(SQLRouter.class, Collections.singleton(staticRule)).get(staticRule);
}

@Test
void assertCreateRouteContextToPrimaryWithoutRouteUnits() {
QueryContext queryContext = new QueryContext(mock(SQLStatementContext.class), "", Collections.emptyList(), new HintValueContext());
RuleMetaData ruleMetaData = new RuleMetaData(Collections.singleton(staticRule));
ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
mock(DatabaseType.class), mock(ResourceMetaData.class, RETURNS_DEEP_STUBS), ruleMetaData, Collections.emptyMap());
RouteContext actual = sqlRouter.createRouteContext(queryContext,
mock(RuleMetaData.class), database, staticRule, new ConfigurationProperties(new Properties()), new ConnectionContext(Collections::emptySet));
assertThat(actual.getRouteUnits().size(), is(1));
RouteUnit routeUnit = actual.getRouteUnits().iterator().next();
assertThat(routeUnit.getDataSourceMapper().getLogicName(), is(DATASOURCE_NAME));
assertThat(routeUnit.getDataSourceMapper().getActualName(), is(WRITE_DATASOURCE));
Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
assertThat(routedDataSourceNames.next(), is(WRITE_DATASOURCE));
}

@Test
void assertDecorateRouteContextToPrimaryDataSource() {
RouteContext actual = mockRouteContext();
Expand All @@ -114,25 +94,6 @@ void assertDecorateRouteContextToPrimaryDataSource() {
assertThat(routedDataSourceNames.next(), is(WRITE_DATASOURCE));
}

@Test
void assertCreateRouteContextToReplicaDataSource() {
MySQLSelectStatement selectStatement = mock(MySQLSelectStatement.class);
when(sqlStatementContext.getSqlStatement()).thenReturn(selectStatement);
when(selectStatement.getLock()).thenReturn(Optional.empty());
QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext());
RuleMetaData ruleMetaData = new RuleMetaData(Collections.singleton(staticRule));
ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
mock(DatabaseType.class), mock(ResourceMetaData.class, RETURNS_DEEP_STUBS), ruleMetaData, Collections.emptyMap());
RouteContext actual = sqlRouter.createRouteContext(queryContext,
mock(RuleMetaData.class), database, staticRule, new ConfigurationProperties(new Properties()), new ConnectionContext(Collections::emptySet));
assertThat(actual.getRouteUnits().size(), is(1));
RouteUnit routeUnit = actual.getRouteUnits().iterator().next();
assertThat(routeUnit.getDataSourceMapper().getLogicName(), is(DATASOURCE_NAME));
assertThat(routeUnit.getDataSourceMapper().getActualName(), is(READ_DATASOURCE));
Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
assertThat(routedDataSourceNames.next(), is(READ_DATASOURCE));
}

@Test
void assertDecorateRouteContextToReplicaDataSource() {
RouteContext actual = mockRouteContext();
Expand All @@ -149,21 +110,6 @@ void assertDecorateRouteContextToReplicaDataSource() {
assertThat(routedDataSourceNames.next(), is(READ_DATASOURCE));
}

@Test
void assertCreateRouteContextToPrimaryDataSourceWithLock() {
MySQLSelectStatement selectStatement = mock(MySQLSelectStatement.class);
when(sqlStatementContext.getSqlStatement()).thenReturn(selectStatement);
when(selectStatement.getLock()).thenReturn(Optional.of(mock(LockSegment.class)));
QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext());
RuleMetaData ruleMetaData = new RuleMetaData(Collections.singleton(staticRule));
ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
mock(DatabaseType.class), mock(ResourceMetaData.class, RETURNS_DEEP_STUBS), ruleMetaData, Collections.emptyMap());
RouteContext actual = sqlRouter.createRouteContext(queryContext,
mock(RuleMetaData.class), database, staticRule, new ConfigurationProperties(new Properties()), new ConnectionContext(Collections::emptySet));
Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
assertThat(routedDataSourceNames.next(), is(WRITE_DATASOURCE));
}

@Test
void assertDecorateRouteContextToPrimaryDataSourceWithLock() {
RouteContext actual = mockRouteContext();
Expand All @@ -180,59 +126,6 @@ void assertDecorateRouteContextToPrimaryDataSourceWithLock() {
assertThat(routedDataSourceNames.next(), is(WRITE_DATASOURCE));
}

@Test
void assertCreateRouteContextToPrimaryDataSource() {
when(sqlStatementContext.getSqlStatement()).thenReturn(mock(InsertStatement.class));
QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext());
RuleMetaData ruleMetaData = new RuleMetaData(Collections.singleton(staticRule));
ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
mock(DatabaseType.class), mock(ResourceMetaData.class, RETURNS_DEEP_STUBS), ruleMetaData, Collections.emptyMap());
RouteContext actual = sqlRouter.createRouteContext(queryContext,
mock(RuleMetaData.class), database, staticRule, new ConfigurationProperties(new Properties()), new ConnectionContext(Collections::emptySet));
Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
assertThat(routedDataSourceNames.next(), is(WRITE_DATASOURCE));
}

@Test
void assertCreateRouteContextToReadDataSource() {
MySQLInsertStatement insertStatement = mock(MySQLInsertStatement.class);
when(sqlStatementContext.getSqlStatement()).thenReturn(insertStatement);
QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext());
RuleMetaData ruleMetaData = new RuleMetaData(Collections.singleton(staticRule));
ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
mock(DatabaseType.class), mock(ResourceMetaData.class, RETURNS_DEEP_STUBS), ruleMetaData, Collections.emptyMap());
RouteContext actual = sqlRouter.createRouteContext(queryContext,
mock(RuleMetaData.class), database, staticRule, new ConfigurationProperties(new Properties()), new ConnectionContext(Collections::emptySet));
Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
assertThat(routedDataSourceNames.next(), is(WRITE_DATASOURCE));
MySQLSelectStatement selectStatement = mock(MySQLSelectStatement.class);
when(sqlStatementContext.getSqlStatement()).thenReturn(selectStatement);
when(selectStatement.getLock()).thenReturn(Optional.empty());
queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext());
actual = sqlRouter.createRouteContext(
queryContext, mock(RuleMetaData.class), database, staticRule, new ConfigurationProperties(new Properties()), new ConnectionContext(Collections::emptySet));
routedDataSourceNames = actual.getActualDataSourceNames().iterator();
assertThat(routedDataSourceNames.next(), is(READ_DATASOURCE));
}

@Test
void assertSqlHintRouteWriteOnly() {
SelectStatement statement = mock(SelectStatement.class);
SelectStatementContext sqlStatementContext = mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
when(sqlStatementContext.getSqlStatement()).thenReturn(statement);
HintValueContext hintValueContext = mock(HintValueContext.class);
when(hintValueContext.isWriteRouteOnly()).thenReturn(true);
when(sqlStatementContext.getProjectionsContext().isContainsLastInsertIdProjection()).thenReturn(false);
QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), hintValueContext);
RuleMetaData ruleMetaData = new RuleMetaData(Collections.singleton(staticRule));
ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
mock(DatabaseType.class), mock(ResourceMetaData.class, RETURNS_DEEP_STUBS), ruleMetaData, Collections.emptyMap());
RouteContext actual = sqlRouter.createRouteContext(queryContext,
mock(RuleMetaData.class), database, staticRule, new ConfigurationProperties(new Properties()), new ConnectionContext(Collections::emptySet));
Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator();
assertThat(routedDataSourceNames.next(), is(WRITE_DATASOURCE));
}

private RouteContext mockRouteContext() {
RouteContext result = new RouteContext();
RouteUnit routeUnit = new RouteUnit(new RouteMapper(DATASOURCE_NAME, DATASOURCE_NAME), Collections.singleton(new RouteMapper("table", "table_0")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation;
import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
import org.apache.shardingsphere.infra.route.SQLRouter;
import org.apache.shardingsphere.infra.route.DecorateSQLRouter;
import org.apache.shardingsphere.infra.route.context.RouteContext;
import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
import org.apache.shardingsphere.infra.session.query.QueryContext;
Expand All @@ -33,14 +32,7 @@
* Shadow SQL router.
*/
@HighFrequencyInvocation
public final class ShadowSQLRouter implements SQLRouter<ShadowRule> {

@Override
public RouteContext createRouteContext(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database,
final ShadowRule rule, final ConfigurationProperties props, final ConnectionContext connectionContext) {
// TODO
return new RouteContext();
}
public final class ShadowSQLRouter implements DecorateSQLRouter<ShadowRule> {

@Override
public void decorateRouteContext(final RouteContext routeContext, final QueryContext queryContext, final ShardingSphereDatabase database,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
import org.apache.shardingsphere.infra.route.SQLRouter;
import org.apache.shardingsphere.infra.route.EntranceSQLRouter;
import org.apache.shardingsphere.infra.route.context.RouteContext;
import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
import org.apache.shardingsphere.infra.session.query.QueryContext;
Expand All @@ -46,7 +46,7 @@
* Sharding SQL router.
*/
@HighFrequencyInvocation
public final class ShardingSQLRouter implements SQLRouter<ShardingRule> {
public final class ShardingSQLRouter implements EntranceSQLRouter<ShardingRule> {

@Override
public RouteContext createRouteContext(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database, final ShardingRule rule,
Expand Down Expand Up @@ -86,12 +86,6 @@ private ShardingConditions createShardingConditions(final QueryContext queryCont
return new ShardingConditions(shardingConditions, queryContext.getSqlStatementContext(), rule);
}

@Override
public void decorateRouteContext(final RouteContext routeContext, final QueryContext queryContext, final ShardingSphereDatabase database, final ShardingRule rule,
final ConfigurationProperties props, final ConnectionContext connectionContext) {
// TODO
}

@Override
public int getOrder() {
return ShardingOrder.ORDER;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,31 @@
* limitations under the License.
*/

package org.apache.shardingsphere.shadow.route;
package org.apache.shardingsphere.infra.route;

import org.apache.shardingsphere.infra.session.query.QueryContext;
import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
import org.apache.shardingsphere.shadow.rule.ShadowRule;
import org.junit.jupiter.api.Test;

import java.util.Collections;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.mock;
import org.apache.shardingsphere.infra.route.context.RouteContext;
import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
import org.apache.shardingsphere.infra.session.query.QueryContext;

class ShadowSQLRouterTest {
/**
* Decorate SQL Router.
*
* @param <T> type of rule
*/
public interface DecorateSQLRouter<T extends ShardingSphereRule> extends SQLRouter<T> {

@Test
void assertCreateRouteContext() {
assertNotNull(new ShadowSQLRouter().createRouteContext(mock(QueryContext.class),
mock(RuleMetaData.class), mock(ShardingSphereDatabase.class), mock(ShadowRule.class), mock(ConfigurationProperties.class), new ConnectionContext(Collections::emptySet)));
}
/**
* Decorate route context.
*
* @param routeContext route context
* @param queryContext query context
* @param database database
* @param rule rule
* @param props configuration properties
* @param connectionContext connection context
*/
void decorateRouteContext(RouteContext routeContext, QueryContext queryContext, ShardingSphereDatabase database, T rule, ConfigurationProperties props, ConnectionContext connectionContext);
}
Loading

0 comments on commit f1af66a

Please sign in to comment.