From c931c86896958e4b2f4986a17c6a9c0c17d266f1 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 20 Dec 2023 17:45:28 +0100 Subject: [PATCH] HHH-17506 Return exceptions instead of throwing them in SQLExceptionConversionDelegate --- .../community/dialect/DB2LegacyDialect.java | 7 ++--- .../community/dialect/DerbyLegacyDialect.java | 2 +- .../dialect/OracleLegacyDialect.java | 8 ++--- .../dialect/SQLServerLegacyDialect.java | 31 ++++++++++++++++--- .../dialect/SybaseASELegacyDialect.java | 2 +- .../dialect/AbstractHANADialect.java | 2 +- .../org/hibernate/dialect/DB2Dialect.java | 7 ++--- .../org/hibernate/dialect/DerbyDialect.java | 2 +- .../org/hibernate/dialect/OracleDialect.java | 8 ++--- .../hibernate/dialect/SQLServerDialect.java | 11 +++++-- .../hibernate/dialect/SybaseASEDialect.java | 2 +- .../internal/SQLExceptionTypeDelegate.java | 2 +- .../internal/SQLStateConversionDelegate.java | 2 +- .../internal/JdbcValuesResultSetImpl.java | 21 +++++++++---- 14 files changed, 70 insertions(+), 37 deletions(-) diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java index 6ae54dfdd5..e3d6a35360 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java @@ -892,11 +892,10 @@ public class DB2LegacyDialect extends Dialect { @Override public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() { return (sqlException, message, sql) -> { - final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException ); final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException ); - - if ( -952 == errorCode && "57014".equals( sqlState ) ) { - throw new LockTimeoutException( message, sqlException, sql ); + switch ( errorCode ) { + case -952: + return new LockTimeoutException( message, sqlException, sql ); } return null; }; diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java index 3f4cbfc133..1616eafae2 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java @@ -716,7 +716,7 @@ public class DerbyLegacyDialect extends Dialect { switch ( sqlState ) { case "40XL1": case "40XL2": - throw new LockTimeoutException( message, sqlException, sql ); + return new LockTimeoutException( message, sqlException, sql ); } } return null; diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java index 940dc94b81..4e1553fd1d 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java @@ -1015,13 +1015,13 @@ public class OracleLegacyDialect extends Dialect { case 30006: // ORA-30006: resource busy; acquire with WAIT timeout expired - throw new LockTimeoutException(message, sqlException, sql); + return new LockTimeoutException(message, sqlException, sql); case 54: // ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired - throw new LockTimeoutException(message, sqlException, sql); + return new LockTimeoutException(message, sqlException, sql); case 4021: // ORA-04021 timeout occurred while waiting to lock object - throw new LockTimeoutException(message, sqlException, sql); + return new LockTimeoutException(message, sqlException, sql); // deadlocks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1036,7 +1036,7 @@ public class OracleLegacyDialect extends Dialect { case 1013: // ORA-01013: user requested cancel of current operation - throw new QueryTimeoutException( message, sqlException, sql ); + return new QueryTimeoutException( message, sqlException, sql ); // data integrity violation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacyDialect.java index b3f0440b4b..642b262770 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacyDialect.java @@ -731,14 +731,25 @@ public class SQLServerLegacyDialect extends AbstractTransactSQLDialect { } return (sqlException, message, sql) -> { final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException ); - final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException ); if ( "HY008".equals( sqlState ) ) { - throw new QueryTimeoutException( message, sqlException, sql ); + return new QueryTimeoutException( message, sqlException, sql ); } - if ( 1222 == errorCode ) { - throw new LockTimeoutException( message, sqlException, sql ); + + final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException ); + switch ( errorCode ) { + case 1222: + return new LockTimeoutException( message, sqlException, sql ); + case 2627: + case 2601: + return new ConstraintViolationException( + message, + sqlException, + sql, + getViolatedConstraintNameExtractor().extractConstraintName( sqlException ) + ); + default: + return null; } - return null; }; } @@ -1105,4 +1116,14 @@ public class SQLServerLegacyDialect extends AbstractTransactSQLDialect { // public String getEnableConstraintStatement(String tableName, String name) { // return "alter table " + tableName + " with check check constraint " + name; // } + + @Override + public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() { + return DmlTargetColumnQualifierSupport.TABLE_ALIAS; + } + + @Override + public boolean supportsFromClauseInUpdate() { + return true; + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacyDialect.java index 9a8a9b9ed0..e219369c68 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacyDialect.java @@ -667,7 +667,7 @@ public class SybaseASELegacyDialect extends SybaseLegacyDialect { switch ( sqlState ) { case "JZ0TO": case "JZ006": - throw new LockTimeoutException( message, sqlException, sql ); + return new LockTimeoutException( message, sqlException, sql ); case "S1000": switch ( errorCode ) { case 515: diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java index acad94b8e7..4a40280a7b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java @@ -515,7 +515,7 @@ public abstract class AbstractHANADialect extends Dialect { // 262 - Invalid query name // 263 - Invalid alias name if ( errorCode == 257 || ( errorCode >= 259 && errorCode <= 263 ) ) { - throw new SQLGrammarException( message, sqlException, sql ); + return new SQLGrammarException( message, sqlException, sql ); } // 257 - Cannot insert NULL or update to NULL diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java index a8aba81b1d..1abe8c44f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -976,11 +976,10 @@ public class DB2Dialect extends Dialect { @Override public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() { return (sqlException, message, sql) -> { - final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException ); final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException ); - - if ( -952 == errorCode && "57014".equals( sqlState ) ) { - throw new LockTimeoutException( message, sqlException, sql ); + switch ( errorCode ) { + case -952: + return new LockTimeoutException( message, sqlException, sql ); } return null; }; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java index a4756a523b..339665ac2a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java @@ -700,7 +700,7 @@ public class DerbyDialect extends Dialect { switch ( sqlState ) { case "40XL1": case "40XL2": - throw new LockTimeoutException( message, sqlException, sql ); + return new LockTimeoutException( message, sqlException, sql ); } } return null; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java index 44c7236ee2..f88e29224c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java @@ -1055,13 +1055,13 @@ public class OracleDialect extends Dialect { case 30006: // ORA-30006: resource busy; acquire with WAIT timeout expired - throw new LockTimeoutException(message, sqlException, sql); + return new LockTimeoutException(message, sqlException, sql); case 54: // ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired - throw new LockTimeoutException(message, sqlException, sql); + return new LockTimeoutException(message, sqlException, sql); case 4021: // ORA-04021 timeout occurred while waiting to lock object - throw new LockTimeoutException(message, sqlException, sql); + return new LockTimeoutException(message, sqlException, sql); // deadlocks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1076,7 +1076,7 @@ public class OracleDialect extends Dialect { case 1013: // ORA-01013: user requested cancel of current operation - throw new QueryTimeoutException( message, sqlException, sql ); + return new QueryTimeoutException( message, sqlException, sql ); // data integrity violation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java index 36f2aac602..7f69f440ca 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java @@ -704,16 +704,21 @@ public class SQLServerDialect extends AbstractTransactSQLDialect { return (sqlException, message, sql) -> { final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException ); if ( "HY008".equals( sqlState ) ) { - throw new QueryTimeoutException( message, sqlException, sql ); + return new QueryTimeoutException( message, sqlException, sql ); } final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException ); switch ( errorCode ) { case 1222: - throw new LockTimeoutException( message, sqlException, sql ); + return new LockTimeoutException( message, sqlException, sql ); case 2627: case 2601: - throw new ConstraintViolationException( message, sqlException, sql ); + return new ConstraintViolationException( + message, + sqlException, + sql, + getViolatedConstraintNameExtractor().extractConstraintName( sqlException ) + ); default: return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java index 87d4a484a0..404adaeacb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java @@ -669,7 +669,7 @@ public class SybaseASEDialect extends SybaseDialect { switch ( sqlState ) { case "JZ0TO": case "JZ006": - throw new LockTimeoutException( message, sqlException, sql ); + return new LockTimeoutException( message, sqlException, sql ); case "S1000": switch ( errorCode ) { case 515: diff --git a/hibernate-core/src/main/java/org/hibernate/exception/internal/SQLExceptionTypeDelegate.java b/hibernate-core/src/main/java/org/hibernate/exception/internal/SQLExceptionTypeDelegate.java index b3cae2ff7a..93cf6bfbdb 100644 --- a/hibernate-core/src/main/java/org/hibernate/exception/internal/SQLExceptionTypeDelegate.java +++ b/hibernate-core/src/main/java/org/hibernate/exception/internal/SQLExceptionTypeDelegate.java @@ -52,7 +52,7 @@ public class SQLExceptionTypeDelegate extends AbstractSQLExceptionConversionDele } else if ( sqlException instanceof DataTruncation || sqlException instanceof SQLDataException ) { - throw new DataException( message, sqlException, sql ); + return new DataException( message, sqlException, sql ); } else if ( sqlException instanceof SQLIntegrityConstraintViolationException ) { return new ConstraintViolationException( diff --git a/hibernate-core/src/main/java/org/hibernate/exception/internal/SQLStateConversionDelegate.java b/hibernate-core/src/main/java/org/hibernate/exception/internal/SQLStateConversionDelegate.java index 331492ea03..9dd1f4393a 100644 --- a/hibernate-core/src/main/java/org/hibernate/exception/internal/SQLStateConversionDelegate.java +++ b/hibernate-core/src/main/java/org/hibernate/exception/internal/SQLStateConversionDelegate.java @@ -117,7 +117,7 @@ public class SQLStateConversionDelegate extends AbstractSQLExceptionConversionDe if ( "70100".equals( sqlState ) || // Oracle user requested cancel of current operation ( "72000".equals( sqlState ) && errorCode == 1013 ) ) { - throw new QueryTimeoutException( message, sqlException, sql ); + return new QueryTimeoutException( message, sqlException, sql ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesResultSetImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesResultSetImpl.java index 94eb02045d..db81408521 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesResultSetImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesResultSetImpl.java @@ -11,10 +11,14 @@ import java.sql.SQLException; import java.util.Arrays; import java.util.BitSet; +import org.hibernate.JDBCException; +import org.hibernate.QueryTimeoutException; import org.hibernate.cache.spi.QueryKey; import org.hibernate.cache.spi.QueryResultsCache; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.exception.DataException; +import org.hibernate.exception.LockTimeoutException; import org.hibernate.query.spi.QueryOptions; import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.exec.ExecutionException; @@ -259,13 +263,18 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues { } private ExecutionException makeExecutionException(String message, SQLException cause) { - return new ExecutionException( - message + " [" + cause.getMessage() + "]", - executionContext.getSession().getJdbcServices().getSqlExceptionHelper().convert( - cause, - message - ) + final JDBCException jdbcException = executionContext.getSession().getJdbcServices().getSqlExceptionHelper().convert( + cause, + message ); + if ( jdbcException instanceof QueryTimeoutException + || jdbcException instanceof DataException + || jdbcException instanceof LockTimeoutException ) { + // So far, the exception helper threw these exceptions more or less directly during conversion, + // so to retain the same behavior, we throw that directly now as well instead of wrapping it + throw jdbcException; + } + return new ExecutionException( message + " [" + cause.getMessage() + "]", jdbcException ); } private void readCurrentRowValues() {