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 dfb2609 Split RDLBackendHandler and DropShardingRuleBackendHandler
(#8653)
dfb2609 is described below
commit dfb26090b11c6d57c86010229a15a3c171d0a6a7
Author: Liang Zhang <[email protected]>
AuthorDate: Wed Dec 16 18:24:16 2020 +0800
Split RDLBackendHandler and DropShardingRuleBackendHandler (#8653)
* Add DropShardingRuleBackendHandler
* Add SchemaRequiredBackendHandler
* Refactor DropShardingRuleBackendHandler
---
.../rdl/DropShardingRuleBackendHandler.java | 112 +++++++++++++++++++++
.../text/distsql/rdl/RDLBackendDetailHandler.java | 39 +++++++
.../text/distsql/rdl/RDLBackendHandler.java | 92 +----------------
.../distsql/rdl/SchemaRequiredBackendHandler.java | 61 +++++++++++
.../statement/available/FromSchemaAvailable.java | 35 +++++++
5 files changed, 250 insertions(+), 89 deletions(-)
diff --git
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/DropShardingRuleBackendHandler.java
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/DropShardingRuleBackendHandler.java
new file mode 100644
index 0000000..c8e836e
--- /dev/null
+++
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/DropShardingRuleBackendHandler.java
@@ -0,0 +1,112 @@
+/*
+ * 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.proxy.backend.text.distsql.rdl;
+
+import com.google.common.base.Preconditions;
+import
org.apache.shardingsphere.governance.core.event.model.rule.RuleConfigurationsPersistEvent;
+import
org.apache.shardingsphere.infra.binder.statement.rdl.DropShardingRuleStatementContext;
+import org.apache.shardingsphere.infra.eventbus.ShardingSphereEventBus;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import
org.apache.shardingsphere.proxy.backend.exception.ShardingTableRuleNotExistedException;
+import org.apache.shardingsphere.proxy.backend.exception.TablesInUsedException;
+import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader;
+import
org.apache.shardingsphere.proxy.backend.response.header.update.UpdateResponseHeader;
+import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
+import org.apache.shardingsphere.sharding.rule.ShardingRule;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * Drop sharding rule backend handler.
+ */
+public final class DropShardingRuleBackendHandler extends
SchemaRequiredBackendHandler<DropShardingRuleStatementContext> {
+
+ @Override
+ public ResponseHeader execute(final String schemaName, final
DropShardingRuleStatementContext sqlStatementContext) {
+ Collection<String> tableNames =
sqlStatementContext.getSqlStatement().getTableNames().stream().map(each ->
each.getIdentifier().getValue()).collect(Collectors.toList());
+ check(schemaName, tableNames);
+ drop(schemaName, tableNames);
+ post(schemaName);
+ return new UpdateResponseHeader(sqlStatementContext.getSqlStatement());
+ }
+
+ private void check(final String schemaName, final Collection<String>
tableNames) {
+ ShardingSphereMetaData metaData =
ProxyContext.getInstance().getMetaData(schemaName);
+ Optional<ShardingRule> shardingRule =
metaData.getRuleMetaData().getRules().stream().filter(each -> each instanceof
ShardingRule).map(each -> (ShardingRule) each).findFirst();
+ if (!shardingRule.isPresent()) {
+ throw new ShardingTableRuleNotExistedException(tableNames);
+ }
+ Collection<String> shardingTableNames =
getShardingTableNames(shardingRule.get());
+ Collection<String> notExistedTableNames =
tableNames.stream().filter(each ->
!shardingTableNames.contains(each)).collect(Collectors.toList());
+ if (!notExistedTableNames.isEmpty()) {
+ throw new
ShardingTableRuleNotExistedException(notExistedTableNames);
+ }
+ Collection<String> inUsedTableNames = tableNames.stream().filter(each
->
ProxyContext.getInstance().getMetaData(schemaName).getSchema().containsTable(each)).collect(Collectors.toList());
+ if (!inUsedTableNames.isEmpty()) {
+ throw new TablesInUsedException(inUsedTableNames);
+ }
+ }
+
+ private Collection<String> getShardingTableNames(final ShardingRule
shardingRule) {
+ Collection<String> result = new LinkedList<>(shardingRule.getTables());
+ result.addAll(shardingRule.getBroadcastTables());
+ return result;
+ }
+
+ private void drop(final String schemaName, final Collection<String>
tableNames) {
+ Optional<ShardingRuleConfiguration> shardingRuleConfig =
ProxyContext.getInstance().getMetaData(schemaName)
+ .getRuleMetaData().getConfigurations().stream().filter(each ->
each instanceof ShardingRuleConfiguration).map(each ->
(ShardingRuleConfiguration) each).findFirst();
+ Preconditions.checkState(shardingRuleConfig.isPresent());
+ // TODO add global lock
+ for (String each : tableNames) {
+ dropShardingTable(each, shardingRuleConfig.get());
+ dropBroadcastTable(each, shardingRuleConfig.get());
+ dropBindingTable(each, shardingRuleConfig.get());
+ }
+ }
+
+ private void dropShardingTable(final String tableName, final
ShardingRuleConfiguration shardingRuleConfig) {
+
shardingRuleConfig.getTables().removeAll(shardingRuleConfig.getTables().stream().filter(each
->
tableName.equalsIgnoreCase(each.getLogicTable())).collect(Collectors.toList()));
+ }
+
+ private void dropBroadcastTable(final String tableName, final
ShardingRuleConfiguration shardingRuleConfig) {
+
shardingRuleConfig.getBroadcastTables().removeAll(shardingRuleConfig.getBroadcastTables().stream().filter(tableName::equalsIgnoreCase).collect(Collectors.toList()));
+ }
+
+ private void dropBindingTable(final String tableName, final
ShardingRuleConfiguration shardingRuleConfig) {
+ Collection<String> toBeDroppedGroups =
shardingRuleConfig.getBindingTableGroups().stream().filter(each ->
Arrays.asList(each.split(",")).contains(tableName)).collect(Collectors.toList());
+
shardingRuleConfig.getBindingTableGroups().removeAll(toBeDroppedGroups);
+ Collection<String> newGroups = toBeDroppedGroups.stream().map(each ->
createBindingTableGroupWithoutTableName(tableName,
each)).collect(Collectors.toList());
+ shardingRuleConfig.getBindingTableGroups().addAll(newGroups);
+ }
+
+ private String createBindingTableGroupWithoutTableName(final String
expectedTable, final String originalBindingTableGroup) {
+ return Arrays.stream(originalBindingTableGroup.split(",")).filter(each
->
!each.trim().equalsIgnoreCase(expectedTable)).collect(Collectors.joining(","));
+ }
+
+ private void post(final String schemaName) {
+ // TODO should use RuleConfigurationsChangeEvent
+ ShardingSphereEventBus.getInstance().post(new
RuleConfigurationsPersistEvent(schemaName,
ProxyContext.getInstance().getMetaData(schemaName).getRuleMetaData().getConfigurations()));
+ // TODO Need to get the executed feedback from registry center for
returning.
+ }
+}
diff --git
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/RDLBackendDetailHandler.java
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/RDLBackendDetailHandler.java
new file mode 100644
index 0000000..cd40ae5
--- /dev/null
+++
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/RDLBackendDetailHandler.java
@@ -0,0 +1,39 @@
+/*
+ * 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.proxy.backend.text.distsql.rdl;
+
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
+import
org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
+import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader;
+
+/**
+ * RDL backend detail handler.
+ *
+ * @param <T> type of SQL statement context
+ */
+public interface RDLBackendDetailHandler<T extends SQLStatementContext<?>> {
+
+ /**
+ * Execute detail.
+ *
+ * @param backendConnection backend connection
+ * @param sqlStatementContext SQL statement context
+ * @return response header
+ */
+ ResponseHeader execute(BackendConnection backendConnection, T
sqlStatementContext);
+}
diff --git
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/RDLBackendHandler.java
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/RDLBackendHandler.java
index 6b67d90..e8e6d98 100644
---
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/RDLBackendHandler.java
+++
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/RDLBackendHandler.java
@@ -17,7 +17,6 @@
package org.apache.shardingsphere.proxy.backend.text.distsql.rdl;
-import com.google.common.base.Joiner;
import lombok.RequiredArgsConstructor;
import
org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.AddResourcesStatement;
import
org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateShardingRuleStatement;
@@ -36,37 +35,26 @@ import
org.apache.shardingsphere.infra.config.datasource.DataSourceConfiguration
import
org.apache.shardingsphere.infra.context.metadata.impl.StandardMetaDataContexts;
import org.apache.shardingsphere.infra.database.type.DatabaseType;
import org.apache.shardingsphere.infra.eventbus.ShardingSphereEventBus;
-import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import
org.apache.shardingsphere.infra.yaml.swapper.YamlRuleConfigurationSwapperEngine;
import
org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
import
org.apache.shardingsphere.proxy.backend.exception.DBCreateExistsException;
-import
org.apache.shardingsphere.proxy.backend.exception.NoDatabaseSelectedException;
-import
org.apache.shardingsphere.proxy.backend.exception.ShardingTableRuleNotExistedException;
-import org.apache.shardingsphere.proxy.backend.exception.TablesInUsedException;
-import
org.apache.shardingsphere.proxy.backend.exception.UnknownDatabaseException;
import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader;
import
org.apache.shardingsphere.proxy.backend.response.header.update.UpdateResponseHeader;
import org.apache.shardingsphere.proxy.backend.text.TextProtocolBackendHandler;
import
org.apache.shardingsphere.proxy.config.util.DataSourceParameterConverter;
import org.apache.shardingsphere.proxy.config.yaml.YamlDataSourceParameter;
import
org.apache.shardingsphere.proxy.converter.CreateDataSourcesStatementContextConverter;
-import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import
org.apache.shardingsphere.sharding.converter.CreateShardingRuleStatementContextConverter;
-import org.apache.shardingsphere.sharding.rule.ShardingRule;
import
org.apache.shardingsphere.sharding.yaml.config.YamlShardingRuleConfiguration;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateDatabaseStatement;
import
org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropDatabaseStatement;
import java.sql.SQLException;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.LinkedList;
import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
/**
* RDL backend handler.
@@ -83,7 +71,7 @@ public final class RDLBackendHandler implements
TextProtocolBackendHandler {
if (!isRegistryCenterExisted()) {
throw new SQLException(String.format("No Registry center to
execute `%s` SQL", sqlStatement.getClass().getSimpleName()));
}
- return getResponseHeader(getSQLStatementContext());
+ return getResponseHeader(backendConnection.getSchemaName(),
getSQLStatementContext());
}
private ResponseHeader execute(final CreateDatabaseStatementContext
context) {
@@ -121,80 +109,6 @@ public final class RDLBackendHandler implements
TextProtocolBackendHandler {
return new UpdateResponseHeader(context.getSqlStatement());
}
- private ResponseHeader execute(final DropShardingRuleStatementContext
context) {
- String schemaName = backendConnection.getSchemaName();
- if (null == schemaName) {
- throw new NoDatabaseSelectedException();
- }
- if (!ProxyContext.getInstance().schemaExists(schemaName)) {
- throw new UnknownDatabaseException(schemaName);
- }
- Collection<String> tableNames =
context.getSqlStatement().getTableNames().stream().map(each ->
each.getIdentifier().getValue()).collect(Collectors.toList());
- Optional<ShardingRuleConfiguration> ruleConfig =
findShardingRuleConfiguration(schemaName);
- if (!ruleConfig.isPresent()) {
- throw new ShardingTableRuleNotExistedException(tableNames);
- }
- checkShardingTables(schemaName, tableNames);
- removeShardingTableRules(tableNames, ruleConfig.get());
- // TODO should use RuleConfigurationsChangeEvent
- ShardingSphereEventBus.getInstance().post(new
RuleConfigurationsPersistEvent(schemaName,
ProxyContext.getInstance().getMetaData(schemaName).getRuleMetaData().getConfigurations()));
- // TODO Need to get the executed feedback from registry center for
returning.
- return new UpdateResponseHeader(context.getSqlStatement());
- }
-
- private Optional<ShardingRuleConfiguration>
findShardingRuleConfiguration(final String schemaName) {
- return ProxyContext.getInstance().getMetaData(schemaName)
- .getRuleMetaData().getConfigurations().stream().filter(each ->
each instanceof ShardingRuleConfiguration).map(each ->
(ShardingRuleConfiguration) each).findFirst();
- }
-
- private void checkShardingTables(final String schemaName, final
Collection<String> tableNames) {
- ShardingSphereMetaData metaData =
ProxyContext.getInstance().getMetaData(schemaName);
- Optional<ShardingRule> shardingRule =
metaData.getRuleMetaData().getRules().stream().filter(each -> each instanceof
ShardingRule).map(each -> (ShardingRule) each).findFirst();
- if (!shardingRule.isPresent()) {
- return;
- }
- Collection<String> shardingTableNames =
getShardingTableNames(shardingRule.get());
- Collection<String> notExistedTableNames =
tableNames.stream().filter(each ->
!shardingTableNames.contains(each)).collect(Collectors.toList());
- if (!notExistedTableNames.isEmpty()) {
- throw new
ShardingTableRuleNotExistedException(notExistedTableNames);
- }
- Collection<String> inUsedTableNames = tableNames.stream().filter(each
->
ProxyContext.getInstance().getMetaData(schemaName).getSchema().containsTable(each)).collect(Collectors.toList());
- if (!inUsedTableNames.isEmpty()) {
- throw new TablesInUsedException(inUsedTableNames);
- }
- }
-
- private Collection<String> getShardingTableNames(final ShardingRule
shardingRule) {
- Collection<String> result = new LinkedList<>(shardingRule.getTables());
- result.addAll(shardingRule.getBroadcastTables());
- return result;
- }
-
- private void removeShardingTableRules(final Collection<String> tableNames,
final ShardingRuleConfiguration ruleConfig) {
- // TODO add global lock
- for (String each : tableNames) {
- removeShardingTableRule(each, ruleConfig);
- }
- }
-
- private void removeShardingTableRule(final String tableName, final
ShardingRuleConfiguration ruleConfig) {
- Collection<String> bindingTableGroups =
ruleConfig.getBindingTableGroups().stream().filter(each ->
Arrays.asList(each.split(",")).contains(tableName)).collect(Collectors.toList());
- ruleConfig.getBindingTableGroups().removeAll(bindingTableGroups);
- Collection<String> newBindingTableGroups = new LinkedList<>();
- for (String each : bindingTableGroups) {
- Collection<String> sss = new LinkedList<>();
- for (String str : each.split(",")) {
- if (!str.trim().equalsIgnoreCase(tableName)) {
- sss.add(str);
- }
- }
- newBindingTableGroups.add(Joiner.on(",").join(sss));
- }
- ruleConfig.getBindingTableGroups().addAll(newBindingTableGroups);
-
ruleConfig.getTables().removeAll(ruleConfig.getTables().stream().filter(each ->
tableName.equalsIgnoreCase(each.getLogicTable())).collect(Collectors.toList()));
-
ruleConfig.getBroadcastTables().removeAll(ruleConfig.getBroadcastTables().stream().filter(tableName::equalsIgnoreCase).collect(Collectors.toList()));
- }
-
private boolean isRegistryCenterExisted() {
return !(ProxyContext.getInstance().getMetaDataContexts() instanceof
StandardMetaDataContexts);
}
@@ -219,7 +133,7 @@ public final class RDLBackendHandler implements
TextProtocolBackendHandler {
throw new
UnsupportedOperationException(sqlStatement.getClass().getName());
}
- private ResponseHeader getResponseHeader(final SQLStatementContext<?>
context) {
+ private ResponseHeader getResponseHeader(final String schemaName, final
SQLStatementContext<?> context) {
if (context instanceof CreateDatabaseStatementContext) {
return execute((CreateDatabaseStatementContext) context);
}
@@ -233,7 +147,7 @@ public final class RDLBackendHandler implements
TextProtocolBackendHandler {
return execute((DropDatabaseStatementContext) context);
}
if (context instanceof DropShardingRuleStatementContext) {
- return execute((DropShardingRuleStatementContext) context);
+ new DropShardingRuleBackendHandler().execute(schemaName,
(DropShardingRuleStatementContext) context);
}
throw new UnsupportedOperationException(context.getClass().getName());
}
diff --git
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/SchemaRequiredBackendHandler.java
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/SchemaRequiredBackendHandler.java
new file mode 100644
index 0000000..bc78778
--- /dev/null
+++
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/SchemaRequiredBackendHandler.java
@@ -0,0 +1,61 @@
+/*
+ * 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.proxy.backend.text.distsql.rdl;
+
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
+import
org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import
org.apache.shardingsphere.proxy.backend.exception.NoDatabaseSelectedException;
+import
org.apache.shardingsphere.proxy.backend.exception.UnknownDatabaseException;
+import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.SchemaSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.statement.available.FromSchemaAvailable;
+
+import java.util.Optional;
+
+/**
+ * Schema required backend handler.
+ *
+ * @param <T> type of SQL statement context
+ */
+public abstract class SchemaRequiredBackendHandler<T extends
SQLStatementContext<?>> implements RDLBackendDetailHandler<T> {
+
+ @Override
+ public final ResponseHeader execute(final BackendConnection
backendConnection, final T sqlStatementContext) {
+ String schemaName = getSchemaName(backendConnection,
sqlStatementContext);
+ checkSchema(schemaName);
+ return execute(schemaName, sqlStatementContext);
+ }
+
+ protected abstract ResponseHeader execute(String schemaName, T
sqlStatementContext);
+
+ private String getSchemaName(final BackendConnection backendConnection,
final T sqlStatementContext) {
+ Optional<SchemaSegment> schemaFromSQL =
sqlStatementContext.getSqlStatement() instanceof FromSchemaAvailable
+ ? ((FromSchemaAvailable)
sqlStatementContext.getSqlStatement()).getSchema() : Optional.empty();
+ return schemaFromSQL.isPresent() ?
schemaFromSQL.get().getIdentifier().getValue() :
backendConnection.getSchemaName();
+ }
+
+ private void checkSchema(final String schemaName) {
+ if (null == schemaName) {
+ throw new NoDatabaseSelectedException();
+ }
+ if (!ProxyContext.getInstance().schemaExists(schemaName)) {
+ throw new UnknownDatabaseException(schemaName);
+ }
+ }
+}
diff --git
a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/statement/available/FromSchemaAvailable.java
b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/statement/available/FromSchemaAvailable.java
new file mode 100644
index 0000000..facc4d0
--- /dev/null
+++
b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/statement/available/FromSchemaAvailable.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sql.parser.sql.common.statement.available;
+
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.SchemaSegment;
+
+import java.util.Optional;
+
+/**
+ * From schema available.
+ */
+public interface FromSchemaAvailable {
+
+ /**
+ * Get schema.
+ *
+ * @return schema segment
+ */
+ Optional<SchemaSegment> getSchema();
+}