ShadowSQLRouter implements SQLRouter<ShadowRule> { @Override public void decorateRouteContext(final RouteContext routeContext, final LogicSQL logicSQL, final ShadowRule rule, final ConfigurationProperties props) { Collection<RouteUnit> toBeAdded = new LinkedList<>(); if (!(logicSQL.getSqlStatementContext().getSqlStatement() instanceof DMLStatement)) { for (RouteUnit each : routeContext.getRouteUnits()) { String shadowDataSourceName = rule.getShadowMappings().get(each.getDataSourceMapper().getActualName()); toBeAdded.add(new RouteUnit(new RouteMapper(each.getDataSourceMapper().getLogicName(), shadowDataSourceName), each.getTableMappers())); } routeContext.getRouteUnits().addAll(toBeAdded); return; } Collection<RouteUnit> toBeRemoved = new LinkedList<>(); if (isShadow(logicSQL.getSqlStatementContext(), logicSQL.getParameters(), rule)) { for (RouteUnit each : routeContext.getRouteUnits()) { toBeRemoved.add(each); String shadowDataSourceName = rule.getShadowMappings().get(each.getDataSourceMapper().getActualName()); toBeAdded.add(new RouteUnit(new RouteMapper(each.getDataSourceMapper().getLogicName(), shadowDataSourceName), each.getTableMappers())); } } routeContext.getRouteUnits().removeAll(toBeRemoved); routeContext.getRouteUnits().addAll(toBeAdded); }  @Override RouteContext createRouteContext(final LogicSQL logicSQL, final ShadowRule rule, final ConfigurationProperties props); @Override void decorateRouteContext(final RouteContext routeContext, final LogicSQL logicSQL, final ShadowRule rule, final ConfigurationProperties props); @Override int getOrder(); @Override Class<ShadowRule> getTypeClass();  }
@Test public void assertDecorateRouteContextToShadowDataSource() { RouteContext actual = new RouteContext(); actual.getRouteUnits().add(mockRouteUnit()); ShardingSphereSchema schema = new ShardingSphereSchema("logic_schema", Collections.emptyList(), Collections.singleton(rule), Collections.emptyMap(), mock(ShardingSphereMetaData.class)); LogicSQL logicSQL = new LogicSQL(schema, mockSQLStatementContextForShadow(), "", Collections.emptyList()); sqlRouter.decorateRouteContext(actual, logicSQL, rule, new ConfigurationProperties(new Properties())); assertThat(actual.getRouteUnits().size(), is(1)); assertTrue(actual.getActualDataSourceNames().contains(SHADOW_DATASOURCE)); }
@Test public void assertDecorateRouteContextToActualDataSource() { RouteContext actual = new RouteContext(); actual.getRouteUnits().add(mockRouteUnit()); ShardingSphereSchema schema = new ShardingSphereSchema("logic_schema", Collections.emptyList(), Collections.singleton(rule), Collections.emptyMap(), mock(ShardingSphereMetaData.class)); LogicSQL logicSQL = new LogicSQL(schema, mockSQLStatementContext(), "", Collections.emptyList()); sqlRouter.decorateRouteContext(actual, logicSQL, rule, new ConfigurationProperties(new Properties())); Iterator<String> routedDataSourceNames = actual.getActualDataSourceNames().iterator(); assertThat(routedDataSourceNames.next(), is(ACTUAL_DATASOURCE)); }
@Test public void assertDecorateRouteContextNonDMLStatement() { RouteContext actual = new RouteContext(); actual.getRouteUnits().add(mockRouteUnit()); ShardingSphereSchema schema = new ShardingSphereSchema("logic_schema", Collections.emptyList(), Collections.singleton(rule), Collections.emptyMap(), mock(ShardingSphereMetaData.class)); LogicSQL logicSQL = new LogicSQL(schema, mockNonDMLSQLStatementContext(), "", Collections.emptyList()); sqlRouter.decorateRouteContext(actual, logicSQL, rule, new ConfigurationProperties(new Properties())); assertThat(actual.getRouteUnits().size(), is(2)); assertTrue(actual.getActualDataSourceNames().contains(SHADOW_DATASOURCE)); assertTrue(actual.getActualDataSourceNames().contains(ACTUAL_DATASOURCE)); }
@Test public void assertDecorateRouteContextWithTableMapper() { RouteContext actual = new RouteContext(); actual.getRouteUnits().add(mockRouteUnit()); ShardingSphereSchema schema = new ShardingSphereSchema("logic_schema", Collections.emptyList(), Collections.singleton(rule), Collections.emptyMap(), mock(ShardingSphereMetaData.class)); LogicSQL logicSQL = new LogicSQL(schema, mockSQLStatementContextForShadow(), "", Collections.emptyList()); sqlRouter.decorateRouteContext(actual, logicSQL, rule, new ConfigurationProperties(new Properties())); assertThat(actual.getRouteUnits().size(), is(1)); assertTrue(actual.getActualDataSourceNames().contains(SHADOW_DATASOURCE)); Collection<RouteMapper> tableMappers = actual.getRouteUnits().iterator().next().getTableMappers(); assertThat(tableMappers.size(), is(1)); assertThat(tableMappers.iterator().next().getActualName(), is("table_0")); assertThat(tableMappers.iterator().next().getLogicName(), is("table")); }