This is an automated email from the ASF dual-hosted git repository.
terrymanu 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 fcccba479b6 Add basic Firebird exception mapper (#38812)
fcccba479b6 is described below
commit fcccba479b609ddd064c8dad0b126860f698caea
Author: Maxim Sentyabrskiy <[email protected]>
AuthorDate: Sat Jun 6 08:28:14 2026 +0300
Add basic Firebird exception mapper (#38812)
Co-authored-by: makssent <[email protected]>
---
bom/pom.xml | 5 ++
.../dialect/firebird/pom.xml | 15 +----
.../mapper/FirebirdDialectExceptionMapper.java | 54 ++++++++++++++++
.../exception/firebird/sqlstate/FirebirdState.java | 36 +++++++++++
.../firebird/vendor/FirebirdVendorError.java | 53 ++++++++++++++++
...exception.core.mapper.SQLDialectExceptionMapper | 18 ++++++
.../mapper/FirebirdDialectExceptionMapperTest.java | 64 +++++++++++++++++++
database/exception/dialect/pom.xml | 1 +
database/protocol/dialect/firebird/pom.xml | 5 ++
.../firebird/err/FirebirdStatusVector.java | 8 ++-
.../firebird/err/FirebirdStatusVectorTest.java | 25 ++++++++
.../FirebirdAuthenticationEngine.java | 11 ++--
.../FirebirdAuthenticationEngineTest.java | 71 +++++++++++++++++++++-
.../err/FirebirdErrorPacketFactoryTest.java | 16 +++++
14 files changed, 359 insertions(+), 23 deletions(-)
diff --git a/bom/pom.xml b/bom/pom.xml
index 19dc5ae6237..5f5cc79172c 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -370,6 +370,11 @@
<artifactId>shardingsphere-database-exception-postgresql</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+
<artifactId>shardingsphere-database-exception-firebird</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-database-protocol-core</artifactId>
diff --git a/database/protocol/dialect/firebird/pom.xml
b/database/exception/dialect/firebird/pom.xml
similarity index 74%
copy from database/protocol/dialect/firebird/pom.xml
copy to database/exception/dialect/firebird/pom.xml
index 2b84ba05c4d..df11220b81e 100644
--- a/database/protocol/dialect/firebird/pom.xml
+++ b/database/exception/dialect/firebird/pom.xml
@@ -20,29 +20,18 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.shardingsphere</groupId>
- <artifactId>shardingsphere-database-protocol-dialect</artifactId>
+ <artifactId>shardingsphere-database-exception-dialect</artifactId>
<version>5.5.4-SNAPSHOT</version>
</parent>
- <artifactId>shardingsphere-protocol-firebird</artifactId>
+ <artifactId>shardingsphere-database-exception-firebird</artifactId>
<name>${project.artifactId}</name>
<dependencies>
- <dependency>
- <groupId>org.apache.shardingsphere</groupId>
- <artifactId>shardingsphere-database-protocol-core</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.shardingsphere</groupId>
- <artifactId>shardingsphere-database-connector-firebird</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-database-exception-core</artifactId>
<version>${project.version}</version>
</dependency>
-
<dependency>
<groupId>org.firebirdsql.jdbc</groupId>
<artifactId>jaybird</artifactId>
diff --git
a/database/exception/dialect/firebird/src/main/java/org/apache/shardingsphere/database/exception/firebird/mapper/FirebirdDialectExceptionMapper.java
b/database/exception/dialect/firebird/src/main/java/org/apache/shardingsphere/database/exception/firebird/mapper/FirebirdDialectExceptionMapper.java
new file mode 100644
index 00000000000..fbfe347cf05
--- /dev/null
+++
b/database/exception/dialect/firebird/src/main/java/org/apache/shardingsphere/database/exception/firebird/mapper/FirebirdDialectExceptionMapper.java
@@ -0,0 +1,54 @@
+/*
+ * 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.database.exception.firebird.mapper;
+
+import
org.apache.shardingsphere.database.exception.core.exception.SQLDialectException;
+import
org.apache.shardingsphere.database.exception.core.exception.connection.AccessDeniedException;
+import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
+import
org.apache.shardingsphere.database.exception.core.mapper.SQLDialectExceptionMapper;
+import
org.apache.shardingsphere.database.exception.firebird.vendor.FirebirdVendorError;
+import
org.apache.shardingsphere.infra.exception.external.sql.vendor.VendorError;
+import org.apache.shardingsphere.infra.exception.generic.UnknownSQLException;
+
+import java.sql.SQLException;
+
+/**
+ * Firebird dialect exception mapper.
+ */
+public final class FirebirdDialectExceptionMapper implements
SQLDialectExceptionMapper {
+
+ @Override
+ public SQLException convert(final SQLDialectException sqlDialectException)
{
+ if (sqlDialectException instanceof UnknownDatabaseException) {
+ return toSQLException(FirebirdVendorError.UNAVAILABLE_DATABASE,
((UnknownDatabaseException) sqlDialectException).getDatabaseName());
+ }
+ if (sqlDialectException instanceof AccessDeniedException) {
+ return toSQLException(FirebirdVendorError.LOGIN_FAILED);
+ }
+ return new UnknownSQLException(sqlDialectException).toSQLException();
+ }
+
+ private SQLException toSQLException(final VendorError vendorError, final
Object... messageArgs) {
+ return new SQLException(String.format(vendorError.getReason(),
messageArgs), vendorError.getSqlState().getValue(),
vendorError.getVendorCode());
+ }
+
+ @Override
+ public String getDatabaseType() {
+ return "Firebird";
+ }
+}
diff --git
a/database/exception/dialect/firebird/src/main/java/org/apache/shardingsphere/database/exception/firebird/sqlstate/FirebirdState.java
b/database/exception/dialect/firebird/src/main/java/org/apache/shardingsphere/database/exception/firebird/sqlstate/FirebirdState.java
new file mode 100644
index 00000000000..f00a726c59e
--- /dev/null
+++
b/database/exception/dialect/firebird/src/main/java/org/apache/shardingsphere/database/exception/firebird/sqlstate/FirebirdState.java
@@ -0,0 +1,36 @@
+/*
+ * 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.database.exception.firebird.sqlstate;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import
org.apache.shardingsphere.infra.exception.external.sql.sqlstate.SQLState;
+
+/**
+ * Firebird SQL state.
+ *
+ * <p>Holds SQL states that Jaybird derives from a GDSCODE but that are not
defined in {@code XOpenSQLState}.</p>
+ */
+@RequiredArgsConstructor
+@Getter
+public enum FirebirdState implements SQLState {
+
+ UNAVAILABLE_DATABASE("08001");
+
+ private final String value;
+}
diff --git
a/database/exception/dialect/firebird/src/main/java/org/apache/shardingsphere/database/exception/firebird/vendor/FirebirdVendorError.java
b/database/exception/dialect/firebird/src/main/java/org/apache/shardingsphere/database/exception/firebird/vendor/FirebirdVendorError.java
new file mode 100644
index 00000000000..2c5280ee850
--- /dev/null
+++
b/database/exception/dialect/firebird/src/main/java/org/apache/shardingsphere/database/exception/firebird/vendor/FirebirdVendorError.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.database.exception.firebird.vendor;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import
org.apache.shardingsphere.database.exception.firebird.sqlstate.FirebirdState;
+import
org.apache.shardingsphere.infra.exception.external.sql.sqlstate.SQLState;
+import
org.apache.shardingsphere.infra.exception.external.sql.sqlstate.XOpenSQLState;
+import
org.apache.shardingsphere.infra.exception.external.sql.vendor.VendorError;
+import org.firebirdsql.gds.ISCConstants;
+
+/**
+ * Firebird vendor error.
+ *
+ * <p>The vendor code carries the native Firebird GDSCODE, which the client
(Jaybird) uses to look up both the message
+ * template and the SQL state from its own catalog. The status vector
transmits the GDSCODE plus a single string
+ * argument, so the reason here holds only that argument. With Jaybird's
current message rendering a {@code {0}}
+ * placeholder is filled by the argument and a template without placeholders
is followed by the argument; an empty reason
+ * sends no argument, leaving the catalog message as-is. GDSCODEs whose
templates require multiple arguments are avoided
+ * until the status vector can carry them.</p>
+ *
+ * @see <a
href="https://www.firebirdsql.org/file/documentation/chunk/en/refdocs/fblangref40/fblangref40-appx02-sqlcodes.html">SQLCODE
and GDSCODE Error Codes</a>
+ */
+@RequiredArgsConstructor
+@Getter
+public enum FirebirdVendorError implements VendorError {
+
+ UNAVAILABLE_DATABASE(FirebirdState.UNAVAILABLE_DATABASE,
ISCConstants.isc_unavailable, "%s"),
+
+ LOGIN_FAILED(XOpenSQLState.INVALID_AUTHORIZATION_SPECIFICATION,
ISCConstants.isc_login, "");
+
+ private final SQLState sqlState;
+
+ private final int vendorCode;
+
+ private final String reason;
+}
diff --git
a/database/exception/dialect/firebird/src/main/resources/META-INF/services/org.apache.shardingsphere.database.exception.core.mapper.SQLDialectExceptionMapper
b/database/exception/dialect/firebird/src/main/resources/META-INF/services/org.apache.shardingsphere.database.exception.core.mapper.SQLDialectExceptionMapper
new file mode 100644
index 00000000000..4b26c68316e
--- /dev/null
+++
b/database/exception/dialect/firebird/src/main/resources/META-INF/services/org.apache.shardingsphere.database.exception.core.mapper.SQLDialectExceptionMapper
@@ -0,0 +1,18 @@
+#
+# 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.database.exception.firebird.mapper.FirebirdDialectExceptionMapper
diff --git
a/database/exception/dialect/firebird/src/test/java/org/apache/shardingsphere/database/exception/firebird/mapper/FirebirdDialectExceptionMapperTest.java
b/database/exception/dialect/firebird/src/test/java/org/apache/shardingsphere/database/exception/firebird/mapper/FirebirdDialectExceptionMapperTest.java
new file mode 100644
index 00000000000..7593ebbd061
--- /dev/null
+++
b/database/exception/dialect/firebird/src/test/java/org/apache/shardingsphere/database/exception/firebird/mapper/FirebirdDialectExceptionMapperTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.database.exception.firebird.mapper;
+
+import
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import
org.apache.shardingsphere.database.exception.core.exception.SQLDialectException;
+import
org.apache.shardingsphere.database.exception.core.exception.connection.AccessDeniedException;
+import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
+import
org.apache.shardingsphere.database.exception.core.mapper.SQLDialectExceptionMapper;
+import
org.apache.shardingsphere.database.exception.firebird.vendor.FirebirdVendorError;
+import
org.apache.shardingsphere.infra.exception.external.sql.vendor.VendorError;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.junit.jupiter.api.Test;
+
+import java.sql.SQLException;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.mockito.Mockito.mock;
+
+class FirebirdDialectExceptionMapperTest {
+
+ private final DatabaseType databaseType =
TypedSPILoader.getService(DatabaseType.class, "Firebird");
+
+ private final SQLDialectExceptionMapper mapper =
DatabaseTypedSPILoader.getService(SQLDialectExceptionMapper.class,
databaseType);
+
+ @Test
+ void assertConvertWithUnknownDatabase() {
+ assertSQLException(mapper.convert(new
UnknownDatabaseException("logic_db")),
FirebirdVendorError.UNAVAILABLE_DATABASE, "logic_db");
+ }
+
+ @Test
+ void assertConvertWithAccessDenied() {
+ assertSQLException(mapper.convert(new AccessDeniedException("root",
"127.0.0.1", true)), FirebirdVendorError.LOGIN_FAILED);
+ }
+
+ @Test
+ void assertConvertWithUnknownException() {
+ SQLException actual = mapper.convert(mock(SQLDialectException.class));
+ assertThat(actual.getSQLState(), is("HY000"));
+ }
+
+ private void assertSQLException(final SQLException actual, final
VendorError vendorError, final Object... messageArgs) {
+ assertThat(actual.getSQLState(),
is(vendorError.getSqlState().getValue()));
+ assertThat(actual.getErrorCode(), is(vendorError.getVendorCode()));
+ assertThat(actual.getMessage(),
is(String.format(vendorError.getReason(), messageArgs)));
+ }
+}
diff --git a/database/exception/dialect/pom.xml
b/database/exception/dialect/pom.xml
index 17f2584c363..35cd99a8e70 100644
--- a/database/exception/dialect/pom.xml
+++ b/database/exception/dialect/pom.xml
@@ -30,5 +30,6 @@
<modules>
<module>mysql</module>
<module>postgresql</module>
+ <module>firebird</module>
</modules>
</project>
diff --git a/database/protocol/dialect/firebird/pom.xml
b/database/protocol/dialect/firebird/pom.xml
index 2b84ba05c4d..98765c6fd80 100644
--- a/database/protocol/dialect/firebird/pom.xml
+++ b/database/protocol/dialect/firebird/pom.xml
@@ -42,6 +42,11 @@
<artifactId>shardingsphere-database-exception-core</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-database-exception-firebird</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.firebirdsql.jdbc</groupId>
diff --git
a/database/protocol/dialect/firebird/src/main/java/org/apache/shardingsphere/database/protocol/firebird/err/FirebirdStatusVector.java
b/database/protocol/dialect/firebird/src/main/java/org/apache/shardingsphere/database/protocol/firebird/err/FirebirdStatusVector.java
index 2ef6c55093a..a443e201fa3 100644
---
a/database/protocol/dialect/firebird/src/main/java/org/apache/shardingsphere/database/protocol/firebird/err/FirebirdStatusVector.java
+++
b/database/protocol/dialect/firebird/src/main/java/org/apache/shardingsphere/database/protocol/firebird/err/FirebirdStatusVector.java
@@ -36,7 +36,7 @@ public final class FirebirdStatusVector extends
FirebirdPacket {
public FirebirdStatusVector(final SQLException ex) {
gdsCode = ex.getErrorCode() >= ISCConstants.isc_arith_except ?
ex.getErrorCode() : ISCConstants.isc_random;
- String rawMessage = ex.getMessage();
+ String rawMessage = null == ex.getMessage() ? "" : ex.getMessage();
int idx = rawMessage.indexOf(';');
String message = idx >= 0 ? rawMessage.substring(idx + 1).trim() :
rawMessage;
int stateIdx = message.indexOf(" [SQLState:");
@@ -50,8 +50,10 @@ public final class FirebirdStatusVector extends
FirebirdPacket {
protected void write(final FirebirdPacketPayload payload) {
payload.writeInt4(ISCConstants.isc_arg_gds);
payload.writeInt4(gdsCode);
- payload.writeInt4(ISCConstants.isc_arg_string);
- payload.writeString(errorMessage);
+ if (!errorMessage.isEmpty()) {
+ payload.writeInt4(ISCConstants.isc_arg_string);
+ payload.writeString(errorMessage);
+ }
payload.writeInt4(ISCConstants.isc_arg_end);
}
}
diff --git
a/database/protocol/dialect/firebird/src/test/java/org/apache/shardingsphere/database/protocol/firebird/err/FirebirdStatusVectorTest.java
b/database/protocol/dialect/firebird/src/test/java/org/apache/shardingsphere/database/protocol/firebird/err/FirebirdStatusVectorTest.java
index 9760e664082..82aaa361496 100644
---
a/database/protocol/dialect/firebird/src/test/java/org/apache/shardingsphere/database/protocol/firebird/err/FirebirdStatusVectorTest.java
+++
b/database/protocol/dialect/firebird/src/test/java/org/apache/shardingsphere/database/protocol/firebird/err/FirebirdStatusVectorTest.java
@@ -54,6 +54,31 @@ class FirebirdStatusVectorTest {
verifyNoMoreInteractions(payload);
}
+ @Test
+ void assertWriteOmitsArgumentWhenMessageIsEmpty() {
+ SQLException emptyMessage = new SQLException("", "28000",
ISCConstants.isc_login);
+ FirebirdStatusVector vector = new FirebirdStatusVector(emptyMessage);
+ vector.write(payload);
+ InOrder inOrder = inOrder(payload);
+ inOrder.verify(payload).writeInt4(ISCConstants.isc_arg_gds);
+ inOrder.verify(payload).writeInt4(ISCConstants.isc_login);
+ inOrder.verify(payload).writeInt4(ISCConstants.isc_arg_end);
+ verifyNoMoreInteractions(payload);
+ }
+
+ @Test
+ void assertWriteWithNullMessage() {
+ SQLException nullMessage = new SQLException(null, "28000",
ISCConstants.isc_login);
+ FirebirdStatusVector vector = new FirebirdStatusVector(nullMessage);
+ assertThat(vector.getErrorMessage(), is(""));
+ vector.write(payload);
+ InOrder inOrder = inOrder(payload);
+ inOrder.verify(payload).writeInt4(ISCConstants.isc_arg_gds);
+ inOrder.verify(payload).writeInt4(ISCConstants.isc_login);
+ inOrder.verify(payload).writeInt4(ISCConstants.isc_arg_end);
+ verifyNoMoreInteractions(payload);
+ }
+
@Test
void assertWriteUsesRandomCodeWhenErrorCodeIsLowerThanArithExcept() {
SQLException plainMessage = new SQLException("plain", "00000",
ISCConstants.isc_arith_except - 1);
diff --git
a/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/authentication/FirebirdAuthenticationEngine.java
b/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/authentication/FirebirdAuthenticationEngine.java
index cbd172e794f..8357a139d9c 100644
---
a/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/authentication/FirebirdAuthenticationEngine.java
+++
b/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/authentication/FirebirdAuthenticationEngine.java
@@ -17,7 +17,6 @@
package org.apache.shardingsphere.proxy.frontend.firebird.authentication;
-import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import io.netty.channel.ChannelHandlerContext;
import org.apache.shardingsphere.authentication.AuthenticatorFactory;
@@ -25,6 +24,7 @@ import
org.apache.shardingsphere.authentication.AuthenticatorType;
import org.apache.shardingsphere.authentication.result.AuthenticationResult;
import
org.apache.shardingsphere.authentication.result.AuthenticationResultBuilder;
import org.apache.shardingsphere.authority.rule.AuthorityRule;
+import
org.apache.shardingsphere.database.exception.core.exception.connection.AccessDeniedException;
import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
import org.apache.shardingsphere.database.protocol.constant.CommonConstants;
import
org.apache.shardingsphere.database.protocol.firebird.constant.FirebirdAuthenticationMethod;
@@ -109,9 +109,10 @@ public final class FirebirdAuthenticationEngine implements
AuthenticationEngine
Strings.isNullOrEmpty(databaseName) ||
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().containsDatabase(databaseName),
() -> new UnknownDatabaseException(databaseName));
Grantee grantee = new Grantee(username, "");
- Optional<ShardingSphereUser> user = rule.findUser(grantee);
- user.ifPresent(shardingSphereUser -> new
AuthenticatorFactory<>(FirebirdAuthenticatorType.class, rule)
-
.newInstance(shardingSphereUser).authenticate(shardingSphereUser, new
Object[]{attachPacket.getEncPassword(), authData, attachPacket.getAuthData()}));
+ ShardingSphereUser user = rule.findUser(grantee).orElseThrow(() -> new
AccessDeniedException(username, "", true));
+ boolean authenticated = new
AuthenticatorFactory<>(FirebirdAuthenticatorType.class, rule)
+ .newInstance(user).authenticate(user, new
Object[]{attachPacket.getEncPassword(), authData, attachPacket.getAuthData()});
+ ShardingSpherePreconditions.checkState(authenticated, () -> new
AccessDeniedException(username, "", true));
}
private AuthenticationResult processConnect(final ChannelHandlerContext
context, final FirebirdPacketPayload payload, final AuthorityRule rule) {
@@ -123,7 +124,7 @@ public final class FirebirdAuthenticationEngine implements
AuthenticationEngine
String username = connectPacket.getLogin();
Grantee grantee = new Grantee(username, "");
Optional<ShardingSphereUser> user = rule.findUser(grantee);
- Preconditions.checkState(user.isPresent());
+ ShardingSpherePreconditions.checkState(user.isPresent(), () -> new
AccessDeniedException(username, connectPacket.getHost(), true));
FirebirdAuthenticationMethod plugin =
FirebirdAuthenticationMethod.valueOf(getPluginName(rule, user.get()));
FirebirdAuthenticationMethod userPlugin = connectPacket.getPlugin();
if (plugin != userPlugin) {
diff --git
a/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/authentication/FirebirdAuthenticationEngineTest.java
b/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/authentication/FirebirdAuthenticationEngineTest.java
index e72fcbcdee4..25356587f5b 100644
---
a/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/authentication/FirebirdAuthenticationEngineTest.java
+++
b/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/authentication/FirebirdAuthenticationEngineTest.java
@@ -24,6 +24,7 @@ import
org.apache.shardingsphere.authentication.AuthenticatorFactory;
import org.apache.shardingsphere.authentication.result.AuthenticationResult;
import
org.apache.shardingsphere.authentication.result.AuthenticationResultBuilder;
import org.apache.shardingsphere.authority.rule.AuthorityRule;
+import
org.apache.shardingsphere.database.exception.core.exception.connection.AccessDeniedException;
import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
import org.apache.shardingsphere.database.protocol.constant.CommonConstants;
import
org.apache.shardingsphere.database.protocol.firebird.constant.FirebirdAuthenticationMethod;
@@ -231,6 +232,7 @@ class FirebirdAuthenticationEngineTest {
Plugins.getMemberAccessor().set(FirebirdAuthenticationEngine.class.getDeclaredField("authData"),
authenticationEngine, authData);
FirebirdPacketPayload payload =
mockFirebirdPayload(FirebirdCommandPacketType.ATTACH);
FirebirdAuthenticator authenticator =
mock(FirebirdAuthenticator.class);
+ lenient().when(authenticator.authenticate(any(),
any())).thenReturn(true);
if (expectException) {
try (MockedConstruction<FirebirdAttachPacket> ignored =
mockConstruction(FirebirdAttachPacket.class, (attachPacket, construction) -> {
when(attachPacket.getEncoding()).thenReturn(encoding);
@@ -266,6 +268,72 @@ class FirebirdAuthenticationEngineTest {
}
}
+ @Test
+ void assertAuthenticateConnectWithUnknownUser() {
+ AuthorityRule rule = mock(AuthorityRule.class);
+ when(rule.findUser(any(Grantee.class))).thenReturn(Optional.empty());
+ mockProxyContext(rule, true);
+ Attribute<Charset> charsetAttr = mock(Attribute.class);
+ Attribute<FirebirdProtocolVersion> protocolVersionAttr =
mock(Attribute.class);
+
when(context.channel().attr(CommonConstants.CHARSET_ATTRIBUTE_KEY)).thenReturn(charsetAttr);
+
when(context.channel().attr(FirebirdConstant.CONNECTION_PROTOCOL_VERSION)).thenReturn(protocolVersionAttr);
+ FirebirdProtocol protocol = mock(FirebirdProtocol.class);
+
when(protocol.getVersion()).thenReturn(FirebirdProtocolVersion.PROTOCOL_VERSION10);
+ List<FirebirdProtocol> userProtocols = new
ArrayList<>(Collections.singletonList(protocol));
+ FirebirdPacketPayload payload =
mockFirebirdPayload(FirebirdCommandPacketType.CONNECT);
+ try (MockedConstruction<FirebirdConnectPacket> ignored =
mockConstruction(FirebirdConnectPacket.class, (mockConnect, construction) -> {
+ when(mockConnect.getUserProtocols()).thenReturn(userProtocols);
+ when(mockConnect.getLogin()).thenReturn("absent");
+ when(mockConnect.getHost()).thenReturn("host");
+ })) {
+ assertThrows(AccessDeniedException.class, () ->
authenticationEngine.authenticate(context, payload));
+ }
+ }
+
+ @SneakyThrows(ReflectiveOperationException.class)
+ @Test
+ void assertAuthenticateAttachWithUnknownUser() {
+ AuthorityRule rule = mock(AuthorityRule.class);
+ when(rule.findUser(any(Grantee.class))).thenReturn(Optional.empty());
+ mockProxyContext(rule, true);
+ Attribute<Charset> charsetAttr = mock(Attribute.class);
+
when(context.channel().attr(CommonConstants.CHARSET_ATTRIBUTE_KEY)).thenReturn(charsetAttr);
+
Plugins.getMemberAccessor().set(FirebirdAuthenticationEngine.class.getDeclaredField("currentAuthResult"),
authenticationEngine,
+ AuthenticationResultBuilder.continued("absent", "", "db"));
+ FirebirdPacketPayload payload =
mockFirebirdPayload(FirebirdCommandPacketType.ATTACH);
+ try (MockedConstruction<FirebirdAttachPacket> ignored =
mockConstruction(FirebirdAttachPacket.class, (attachPacket, construction) ->
when(attachPacket.getEncoding()).thenReturn("UTF8"))) {
+ assertThrows(AccessDeniedException.class, () ->
authenticationEngine.authenticate(context, payload));
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ @SneakyThrows(ReflectiveOperationException.class)
+ @Test
+ void assertAuthenticateAttachWithWrongPassword() {
+ AuthorityRule rule = mock(AuthorityRule.class);
+ ShardingSphereUser user = new ShardingSphereUser("root", "pwd", "");
+ when(rule.findUser(any(Grantee.class))).thenReturn(Optional.of(user));
+ mockProxyContext(rule, true);
+ Attribute<Charset> charsetAttr = mock(Attribute.class);
+
when(context.channel().attr(CommonConstants.CHARSET_ATTRIBUTE_KEY)).thenReturn(charsetAttr);
+
Plugins.getMemberAccessor().set(FirebirdAuthenticationEngine.class.getDeclaredField("currentAuthResult"),
authenticationEngine,
+ AuthenticationResultBuilder.continued("root", "", "db"));
+ FirebirdSRPAuthenticationData authData =
mock(FirebirdSRPAuthenticationData.class);
+
Plugins.getMemberAccessor().set(FirebirdAuthenticationEngine.class.getDeclaredField("authData"),
authenticationEngine, authData);
+ FirebirdAuthenticator authenticator =
mock(FirebirdAuthenticator.class);
+ when(authenticator.authenticate(any(), any())).thenReturn(false);
+ FirebirdPacketPayload payload =
mockFirebirdPayload(FirebirdCommandPacketType.ATTACH);
+ try (MockedConstruction<FirebirdAttachPacket> ignoredPacket =
mockConstruction(FirebirdAttachPacket.class, (attachPacket, construction) -> {
+ when(attachPacket.getEncoding()).thenReturn("UTF8");
+ when(attachPacket.getEncPassword()).thenReturn("cipher_pwd");
+ when(attachPacket.getAuthData()).thenReturn("client_auth");
+ });
+ MockedConstruction<AuthenticatorFactory> ignoredFactory =
mockConstruction(AuthenticatorFactory.class,
+ (factory, construction) ->
when(factory.newInstance(user)).thenReturn(authenticator))) {
+ assertThrows(AccessDeniedException.class, () ->
authenticationEngine.authenticate(context, payload));
+ }
+ }
+
private FirebirdPacketPayload mockFirebirdPayload(final
FirebirdCommandPacketType commandPacketType) {
FirebirdPacketPayload result = mock(FirebirdPacketPayload.class,
RETURNS_DEEP_STUBS);
when(result.readInt4()).thenReturn(commandPacketType.getValue());
@@ -294,8 +362,7 @@ class FirebirdAuthenticationEngineTest {
private static Stream<Arguments> attachArguments() {
return Stream.of(
Arguments.of("attachWithUser", true, new
ShardingSphereUser("root", "pwd", ""), "root", "db", "UTF8", false, true, true,
"db", "root", "cipher_pwd", "client_auth"),
- Arguments.of("attachWithoutUser", true, null, "absent", "db",
"NONE", false, false, true, "db", "absent", null, null),
Arguments.of("attachUnknownDatabase", false, new
ShardingSphereUser("root", "pwd", ""), "root", "missing_db", "UTF8", true,
false, false, "", "root", null, null),
- Arguments.of("attachEmptyDatabase", false, null, "root", "",
"NONE", false, false, true, "", "root", null, null));
+ Arguments.of("attachEmptyDatabase", false, new
ShardingSphereUser("root", "pwd", ""), "root", "", "NONE", false, true, true,
"", "root", "cipher_pwd", "client_auth"));
}
}
diff --git
a/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/err/FirebirdErrorPacketFactoryTest.java
b/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/err/FirebirdErrorPacketFactoryTest.java
index 741345b8c47..5bf1fae1753 100644
---
a/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/err/FirebirdErrorPacketFactoryTest.java
+++
b/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/err/FirebirdErrorPacketFactoryTest.java
@@ -17,6 +17,8 @@
package org.apache.shardingsphere.proxy.frontend.firebird.err;
+import
org.apache.shardingsphere.database.exception.core.exception.connection.AccessDeniedException;
+import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
import
org.apache.shardingsphere.database.protocol.firebird.packet.generic.FirebirdGenericResponsePacket;
import org.junit.jupiter.api.Test;
@@ -41,6 +43,20 @@ class FirebirdErrorPacketFactoryTest {
assertThat(actual.getErrorMessage(), is("Table not found"));
}
+ @Test
+ void assertNewInstanceWithUnknownDatabaseException() {
+ FirebirdGenericResponsePacket actual = (FirebirdGenericResponsePacket)
FirebirdErrorPacketFactory.newInstance(new
UnknownDatabaseException("logic_db"));
+ assertThat(actual.getErrorCode(), is(335544375));
+ assertThat(actual.getErrorMessage(), is("logic_db"));
+ }
+
+ @Test
+ void assertNewInstanceWithAccessDeniedException() {
+ FirebirdGenericResponsePacket actual = (FirebirdGenericResponsePacket)
FirebirdErrorPacketFactory.newInstance(new AccessDeniedException("root",
"127.0.0.1", true));
+ assertThat(actual.getErrorCode(), is(335544472));
+ assertThat(actual.getErrorMessage(), is(""));
+ }
+
@Test
void assertNewInstanceWithNonFirebirdErrorCode() {
FirebirdGenericResponsePacket actual = (FirebirdGenericResponsePacket)
FirebirdErrorPacketFactory.newInstance(new SQLException("Invalid error",
"HY000", 123));