From 00e067d7b951bdd985eca7955c7617cc91c836a4 Mon Sep 17 00:00:00 2001 From: Haoran Meng Date: Mon, 6 Dec 2021 18:31:13 +0800 Subject: [PATCH] Refactor meta data refresher with spi for DDL (#13947) Co-authored-by: shardingsphere --- .../refresher/MetaDataRefreshEngine.java | 29 +++---- .../context/refresher/MetaDataRefresher.java | 47 +++++++++++ .../AlterIndexStatementSchemaRefresher.java | 67 +++++++++++++++ .../AlterTableStatementSchemaRefresher.java | 81 ++++++++++++++++++ .../CreateIndexStatementSchemaRefresher.java | 52 ++++++++++++ .../CreateTableStatementSchemaRefresher.java | 65 +++++++++++++++ .../CreateViewStatementSchemaRefresher.java | 56 +++++++++++++ .../DropIndexStatementSchemaRefresher.java | 82 +++++++++++++++++++ .../DropTableStatementSchemaRefresher.java | 53 ++++++++++++ .../DropViewStatementSchemaRefresher.java | 50 +++++++++++ ....infra.context.refresher.MetaDataRefresher | 25 ++++++ 11 files changed, 588 insertions(+), 19 deletions(-) create mode 100644 shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/MetaDataRefresher.java create mode 100644 shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/AlterIndexStatementSchemaRefresher.java create mode 100644 shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/AlterTableStatementSchemaRefresher.java create mode 100644 shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateIndexStatementSchemaRefresher.java create mode 100644 shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateTableStatementSchemaRefresher.java create mode 100644 shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateViewStatementSchemaRefresher.java create mode 100644 shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropIndexStatementSchemaRefresher.java create mode 100644 shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropTableStatementSchemaRefresher.java create mode 100644 shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropViewStatementSchemaRefresher.java create mode 100644 shardingsphere-infra/shardingsphere-infra-context/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/MetaDataRefreshEngine.java b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/MetaDataRefreshEngine.java index 5befbfed5fe3a..ae5d87755131d 100644 --- a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/MetaDataRefreshEngine.java +++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/MetaDataRefreshEngine.java @@ -21,17 +21,16 @@ import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties; import org.apache.shardingsphere.infra.eventbus.ShardingSphereEventBus; import org.apache.shardingsphere.infra.federation.optimizer.metadata.FederationSchemaMetaData; -import org.apache.shardingsphere.infra.federation.optimizer.metadata.refresher.FederationMetaDataRefresher; -import org.apache.shardingsphere.infra.metadata.MetaDataRefresher; import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; import org.apache.shardingsphere.infra.metadata.mapper.SQLStatementEventMapper; import org.apache.shardingsphere.infra.metadata.mapper.SQLStatementEventMapperFactory; import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema; import org.apache.shardingsphere.infra.metadata.schema.loader.SchemaLoader; -import org.apache.shardingsphere.infra.metadata.schema.refresher.SchemaRefresher; import org.apache.shardingsphere.infra.metadata.schema.refresher.event.SchemaAlteredEvent; import org.apache.shardingsphere.infra.rule.ShardingSphereRule; import org.apache.shardingsphere.infra.rule.builder.schema.SchemaRulesBuilder; +import org.apache.shardingsphere.spi.ShardingSphereServiceLoader; +import org.apache.shardingsphere.spi.typed.TypedSPIRegistry; import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement; import javax.sql.DataSource; @@ -46,6 +45,10 @@ */ public final class MetaDataRefreshEngine { + static { + ShardingSphereServiceLoader.register(MetaDataRefresher.class); + } + private final ShardingSphereMetaData schemaMetaData; private final FederationSchemaMetaData federationMetaData; @@ -66,9 +69,10 @@ public MetaDataRefreshEngine(final ShardingSphereMetaData schemaMetaData, final * @throws SQLException SQL exception */ public void refresh(final SQLStatement sqlStatement, final Collection logicDataSourceNames) throws SQLException { - Collection metaDataRefreshers = MetaDataRefresherFactory.newInstance(sqlStatement); - if (!metaDataRefreshers.isEmpty()) { - refresh(sqlStatement, logicDataSourceNames, metaDataRefreshers); + Optional schemaRefresher = TypedSPIRegistry.findRegisteredService(MetaDataRefresher.class, sqlStatement.getClass().getSuperclass().getCanonicalName(), null); + if (schemaRefresher.isPresent()) { + schemaRefresher.get().refresh(schemaMetaData, federationMetaData, logicDataSourceNames, sqlStatement, props); + ShardingSphereEventBus.getInstance().post(new SchemaAlteredEvent(schemaMetaData.getName(), loadActualSchema(schemaMetaData))); } Optional sqlStatementEventMapper = SQLStatementEventMapperFactory.newInstance(sqlStatement); if (sqlStatementEventMapper.isPresent()) { @@ -77,19 +81,6 @@ public void refresh(final SQLStatement sqlStatement, final Collection lo } } - @SuppressWarnings({"unchecked", "rawtypes"}) - private void refresh(final SQLStatement sqlStatement, final Collection logicDataSourceNames, final Collection refreshers) throws SQLException { - for (MetaDataRefresher each : refreshers) { - if (each instanceof SchemaRefresher) { - ((SchemaRefresher) each).refresh(schemaMetaData, logicDataSourceNames, sqlStatement, props); - } - if (each instanceof FederationMetaDataRefresher) { - ((FederationMetaDataRefresher) each).refresh(federationMetaData, logicDataSourceNames, sqlStatement, schemaMetaData, props); - } - } - ShardingSphereEventBus.getInstance().post(new SchemaAlteredEvent(schemaMetaData.getName(), loadActualSchema(schemaMetaData))); - } - private ShardingSphereSchema loadActualSchema(final ShardingSphereMetaData schemaMetaData) throws SQLException { Map> dataSourcesMap = Collections.singletonMap(schemaMetaData.getName(), schemaMetaData.getResource().getDataSources()); Map> schemaRuleConfigs = Collections.singletonMap(schemaMetaData.getName(), schemaMetaData.getRuleMetaData().getConfigurations()); diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/MetaDataRefresher.java b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/MetaDataRefresher.java new file mode 100644 index 0000000000000..7c21d25c5d5a8 --- /dev/null +++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/MetaDataRefresher.java @@ -0,0 +1,47 @@ +/* + * 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.context.refresher; + +import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties; +import org.apache.shardingsphere.infra.federation.optimizer.metadata.FederationSchemaMetaData; +import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; +import org.apache.shardingsphere.spi.typed.TypedSPI; +import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement; + +import java.sql.SQLException; +import java.util.Collection; + +/** + * ShardingSphere schema refresher. + * + * @param type of SQL statement + */ +public interface MetaDataRefresher extends TypedSPI { + + /** + * Refresh ShardingSphere schema. + * + * @param schemaMetaData schema meta data + * @param schema federation schema meta data + * @param logicDataSourceNames route data source names + * @param sqlStatement SQL statement + * @param props configuration properties + * @throws SQLException SQL exception + */ + void refresh(ShardingSphereMetaData schemaMetaData, FederationSchemaMetaData schema, Collection logicDataSourceNames, T sqlStatement, ConfigurationProperties props) throws SQLException; +} diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/AlterIndexStatementSchemaRefresher.java b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/AlterIndexStatementSchemaRefresher.java new file mode 100644 index 0000000000000..e50b9d4400ced --- /dev/null +++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/AlterIndexStatementSchemaRefresher.java @@ -0,0 +1,67 @@ +/* + * 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.context.refresher.type; + +import com.google.common.base.Preconditions; +import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties; +import org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher; +import org.apache.shardingsphere.infra.federation.optimizer.metadata.FederationSchemaMetaData; +import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; +import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema; +import org.apache.shardingsphere.infra.metadata.schema.model.IndexMetaData; +import org.apache.shardingsphere.infra.metadata.schema.model.TableMetaData; +import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment; +import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.AlterIndexStatement; +import org.apache.shardingsphere.sql.parser.sql.dialect.handler.ddl.AlterIndexStatementHandler; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.Optional; + +/** + * Schema refresher for alter index statement. + */ +public final class AlterIndexStatementSchemaRefresher implements MetaDataRefresher { + + @Override + public void refresh(final ShardingSphereMetaData schemaMetaData, final FederationSchemaMetaData schema, final Collection logicDataSourceNames, final AlterIndexStatement sqlStatement, + final ConfigurationProperties props) throws SQLException { + Optional renameIndex = AlterIndexStatementHandler.getRenameIndexSegment(sqlStatement); + if (!sqlStatement.getIndex().isPresent() || !renameIndex.isPresent()) { + return; + } + String indexName = sqlStatement.getIndex().get().getIdentifier().getValue(); + Optional logicTableName = findLogicTableName(schemaMetaData.getSchema(), indexName); + if (logicTableName.isPresent()) { + TableMetaData tableMetaData = schemaMetaData.getSchema().get(logicTableName.get()); + Preconditions.checkNotNull(tableMetaData, "Can not get the table '%s' metadata!", logicTableName.get()); + tableMetaData.getIndexes().remove(indexName); + String renameIndexName = renameIndex.get().getIdentifier().getValue(); + tableMetaData.getIndexes().put(renameIndexName, new IndexMetaData(renameIndexName)); + } + } + + private Optional findLogicTableName(final ShardingSphereSchema schema, final String indexName) { + return schema.getAllTableNames().stream().filter(each -> schema.get(each).getIndexes().containsKey(indexName)).findFirst(); + } + + @Override + public String getType() { + return AlterIndexStatement.class.getCanonicalName(); + } +} diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/AlterTableStatementSchemaRefresher.java b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/AlterTableStatementSchemaRefresher.java new file mode 100644 index 0000000000000..19ff426b49629 --- /dev/null +++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/AlterTableStatementSchemaRefresher.java @@ -0,0 +1,81 @@ +/* + * 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.context.refresher.type; + +import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties; +import org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher; +import org.apache.shardingsphere.infra.federation.optimizer.metadata.FederationSchemaMetaData; +import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; +import org.apache.shardingsphere.infra.metadata.schema.builder.SchemaBuilderMaterials; +import org.apache.shardingsphere.infra.metadata.schema.builder.TableMetaDataBuilder; +import org.apache.shardingsphere.infra.metadata.schema.model.TableMetaData; +import org.apache.shardingsphere.infra.rule.identifier.type.DataNodeContainedRule; +import org.apache.shardingsphere.infra.rule.identifier.type.MutableDataNodeRule; +import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.AlterTableStatement; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; + +/** + * Schema refresher for alter table statement. + */ +public final class AlterTableStatementSchemaRefresher implements MetaDataRefresher { + + @Override + public void refresh(final ShardingSphereMetaData schemaMetaData, final FederationSchemaMetaData schema, final Collection logicDataSourceNames, final AlterTableStatement sqlStatement, + final ConfigurationProperties props) throws SQLException { + String tableName = sqlStatement.getTable().getTableName().getIdentifier().getValue(); + if (sqlStatement.getRenameTable().isPresent()) { + putTableMetaData(schemaMetaData, schema, logicDataSourceNames, sqlStatement.getRenameTable().get().getTableName().getIdentifier().getValue(), props); + removeTableMetaData(schemaMetaData, schema, tableName); + } else { + putTableMetaData(schemaMetaData, schema, logicDataSourceNames, tableName, props); + } + } + + private void removeTableMetaData(final ShardingSphereMetaData schemaMetaData, final FederationSchemaMetaData schema, final String tableName) { + schemaMetaData.getSchema().remove(tableName); + schemaMetaData.getRuleMetaData().findRules(MutableDataNodeRule.class).forEach(each -> each.remove(tableName)); + schema.remove(tableName); + } + + private void putTableMetaData(final ShardingSphereMetaData schemaMetaData, final FederationSchemaMetaData schema, final Collection logicDataSourceNames, final String tableName, + final ConfigurationProperties props) throws SQLException { + if (!containsInDataNodeContainedRule(tableName, schemaMetaData)) { + schemaMetaData.getRuleMetaData().findRules(MutableDataNodeRule.class).forEach(each -> each.put(tableName, logicDataSourceNames.iterator().next())); + } + SchemaBuilderMaterials materials = new SchemaBuilderMaterials( + schemaMetaData.getResource().getDatabaseType(), schemaMetaData.getResource().getDataSources(), schemaMetaData.getRuleMetaData().getRules(), props); + Optional actualTableMetaData = Optional.ofNullable(TableMetaDataBuilder.load(Collections.singletonList(tableName), materials).get(tableName)); + actualTableMetaData.ifPresent(tableMetaData -> { + schemaMetaData.getSchema().put(tableName, TableMetaDataBuilder.decorateKernelTableMetaData(tableMetaData, materials.getRules())); + schema.put(TableMetaDataBuilder.decorateFederationTableMetaData(tableMetaData, materials.getRules())); + }); + } + + private boolean containsInDataNodeContainedRule(final String tableName, final ShardingSphereMetaData schemaMetaData) { + return schemaMetaData.getRuleMetaData().findRules(DataNodeContainedRule.class).stream().anyMatch(each -> each.getAllTables().contains(tableName)); + } + + @Override + public String getType() { + return AlterTableStatement.class.getCanonicalName(); + } +} diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateIndexStatementSchemaRefresher.java b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateIndexStatementSchemaRefresher.java new file mode 100644 index 0000000000000..6df0be80ac414 --- /dev/null +++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateIndexStatementSchemaRefresher.java @@ -0,0 +1,52 @@ +/* + * 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.context.refresher.type; + +import com.google.common.base.Strings; +import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties; +import org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher; +import org.apache.shardingsphere.infra.federation.optimizer.metadata.FederationSchemaMetaData; +import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; +import org.apache.shardingsphere.infra.metadata.schema.builder.util.IndexMetaDataUtil; +import org.apache.shardingsphere.infra.metadata.schema.model.IndexMetaData; +import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateIndexStatement; + +import java.sql.SQLException; +import java.util.Collection; + +/** + * Schema refresher for create index statement. + */ +public final class CreateIndexStatementSchemaRefresher implements MetaDataRefresher { + + @Override + public void refresh(final ShardingSphereMetaData schemaMetaData, final FederationSchemaMetaData schema, final Collection logicDataSourceNames, final CreateIndexStatement sqlStatement, + final ConfigurationProperties props) throws SQLException { + String indexName = null != sqlStatement.getIndex() ? sqlStatement.getIndex().getIdentifier().getValue() : IndexMetaDataUtil.getGeneratedLogicIndexName(sqlStatement.getColumns()); + if (Strings.isNullOrEmpty(indexName)) { + return; + } + String tableName = sqlStatement.getTable().getTableName().getIdentifier().getValue(); + schemaMetaData.getSchema().get(tableName).getIndexes().put(indexName, new IndexMetaData(indexName)); + } + + @Override + public String getType() { + return CreateIndexStatement.class.getCanonicalName(); + } +} diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateTableStatementSchemaRefresher.java b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateTableStatementSchemaRefresher.java new file mode 100644 index 0000000000000..e25a319375c30 --- /dev/null +++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateTableStatementSchemaRefresher.java @@ -0,0 +1,65 @@ +/* + * 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.context.refresher.type; + +import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties; +import org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher; +import org.apache.shardingsphere.infra.federation.optimizer.metadata.FederationSchemaMetaData; +import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; +import org.apache.shardingsphere.infra.metadata.schema.builder.SchemaBuilderMaterials; +import org.apache.shardingsphere.infra.metadata.schema.builder.TableMetaDataBuilder; +import org.apache.shardingsphere.infra.metadata.schema.model.TableMetaData; +import org.apache.shardingsphere.infra.rule.identifier.type.DataNodeContainedRule; +import org.apache.shardingsphere.infra.rule.identifier.type.MutableDataNodeRule; +import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateTableStatement; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; + +/** + * Schema refresher for create table statement. + */ +public final class CreateTableStatementSchemaRefresher implements MetaDataRefresher { + + @Override + public void refresh(final ShardingSphereMetaData schemaMetaData, final FederationSchemaMetaData schema, final Collection logicDataSourceNames, final CreateTableStatement sqlStatement, + final ConfigurationProperties props) throws SQLException { + String tableName = sqlStatement.getTable().getTableName().getIdentifier().getValue(); + if (!containsInDataNodeContainedRule(tableName, schemaMetaData)) { + schemaMetaData.getRuleMetaData().findRules(MutableDataNodeRule.class).forEach(each -> each.put(tableName, logicDataSourceNames.iterator().next())); + } + SchemaBuilderMaterials materials = new SchemaBuilderMaterials( + schemaMetaData.getResource().getDatabaseType(), schemaMetaData.getResource().getDataSources(), schemaMetaData.getRuleMetaData().getRules(), props); + Optional actualTableMetaData = Optional.ofNullable(TableMetaDataBuilder.load(Collections.singletonList(tableName), materials).get(tableName)); + actualTableMetaData.ifPresent(tableMetaData -> { + schemaMetaData.getSchema().put(tableName, TableMetaDataBuilder.decorateKernelTableMetaData(tableMetaData, materials.getRules())); + schema.put(TableMetaDataBuilder.decorateFederationTableMetaData(tableMetaData, materials.getRules())); + }); + } + + private boolean containsInDataNodeContainedRule(final String tableName, final ShardingSphereMetaData schemaMetaData) { + return schemaMetaData.getRuleMetaData().findRules(DataNodeContainedRule.class).stream().anyMatch(each -> each.getAllTables().contains(tableName)); + } + + @Override + public String getType() { + return CreateTableStatement.class.getCanonicalName(); + } +} diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateViewStatementSchemaRefresher.java b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateViewStatementSchemaRefresher.java new file mode 100644 index 0000000000000..0c3e28a26a14b --- /dev/null +++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/CreateViewStatementSchemaRefresher.java @@ -0,0 +1,56 @@ +/* + * 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.context.refresher.type; + +import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties; +import org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher; +import org.apache.shardingsphere.infra.federation.optimizer.metadata.FederationSchemaMetaData; +import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; +import org.apache.shardingsphere.infra.metadata.schema.model.TableMetaData; +import org.apache.shardingsphere.infra.rule.identifier.type.DataNodeContainedRule; +import org.apache.shardingsphere.infra.rule.identifier.type.MutableDataNodeRule; +import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateViewStatement; + +import java.sql.SQLException; +import java.util.Collection; + +/** + * Schema refresher for create view statement. + */ +public final class CreateViewStatementSchemaRefresher implements MetaDataRefresher { + + @Override + public void refresh(final ShardingSphereMetaData schemaMetaData, final FederationSchemaMetaData schema, final Collection logicDataSourceNames, final CreateViewStatement sqlStatement, + final ConfigurationProperties props) throws SQLException { + String viewName = sqlStatement.getView().getTableName().getIdentifier().getValue(); + TableMetaData tableMetaData = new TableMetaData(); + schemaMetaData.getSchema().put(viewName, tableMetaData); + if (!containsInDataNodeContainedRule(viewName, schemaMetaData)) { + schemaMetaData.getRuleMetaData().findRules(MutableDataNodeRule.class).forEach(each -> each.put(viewName, logicDataSourceNames.iterator().next())); + } + } + + private boolean containsInDataNodeContainedRule(final String tableName, final ShardingSphereMetaData schemaMetaData) { + return schemaMetaData.getRuleMetaData().findRules(DataNodeContainedRule.class).stream().anyMatch(each -> each.getAllTables().contains(tableName)); + } + + @Override + public String getType() { + return CreateViewStatement.class.getCanonicalName(); + } +} diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropIndexStatementSchemaRefresher.java b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropIndexStatementSchemaRefresher.java new file mode 100644 index 0000000000000..5996ea1ff075b --- /dev/null +++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropIndexStatementSchemaRefresher.java @@ -0,0 +1,82 @@ +/* + * 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.context.refresher.type; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties; +import org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher; +import org.apache.shardingsphere.infra.federation.optimizer.metadata.FederationSchemaMetaData; +import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; +import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema; +import org.apache.shardingsphere.infra.metadata.schema.model.TableMetaData; +import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment; +import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropIndexStatement; +import org.apache.shardingsphere.sql.parser.sql.dialect.handler.ddl.DropIndexStatementHandler; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.LinkedList; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Schema refresher for drop index statement. + */ +public final class DropIndexStatementSchemaRefresher implements MetaDataRefresher { + + @Override + public void refresh(final ShardingSphereMetaData schemaMetaData, final FederationSchemaMetaData schema, final Collection logicDataSourceNames, final DropIndexStatement sqlStatement, + final ConfigurationProperties props) throws SQLException { + Collection indexNames = getIndexNames(sqlStatement); + Optional simpleTableSegment = DropIndexStatementHandler.getSimpleTableSegment(sqlStatement); + String tableName = simpleTableSegment.map(tableSegment -> tableSegment.getTableName().getIdentifier().getValue()).orElse(""); + TableMetaData tableMetaData = schemaMetaData.getSchema().get(tableName); + if (!Strings.isNullOrEmpty(tableName)) { + for (String each : indexNames) { + tableMetaData.getIndexes().remove(each); + } + return; + } + for (String each : indexNames) { + Optional logicTableNameOptional = findLogicTableName(schemaMetaData.getSchema(), each); + if (logicTableNameOptional.isPresent()) { + String logicTableName = logicTableNameOptional.orElse(""); + Preconditions.checkArgument(!Strings.isNullOrEmpty(logicTableName), "Cannot get the table name!"); + if (null == tableMetaData) { + tableMetaData = schemaMetaData.getSchema().get(logicTableName); + } + Preconditions.checkNotNull(tableMetaData, "Cannot get the table metadata!"); + tableMetaData.getIndexes().remove(each); + } + } + } + + private Collection getIndexNames(final DropIndexStatement dropIndexStatement) { + return dropIndexStatement.getIndexes().stream().map(each -> each.getIdentifier().getValue()).collect(Collectors.toCollection(LinkedList::new)); + } + + private Optional findLogicTableName(final ShardingSphereSchema schema, final String logicIndexName) { + return schema.getAllTableNames().stream().filter(each -> schema.get(each).getIndexes().containsKey(logicIndexName)).findFirst(); + } + + @Override + public String getType() { + return DropIndexStatement.class.getCanonicalName(); + } +} diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropTableStatementSchemaRefresher.java b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropTableStatementSchemaRefresher.java new file mode 100644 index 0000000000000..ff9876efa2b6d --- /dev/null +++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropTableStatementSchemaRefresher.java @@ -0,0 +1,53 @@ +/* + * 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.context.refresher.type; + +import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties; +import org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher; +import org.apache.shardingsphere.infra.federation.optimizer.metadata.FederationSchemaMetaData; +import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; +import org.apache.shardingsphere.infra.rule.identifier.type.MutableDataNodeRule; +import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment; +import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropTableStatement; + +import java.sql.SQLException; +import java.util.Collection; + +/** + * Schema refresher for drop table statement. + */ +public final class DropTableStatementSchemaRefresher implements MetaDataRefresher { + + @Override + public void refresh(final ShardingSphereMetaData schemaMetaData, final FederationSchemaMetaData schema, final Collection logicDataSourceNames, final DropTableStatement sqlStatement, + final ConfigurationProperties props) throws SQLException { + sqlStatement.getTables().forEach(each -> { + schemaMetaData.getSchema().remove(each.getTableName().getIdentifier().getValue()); + schema.remove(each.getTableName().getIdentifier().getValue()); + }); + Collection rules = schemaMetaData.getRuleMetaData().findRules(MutableDataNodeRule.class); + for (SimpleTableSegment each : sqlStatement.getTables()) { + rules.forEach(rule -> rule.remove(each.getTableName().getIdentifier().getValue())); + } + } + + @Override + public String getType() { + return DropTableStatement.class.getCanonicalName(); + } +} diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropViewStatementSchemaRefresher.java b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropViewStatementSchemaRefresher.java new file mode 100644 index 0000000000000..97902a62235c9 --- /dev/null +++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/refresher/type/DropViewStatementSchemaRefresher.java @@ -0,0 +1,50 @@ +/* + * 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.context.refresher.type; + +import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties; +import org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher; +import org.apache.shardingsphere.infra.federation.optimizer.metadata.FederationSchemaMetaData; +import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; +import org.apache.shardingsphere.infra.rule.identifier.type.MutableDataNodeRule; +import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment; +import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropViewStatement; + +import java.sql.SQLException; +import java.util.Collection; + +/** + * Schema refresher for drop view statement. + */ +public final class DropViewStatementSchemaRefresher implements MetaDataRefresher { + + @Override + public void refresh(final ShardingSphereMetaData schemaMetaData, final FederationSchemaMetaData schema, final Collection logicDataSourceNames, final DropViewStatement sqlStatement, + final ConfigurationProperties props) throws SQLException { + sqlStatement.getViews().forEach(each -> schemaMetaData.getSchema().remove(each.getTableName().getIdentifier().getValue())); + Collection rules = schemaMetaData.getRuleMetaData().findRules(MutableDataNodeRule.class); + for (SimpleTableSegment each : sqlStatement.getViews()) { + rules.forEach(rule -> rule.remove(each.getTableName().getIdentifier().getValue())); + } + } + + @Override + public String getType() { + return DropViewStatement.class.getCanonicalName(); + } +} diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher b/shardingsphere-infra/shardingsphere-infra-context/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher new file mode 100644 index 0000000000000..87c1bc23bd200 --- /dev/null +++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.context.refresher.MetaDataRefresher @@ -0,0 +1,25 @@ +# +# 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.infra.context.refresher.type.AlterIndexStatementSchemaRefresher +org.apache.shardingsphere.infra.context.refresher.type.AlterTableStatementSchemaRefresher +org.apache.shardingsphere.infra.context.refresher.type.CreateIndexStatementSchemaRefresher +org.apache.shardingsphere.infra.context.refresher.type.CreateTableStatementSchemaRefresher +org.apache.shardingsphere.infra.context.refresher.type.CreateViewStatementSchemaRefresher +org.apache.shardingsphere.infra.context.refresher.type.DropIndexStatementSchemaRefresher +org.apache.shardingsphere.infra.context.refresher.type.DropTableStatementSchemaRefresher +org.apache.shardingsphere.infra.context.refresher.type.DropViewStatementSchemaRefresher