From aca45af3a51d9a801c264bb995157ddeab742553 Mon Sep 17 00:00:00 2001 From: "Juan Pan(Trista)" Date: Mon, 24 Aug 2020 17:39:11 +0800 Subject: [PATCH] Add checking for creating the same database. (#7028) --- .../mysql/constant/MySQLServerErrorCode.java | 2 ++ .../exception/DBCreateExistsException.java | 33 +++++++++++++++++++ .../backend/text/admin/RDLBackendHandler.java | 6 +++- .../OrchestrationSchemaContextsFixture.java | 2 +- .../text/admin/RDLBackendHandlerTest.java | 16 ++++++++- .../frontend/mysql/MySQLErrPacketFactory.java | 4 +++ .../ddl/CreateDatabaseStatement.java | 2 +- 7 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/exception/DBCreateExistsException.java diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLServerErrorCode.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLServerErrorCode.java index 89b9565a50..90f02d2a21 100644 --- a/shardingsphere-db-protocol/shardingsphere-db-protocol-mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLServerErrorCode.java +++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLServerErrorCode.java @@ -42,6 +42,8 @@ public enum MySQLServerErrorCode implements SQLErrorCode { ER_UNSUPPORTED_PS(1295, "HY000", "This command is not supported in the prepared statement protocol yet"), + ER_DB_CREATE_EXISTS(1007, "HY000", "Message: Can't create database '%s'; database exists"), + ER_ERROR_ON_MODIFYING_GTID_EXECUTED_TABLE(3176, "HY000", "Please do not modify the %s table with an XA transaction. This is an internal system table used to store GTIDs for committed transactions. " + "Although modifying it can lead to an inconsistent GTID state, if neccessary you can modify it with a non-XA transaction."); diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/exception/DBCreateExistsException.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/exception/DBCreateExistsException.java new file mode 100644 index 0000000000..1f9b5c4dbb --- /dev/null +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/exception/DBCreateExistsException.java @@ -0,0 +1,33 @@ +/* + * 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.exception; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * DB create exists exception. + */ +@RequiredArgsConstructor +@Getter +public final class DBCreateExistsException extends BackendException { + + private static final long serialVersionUID = 779787160167652641L; + + private final String databaseName; +} diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/RDLBackendHandler.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/RDLBackendHandler.java index 8159d68cff..42afd496f2 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/RDLBackendHandler.java +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/RDLBackendHandler.java @@ -27,6 +27,7 @@ import org.apache.shardingsphere.infra.database.type.DatabaseType; import org.apache.shardingsphere.infra.yaml.swapper.YamlRuleConfigurationSwapperEngine; import org.apache.shardingsphere.kernel.context.StandardSchemaContexts; import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection; +import org.apache.shardingsphere.proxy.backend.exception.DBCreateExistsException; import org.apache.shardingsphere.proxy.backend.response.BackendResponse; import org.apache.shardingsphere.proxy.backend.response.error.ErrorResponse; import org.apache.shardingsphere.proxy.backend.response.query.QueryData; @@ -72,7 +73,10 @@ public final class RDLBackendHandler implements TextProtocolBackendHandler { } private BackendResponse execute(final CreateDatabaseStatementContext context) { - SchemaNameCallback.getInstance().run(context.getSqlStatement().getSchemaName(), true); + if (ProxySchemaContexts.getInstance().getSchemaNames().contains(context.getSqlStatement().getDatabaseName())) { + return new ErrorResponse(new DBCreateExistsException(context.getSqlStatement().getDatabaseName())); + } + SchemaNameCallback.getInstance().run(context.getSqlStatement().getDatabaseName(), true); // TODO Need to get the executed feedback from registry center for returning. UpdateResponse result = new UpdateResponse(); result.setType("CREATE"); diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/execute/OrchestrationSchemaContextsFixture.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/execute/OrchestrationSchemaContextsFixture.java index b23c9cc5d6..a7fab923e2 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/execute/OrchestrationSchemaContextsFixture.java +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/execute/OrchestrationSchemaContextsFixture.java @@ -41,7 +41,7 @@ public final class OrchestrationSchemaContextsFixture implements SchemaContexts @Override public Map getSchemaContexts() { - return Collections.emptyMap(); + return Collections.singletonMap("schema", mock(SchemaContext.class)); } @Override diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/RDLBackendHandlerTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/RDLBackendHandlerTest.java index e0699f5aad..9b5c0aea86 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/RDLBackendHandlerTest.java +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/RDLBackendHandlerTest.java @@ -25,6 +25,7 @@ import org.apache.shardingsphere.kernel.context.SchemaContext; import org.apache.shardingsphere.kernel.context.StandardSchemaContexts; import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection; import org.apache.shardingsphere.proxy.backend.communication.jdbc.execute.OrchestrationSchemaContextsFixture; +import org.apache.shardingsphere.proxy.backend.exception.DBCreateExistsException; import org.apache.shardingsphere.proxy.backend.response.BackendResponse; import org.apache.shardingsphere.proxy.backend.response.error.ErrorResponse; import org.apache.shardingsphere.proxy.backend.response.update.UpdateResponse; @@ -69,6 +70,19 @@ public final class RDLBackendHandlerTest { assertThat(response, instanceOf(UpdateResponse.class)); } + @Test + public void assertExecuteCreateDatabaseContextWithException() { + BackendConnection connection = mock(BackendConnection.class); + when(connection.getSchema()).thenReturn("schema"); + RDLBackendHandler executeEngine = new RDLBackendHandler(connection, new CreateDatabaseStatement("schema")); + BackendResponse response = executeEngine.execute(); + assertThat(response, instanceOf(ErrorResponse.class)); + setOrchestrationSchemaContexts(true); + response = executeEngine.execute(); + assertThat(response, instanceOf(ErrorResponse.class)); + assertThat(((ErrorResponse) response).getCause(), instanceOf(DBCreateExistsException.class)); + } + private Map getSchemaContextMap() { SchemaContext result = new SchemaContext("schema", null, null); return Collections.singletonMap("schema", result); @@ -103,7 +117,7 @@ public final class RDLBackendHandlerTest { Field schemaContexts = ProxySchemaContexts.getInstance().getClass().getDeclaredField("schemaContexts"); schemaContexts.setAccessible(true); if (isOrchestration) { - schemaContexts.set(ProxySchemaContexts.getInstance(), mock(OrchestrationSchemaContextsFixture.class)); + schemaContexts.set(ProxySchemaContexts.getInstance(), new OrchestrationSchemaContextsFixture()); } else { schemaContexts.set(ProxySchemaContexts.getInstance(), new StandardSchemaContexts()); } diff --git a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/MySQLErrPacketFactory.java b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/MySQLErrPacketFactory.java index a6d8c724f2..7081060533 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/MySQLErrPacketFactory.java +++ b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/MySQLErrPacketFactory.java @@ -22,6 +22,7 @@ import lombok.NoArgsConstructor; import org.apache.shardingsphere.db.protocol.error.CommonErrorCode; import org.apache.shardingsphere.db.protocol.mysql.constant.MySQLServerErrorCode; import org.apache.shardingsphere.db.protocol.mysql.packet.generic.MySQLErrPacket; +import org.apache.shardingsphere.proxy.backend.exception.DBCreateExistsException; import org.apache.shardingsphere.proxy.backend.exception.NoDatabaseSelectedException; import org.apache.shardingsphere.proxy.backend.exception.TableModifyInTransactionException; import org.apache.shardingsphere.proxy.backend.exception.UnknownDatabaseException; @@ -62,6 +63,9 @@ public final class MySQLErrPacketFactory { if (cause instanceof NoDatabaseSelectedException) { return new MySQLErrPacket(sequenceId, MySQLServerErrorCode.ER_NO_DB_ERROR); } + if (cause instanceof DBCreateExistsException) { + return new MySQLErrPacket(sequenceId, MySQLServerErrorCode.ER_DB_CREATE_EXISTS, ((DBCreateExistsException) cause).getDatabaseName()); + } return new MySQLErrPacket(sequenceId, CommonErrorCode.UNKNOWN_EXCEPTION, cause.getMessage()); } } diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/statement/ddl/CreateDatabaseStatement.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/statement/ddl/CreateDatabaseStatement.java index 7e11efb1af..e7d30d21a7 100644 --- a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/statement/ddl/CreateDatabaseStatement.java +++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/statement/ddl/CreateDatabaseStatement.java @@ -27,5 +27,5 @@ import lombok.RequiredArgsConstructor; @Getter public final class CreateDatabaseStatement extends DDLStatement { - private final String schemaName; + private final String databaseName; } -- GitLab