From 02b8b17080b1c0aae065f6dd17039eb5d1e18ebd Mon Sep 17 00:00:00 2001 From: "Juan Pan(Trista)" Date: Tue, 25 Aug 2020 16:51:59 +0800 Subject: [PATCH] Add exceptions for unsupported SQL, incomplete rules and other exceptions (#7054) * Add exception for unsupported SQL, incomplete rules and other exceptions. * check style --- .../mysql/constant/MySQLServerErrorCode.java | 2 ++ .../jdbc/JDBCDatabaseCommunicationEngine.java | 4 +++- .../frontend/mysql/MySQLErrPacketFactory.java | 5 +++++ .../execute/MySQLComStmtExecuteExecutor.java | 14 +++++++++++++- .../text/query/MySQLComQueryPacketExecutor.java | 14 +++++++++++++- .../binary/bind/PostgreSQLComBindExecutor.java | 14 +++++++++++++- .../query/text/PostgreSQLComQueryExecutor.java | 14 +++++++++++++- 7 files changed, 62 insertions(+), 5 deletions(-) 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 b2a707ca28..86e922907b 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 @@ -46,6 +46,8 @@ public enum MySQLServerErrorCode implements SQLErrorCode { ER_TABLE_EXISTS_ERROR(1050, "42S01", "Table '%s' already exists"), + ER_NOT_SUPPORTED_YET(1235, "42000", "This version of ShardingProxy doesn't yet support this SQL. '%s'"), + 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/communication/jdbc/JDBCDatabaseCommunicationEngine.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/JDBCDatabaseCommunicationEngine.java index f2777c086d..78b2ecf55f 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/JDBCDatabaseCommunicationEngine.java +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/JDBCDatabaseCommunicationEngine.java @@ -19,6 +19,7 @@ package org.apache.shardingsphere.proxy.backend.communication.jdbc; import lombok.RequiredArgsConstructor; import org.apache.shardingsphere.infra.callback.orchestration.MetaDataCallback; +import org.apache.shardingsphere.infra.config.exception.ShardingSphereConfigurationException; import org.apache.shardingsphere.infra.config.properties.ConfigurationPropertyKey; import org.apache.shardingsphere.infra.executor.sql.QueryResult; import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext; @@ -88,7 +89,8 @@ public final class JDBCDatabaseCommunicationEngine implements DatabaseCommunicat SQLLogger.logSQL(sql, ProxySchemaContexts.getInstance().getSchemaContexts().getProps().getValue(ConfigurationPropertyKey.SQL_SIMPLE), executionContext); } return execute(executionContext); - } catch (final TableExistsException | SQLException ex) { + } catch (final TableExistsException | ShardingSphereConfigurationException | SQLException ex) { + // TODO Particular handling needed for `createTable` without shardingRule and dataNode. return new ErrorResponse(ex); } } 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 88b3797456..b75155b82d 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.infra.config.exception.ShardingSphereConfigurationException; import org.apache.shardingsphere.proxy.backend.exception.DBCreateExistsException; import org.apache.shardingsphere.proxy.backend.exception.NoDatabaseSelectedException; import org.apache.shardingsphere.proxy.backend.exception.TableModifyInTransactionException; @@ -29,6 +30,7 @@ import org.apache.shardingsphere.proxy.backend.exception.UnknownDatabaseExceptio import org.apache.shardingsphere.proxy.backend.text.sctl.ShardingCTLErrorCode; import org.apache.shardingsphere.proxy.backend.text.sctl.exception.ShardingCTLException; import org.apache.shardingsphere.sharding.route.engine.exception.TableExistsException; +import org.apache.shardingsphere.sql.parser.exception.SQLParsingException; import java.sql.SQLException; @@ -70,6 +72,9 @@ public final class MySQLErrPacketFactory { if (cause instanceof TableExistsException) { return new MySQLErrPacket(sequenceId, MySQLServerErrorCode.ER_TABLE_EXISTS_ERROR, ((TableExistsException) cause).getTableName()); } + if (cause instanceof ShardingSphereConfigurationException || cause instanceof SQLParsingException) { + return new MySQLErrPacket(sequenceId, MySQLServerErrorCode.ER_NOT_SUPPORTED_YET, cause.getMessage()); + } return new MySQLErrPacket(sequenceId, CommonErrorCode.UNKNOWN_EXCEPTION, cause.getMessage()); } } diff --git a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/execute/MySQLComStmtExecuteExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/execute/MySQLComStmtExecuteExecutor.java index 7088c0d302..3ef0dd8082 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/execute/MySQLComStmtExecuteExecutor.java +++ b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/execute/MySQLComStmtExecuteExecutor.java @@ -80,7 +80,7 @@ public final class MySQLComStmtExecuteExecutor implements QueryCommandExecutor { if (ProxySchemaContexts.getInstance().getSchemaContexts().isCircuitBreak()) { return Collections.singletonList(new MySQLErrPacket(1, CommonErrorCode.CIRCUIT_BREAK_MODE)); } - BackendResponse backendResponse = databaseCommunicationEngine.execute(); + BackendResponse backendResponse = getBackendResponse(); if (backendResponse instanceof QueryResponse) { isQueryResponse = true; return createQueryPacket((QueryResponse) backendResponse); @@ -93,6 +93,18 @@ public final class MySQLComStmtExecuteExecutor implements QueryCommandExecutor { return Collections.singletonList(createErrorPacket(((ErrorResponse) backendResponse).getCause())); } + private BackendResponse getBackendResponse() { + BackendResponse result; + try { + result = databaseCommunicationEngine.execute(); + // CHECKSTYLE:OFF + } catch (final Exception ex) { + // CHECKSTYLE:OFF + result = new ErrorResponse(ex); + } + return result; + } + private Collection> createQueryPacket(final QueryResponse backendResponse) { Collection> result = new LinkedList<>(); List queryHeader = backendResponse.getQueryHeaders(); diff --git a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryPacketExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryPacketExecutor.java index 15aa62ee45..18a22efef8 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryPacketExecutor.java +++ b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryPacketExecutor.java @@ -76,7 +76,7 @@ public final class MySQLComQueryPacketExecutor implements QueryCommandExecutor { if (ProxySchemaContexts.getInstance().getSchemaContexts().isCircuitBreak()) { return Collections.singletonList(new MySQLErrPacket(1, CommonErrorCode.CIRCUIT_BREAK_MODE)); } - BackendResponse backendResponse = textProtocolBackendHandler.execute(); + BackendResponse backendResponse = getBackendResponse(); if (backendResponse instanceof QueryResponse) { isQueryResponse = true; return createQueryPackets((QueryResponse) backendResponse); @@ -89,6 +89,18 @@ public final class MySQLComQueryPacketExecutor implements QueryCommandExecutor { return Collections.singletonList(createErrorPacket(((ErrorResponse) backendResponse).getCause())); } + private BackendResponse getBackendResponse() { + BackendResponse result; + try { + result = textProtocolBackendHandler.execute(); + // CHECKSTYLE:OFF + } catch (final Exception ex) { + // CHECKSTYLE:OFF + result = new ErrorResponse(ex); + } + return result; + } + private Collection> createQueryPackets(final QueryResponse backendResponse) { Collection> result = new LinkedList<>(); List queryHeader = backendResponse.getQueryHeaders(); diff --git a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/binary/bind/PostgreSQLComBindExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/binary/bind/PostgreSQLComBindExecutor.java index 27adb99a8f..ddc244fc4d 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/binary/bind/PostgreSQLComBindExecutor.java +++ b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/binary/bind/PostgreSQLComBindExecutor.java @@ -94,7 +94,7 @@ public final class PostgreSQLComBindExecutor implements QueryCommandExecutor { if (null == databaseCommunicationEngine) { return result; } - BackendResponse backendResponse = databaseCommunicationEngine.execute(); + BackendResponse backendResponse = getBackendResponse(); if (backendResponse instanceof QueryResponse) { createQueryPacket((QueryResponse) backendResponse).ifPresent(result::add); } @@ -109,6 +109,18 @@ public final class PostgreSQLComBindExecutor implements QueryCommandExecutor { return result; } + private BackendResponse getBackendResponse() { + BackendResponse result; + try { + result = databaseCommunicationEngine.execute(); + // CHECKSTYLE:OFF + } catch (final Exception ex) { + // CHECKSTYLE:OFF + result = new ErrorResponse(ex); + } + return result; + } + private Optional createQueryPacket(final QueryResponse queryResponse) { List columnDescriptions = getPostgreSQLColumnDescriptions(queryResponse); isQueryResponse = !columnDescriptions.isEmpty(); diff --git a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/text/PostgreSQLComQueryExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/text/PostgreSQLComQueryExecutor.java index 926031926a..758ede31f1 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/text/PostgreSQLComQueryExecutor.java +++ b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/query/text/PostgreSQLComQueryExecutor.java @@ -73,7 +73,7 @@ public final class PostgreSQLComQueryExecutor implements QueryCommandExecutor { if (ProxySchemaContexts.getInstance().getSchemaContexts().isCircuitBreak()) { return Collections.singletonList(new PostgreSQLErrorResponsePacket()); } - BackendResponse backendResponse = textProtocolBackendHandler.execute(); + BackendResponse backendResponse = getBackendResponse(); if (backendResponse instanceof QueryResponse) { Optional result = createQueryPacket((QueryResponse) backendResponse); return result.>>map(Collections::singletonList).orElseGet(Collections::emptyList); @@ -86,6 +86,18 @@ public final class PostgreSQLComQueryExecutor implements QueryCommandExecutor { return Collections.singletonList(createErrorPacket((ErrorResponse) backendResponse)); } + private BackendResponse getBackendResponse() { + BackendResponse result; + try { + result = textProtocolBackendHandler.execute(); + // CHECKSTYLE:OFF + } catch (final Exception ex) { + // CHECKSTYLE:OFF + result = new ErrorResponse(ex); + } + return result; + } + private Optional createQueryPacket(final QueryResponse queryResponse) { List columnDescriptions = getPostgreSQLColumnDescriptions(queryResponse); isQueryResponse = !columnDescriptions.isEmpty(); -- GitLab