Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class BigQueryConversionException extends SQLException {
new BigQueryJdbcCustomLogger(BigQueryConversionException.class.getName());

public BigQueryConversionException(String message, Throwable cause) {
super(message, cause);
LOG.severe(message, this);
super(BigQueryJdbcExceptionUtils.formatMessage(message, cause), cause);
LOG.severe(this.getMessage(), this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class BigQueryJdbcCoercionException extends RuntimeException {
* @param cause the actual cause which was thrown while performing the coercion.
*/
public BigQueryJdbcCoercionException(Exception cause) {
super("Coercion error", cause);
LOG.severe("Coercion error", this);
super(BigQueryJdbcExceptionUtils.formatMessage("Coercion error", cause), cause);
LOG.severe(this.getMessage(), this);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: My latest PR removes the severe logs from the exception classes. You can leave these unedited, it will be removed later.

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ public BigQueryJdbcException(InterruptedException ex) {
* @param ex The BigQueryException to be thrown.
*/
public BigQueryJdbcException(String message, BigQueryException ex) {
super(message, ex);
super(BigQueryJdbcExceptionUtils.formatMessage(message, ex), ex);
this.bigQueryException = ex;
LOG.severe(ex.getMessage(), this);
LOG.severe(this.getMessage(), this);
}

/**
Expand All @@ -64,8 +64,8 @@ public BigQueryJdbcException(String message, BigQueryException ex) {
* @param cause Throwable that is being converted.
*/
public BigQueryJdbcException(String message, Throwable cause) {
super(message, cause);
LOG.severe(message, this);
super(BigQueryJdbcExceptionUtils.formatMessage(message, cause), cause);
LOG.severe(this.getMessage(), this);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2026 Google LLC
*
* Licensed 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 com.google.cloud.bigquery.exception;

/** Utility class for JDBC exceptions. */
final class BigQueryJdbcExceptionUtils {

private BigQueryJdbcExceptionUtils() {
// Utility class, prevent instantiation
}

/**
* Formats the exception message by appending the cause's message (or toString if null) on a
* newline.
*
* @param message The custom detail message.
* @param cause The underlying cause of the exception.
* @return The formatted message.
*/
public static String formatMessage(String message, Throwable cause) {
return message
+ (cause != null
? "\n" + (cause.getMessage() != null ? cause.getMessage() : cause.toString())
: "");
}
Comment thread
logachev marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ public BigQueryJdbcRuntimeException(Throwable ex) {
* @param ex Throwable to be thrown.
*/
public BigQueryJdbcRuntimeException(String message, InterruptedException ex) {
super(message, ex);
LOG.severe(message, this);
super(BigQueryJdbcExceptionUtils.formatMessage(message, ex), ex);
LOG.severe(this.getMessage(), this);
}

public BigQueryJdbcRuntimeException(String message, Throwable ex) {
super(message, ex);
LOG.severe(message, this);
super(BigQueryJdbcExceptionUtils.formatMessage(message, ex), ex);
LOG.severe(this.getMessage(), this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public BigQueryJdbcSqlSyntaxErrorException(BigQueryException ex) {
}

public BigQueryJdbcSqlSyntaxErrorException(String message, BigQueryException ex) {
super(message, ex);
LOG.severe(message, this);
super(BigQueryJdbcExceptionUtils.formatMessage(message, ex), ex);
LOG.severe(this.getMessage(), this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright 2026 Google LLC
*
* Licensed 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 com.google.cloud.bigquery.exception;

import static org.junit.jupiter.api.Assertions.assertEquals;

import com.google.cloud.bigquery.BigQueryException;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

public class BigQueryJdbcExceptionTest {

@FunctionalInterface
interface ExceptionCreator {
Throwable create(String message, Throwable cause);
}

static Stream<Arguments> exceptionProvider() {
return Stream.of(
Arguments.of(
(ExceptionCreator)
(msg, cause) -> new BigQueryJdbcException(msg, (BigQueryException) cause)),
Arguments.of((ExceptionCreator) BigQueryJdbcException::new),
Arguments.of((ExceptionCreator) BigQueryJdbcRuntimeException::new),
Arguments.of((ExceptionCreator) BigQueryConversionException::new),
Arguments.of(
(ExceptionCreator)
(msg, cause) -> new BigQueryJdbcCoercionException((Exception) cause)),
Arguments.of(
(ExceptionCreator)
(msg, cause) ->
new BigQueryJdbcSqlSyntaxErrorException(msg, (BigQueryException) cause)));
}

@ParameterizedTest
@MethodSource("exceptionProvider")
public void testExceptionMessageFormatting(ExceptionCreator creator) {
String message = "Custom error message";
Throwable cause = new BigQueryException(500, "Underlying error");

Throwable ex = creator.create(message, cause);

String expectedPrefix =
ex instanceof BigQueryJdbcCoercionException ? "Coercion error" : message;
String expectedMessage = expectedPrefix + "\n" + cause.getMessage();
Comment thread
logachev marked this conversation as resolved.

assertEquals(expectedMessage, ex.getMessage());
assertEquals(cause, ex.getCause());
}

@Test
public void testException_withCauseHavingNullMessage() {
String message = "Custom error message";
Throwable cause = new RuntimeException(); // Null message

BigQueryJdbcException ex = new BigQueryJdbcException(message, cause);

String expectedMessage = message + "\n" + cause.toString();
assertEquals(expectedMessage, ex.getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void shouldThrowCoercionException() {
assertThrows(
BigQueryJdbcCoercionException.class,
() -> bigQueryTypeCoercer.coerceTo(Integer.class, 2147483648L));
assertThat(exception.getMessage()).isEqualTo("Coercion error");
assertThat(exception.getMessage()).isEqualTo("Coercion error\ninteger overflow");
assertThat(exception.getCause()).isInstanceOf(ArithmeticException.class);
}

Expand Down
Loading