HHH-15592 Fix NPE for uses of JdbcExceptionHelper.extractSqlState

This commit is contained in:
Christian Beikov 2022-10-11 15:32:27 +02:00
parent 4b24bcf7af
commit 6b6cd51edf
9 changed files with 242 additions and 169 deletions

View File

@ -647,8 +647,12 @@ public class DerbyLegacyDialect extends Dialect {
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
// final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException );
if ( "40XL1".equals( sqlState ) || "40XL2".equals( sqlState ) ) {
throw new LockTimeoutException( message, sqlException, sql );
if ( sqlState != null ) {
switch ( sqlState ) {
case "40XL1":
case "40XL2":
throw new LockTimeoutException( message, sqlException, sql );
}
}
return null;
};

View File

@ -719,12 +719,14 @@ public class MySQLLegacyDialect extends Dialect {
private static final ViolatedConstraintNameExtractor EXTRACTOR =
new TemplatedViolatedConstraintNameExtractor( sqle -> {
switch ( Integer.parseInt( JdbcExceptionHelper.extractSqlState( sqle ) ) ) {
case 23000:
return extractUsingTemplate( " for key '", "'", sqle.getMessage() );
default:
return null;
final String sqlState = JdbcExceptionHelper.extractSqlState( sqle );
if ( sqlState != null ) {
switch ( Integer.parseInt( sqlState ) ) {
case 23000:
return extractUsingTemplate( " for key '", "'", sqle.getMessage() );
}
}
return null;
} );
@Override

View File

@ -872,44 +872,54 @@ public class PostgreSQLLegacyDialect extends Dialect {
*/
private static final ViolatedConstraintNameExtractor EXTRACTOR =
new TemplatedViolatedConstraintNameExtractor( sqle -> {
switch ( Integer.parseInt( JdbcExceptionHelper.extractSqlState( sqle ) ) ) {
// CHECK VIOLATION
case 23514:
return extractUsingTemplate( "violates check constraint \"","\"", sqle.getMessage() );
// UNIQUE VIOLATION
case 23505:
return extractUsingTemplate( "violates unique constraint \"","\"", sqle.getMessage() );
// FOREIGN KEY VIOLATION
case 23503:
return extractUsingTemplate( "violates foreign key constraint \"","\"", sqle.getMessage() );
// NOT NULL VIOLATION
case 23502:
return extractUsingTemplate( "null value in column \"","\" violates not-null constraint", sqle.getMessage() );
// TODO: RESTRICT VIOLATION
case 23001:
return null;
// ALL OTHER
default:
return null;
final String sqlState = JdbcExceptionHelper.extractSqlState( sqle );
if ( sqlState != null ) {
switch ( Integer.parseInt( sqlState ) ) {
// CHECK VIOLATION
case 23514:
return extractUsingTemplate( "violates check constraint \"", "\"", sqle.getMessage() );
// UNIQUE VIOLATION
case 23505:
return extractUsingTemplate( "violates unique constraint \"", "\"", sqle.getMessage() );
// FOREIGN KEY VIOLATION
case 23503:
return extractUsingTemplate(
"violates foreign key constraint \"",
"\"",
sqle.getMessage()
);
// NOT NULL VIOLATION
case 23502:
return extractUsingTemplate(
"null value in column \"",
"\" violates not-null constraint",
sqle.getMessage()
);
// TODO: RESTRICT VIOLATION
case 23001:
return null;
}
}
return null;
} );
@Override
public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
return (sqlException, message, sql) -> {
switch ( JdbcExceptionHelper.extractSqlState( sqlException ) ) {
case "40P01":
// DEADLOCK DETECTED
return new LockAcquisitionException(message, sqlException, sql);
case "55P03":
// LOCK NOT AVAILABLE
return new PessimisticLockException(message, sqlException, sql);
case "57014":
return new QueryTimeoutException( message, sqlException, sql );
default:
// returning null allows other delegates to operate
return null;
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
if ( sqlState != null ) {
switch ( sqlState ) {
case "40P01":
// DEADLOCK DETECTED
return new LockAcquisitionException( message, sqlException, sql );
case "55P03":
// LOCK NOT AVAILABLE
return new PessimisticLockException( message, sqlException, sql );
case "57014":
return new QueryTimeoutException( message, sqlException, sql );
}
}
return null;
};
}

View File

@ -642,20 +642,22 @@ public class SybaseASELegacyDialect extends SybaseLegacyDialect {
*/
private static final ViolatedConstraintNameExtractor EXTRACTOR =
new TemplatedViolatedConstraintNameExtractor( sqle -> {
final String sqlState = JdbcExceptionHelper.extractSqlState( sqle );
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
switch ( JdbcExceptionHelper.extractSqlState( sqle ) ) {
// UNIQUE VIOLATION
case "S1000":
if (2601 == errorCode) {
return extractUsingTemplate( "with unique index '", "'", sqle.getMessage() );
}
break;
case "23000":
if (546 == errorCode) {
// Foreign key violation
return extractUsingTemplate( "constraint name = '", "'", sqle.getMessage() );
}
break;
if ( sqlState != null ) {
switch ( sqlState ) {
// UNIQUE VIOLATION
case "S1000":
if ( 2601 == errorCode ) {
return extractUsingTemplate( "with unique index '", "'", sqle.getMessage() );
}
break;
case "23000":
if ( 546 == errorCode ) {
// Foreign key violation
return extractUsingTemplate( "constraint name = '", "'", sqle.getMessage() );
}
break;
// // FOREIGN KEY VIOLATION
// case 23503:
// return extractUsingTemplate( "violates foreign key constraint \"","\"", sqle.getMessage() );
@ -665,9 +667,7 @@ public class SybaseASELegacyDialect extends SybaseLegacyDialect {
// // TODO: RESTRICT VIOLATION
// case 23001:
// return null;
// ALL OTHER
default:
return null;
}
}
return null;
} );
@ -681,34 +681,39 @@ public class SybaseASELegacyDialect extends SybaseLegacyDialect {
return (sqlException, message, sql) -> {
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException );
switch ( sqlState ) {
case "JZ0TO":
case "JZ006":
throw new LockTimeoutException( message, sqlException, sql );
case "S1000":
switch ( errorCode ) {
case 515:
if ( sqlState != null ) {
switch ( sqlState ) {
case "JZ0TO":
case "JZ006":
throw new LockTimeoutException( message, sqlException, sql );
case "S1000":
switch ( errorCode ) {
case 515:
// Attempt to insert NULL value into column; column does not allow nulls.
case 2601:
// Unique constraint violation
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName(
sqlException );
return new ConstraintViolationException( message, sqlException, sql, constraintName );
}
break;
case "ZZZZZ":
if ( 515 == errorCode ) {
// Attempt to insert NULL value into column; column does not allow nulls.
case 2601:
// Unique constraint violation
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName( sqlException );
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName(
sqlException );
return new ConstraintViolationException( message, sqlException, sql, constraintName );
}
break;
case "ZZZZZ":
if (515 == errorCode) {
// Attempt to insert NULL value into column; column does not allow nulls.
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName( sqlException );
return new ConstraintViolationException( message, sqlException, sql, constraintName );
}
break;
case "23000":
if (546 == errorCode) {
// Foreign key violation
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName( sqlException );
return new ConstraintViolationException( message, sqlException, sql, constraintName );
}
break;
}
break;
case "23000":
if ( 546 == errorCode ) {
// Foreign key violation
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName(
sqlException );
return new ConstraintViolationException( message, sqlException, sql, constraintName );
}
break;
}
}
return null;
};

View File

@ -602,8 +602,12 @@ public class DerbyDialect extends Dialect {
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
// final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException );
if ( "40XL1".equals( sqlState ) || "40XL2".equals( sqlState ) ) {
throw new LockTimeoutException( message, sqlException, sql );
if ( sqlState != null ) {
switch ( sqlState ) {
case "40XL1":
case "40XL2":
throw new LockTimeoutException( message, sqlException, sql );
}
}
return null;
};

View File

@ -728,12 +728,14 @@ public class MySQLDialect extends Dialect {
private static final ViolatedConstraintNameExtractor EXTRACTOR =
new TemplatedViolatedConstraintNameExtractor( sqle -> {
switch ( Integer.parseInt( JdbcExceptionHelper.extractSqlState( sqle ) ) ) {
case 23000:
return extractUsingTemplate( " for key '", "'", sqle.getMessage() );
default:
return null;
final String sqlState = JdbcExceptionHelper.extractSqlState( sqle );
if ( sqlState != null ) {
switch ( Integer.parseInt( sqlState ) ) {
case 23000:
return extractUsingTemplate( " for key '", "'", sqle.getMessage() );
}
}
return null;
} );
@Override

View File

@ -847,44 +847,50 @@ public class PostgreSQLDialect extends Dialect {
*/
private static final ViolatedConstraintNameExtractor EXTRACTOR =
new TemplatedViolatedConstraintNameExtractor( sqle -> {
switch ( Integer.parseInt( JdbcExceptionHelper.extractSqlState( sqle ) ) ) {
// CHECK VIOLATION
case 23514:
return extractUsingTemplate( "violates check constraint \"","\"", sqle.getMessage() );
// UNIQUE VIOLATION
case 23505:
return extractUsingTemplate( "violates unique constraint \"","\"", sqle.getMessage() );
// FOREIGN KEY VIOLATION
case 23503:
return extractUsingTemplate( "violates foreign key constraint \"","\"", sqle.getMessage() );
// NOT NULL VIOLATION
case 23502:
return extractUsingTemplate( "null value in column \"","\" violates not-null constraint", sqle.getMessage() );
// TODO: RESTRICT VIOLATION
case 23001:
return null;
// ALL OTHER
default:
return null;
final String sqlState = JdbcExceptionHelper.extractSqlState( sqle );
if ( sqlState != null ) {
switch ( Integer.parseInt( sqlState ) ) {
// CHECK VIOLATION
case 23514:
return extractUsingTemplate( "violates check constraint \"", "\"", sqle.getMessage() );
// UNIQUE VIOLATION
case 23505:
return extractUsingTemplate( "violates unique constraint \"", "\"", sqle.getMessage() );
// FOREIGN KEY VIOLATION
case 23503:
return extractUsingTemplate( "violates foreign key constraint \"", "\"", sqle.getMessage() );
// NOT NULL VIOLATION
case 23502:
return extractUsingTemplate(
"null value in column \"",
"\" violates not-null constraint",
sqle.getMessage()
);
// TODO: RESTRICT VIOLATION
case 23001:
return null;
}
}
return null;
} );
@Override
public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
return (sqlException, message, sql) -> {
switch ( JdbcExceptionHelper.extractSqlState( sqlException ) ) {
case "40P01":
// DEADLOCK DETECTED
return new LockAcquisitionException(message, sqlException, sql);
case "55P03":
// LOCK NOT AVAILABLE
return new PessimisticLockException(message, sqlException, sql);
case "57014":
return new QueryTimeoutException( message, sqlException, sql );
default:
// returning null allows other delegates to operate
return null;
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
if ( sqlState != null ) {
switch ( sqlState ) {
case "40P01":
// DEADLOCK DETECTED
return new LockAcquisitionException( message, sqlException, sql );
case "55P03":
// LOCK NOT AVAILABLE
return new PessimisticLockException( message, sqlException, sql );
case "57014":
return new QueryTimeoutException( message, sqlException, sql );
}
}
return null;
};
}

View File

@ -625,32 +625,33 @@ public class SybaseASEDialect extends SybaseDialect {
*/
private static final ViolatedConstraintNameExtractor EXTRACTOR =
new TemplatedViolatedConstraintNameExtractor( sqle -> {
final String sqlState = JdbcExceptionHelper.extractSqlState( sqle );
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
switch ( JdbcExceptionHelper.extractSqlState( sqle ) ) {
// UNIQUE VIOLATION
case "S1000":
if (2601 == errorCode) {
return extractUsingTemplate( "with unique index '", "'", sqle.getMessage() );
}
break;
case "23000":
if (546 == errorCode) {
// Foreign key violation
return extractUsingTemplate( "constraint name = '", "'", sqle.getMessage() );
}
break;
// // FOREIGN KEY VIOLATION
// case 23503:
// return extractUsingTemplate( "violates foreign key constraint \"","\"", sqle.getMessage() );
// // NOT NULL VIOLATION
// case 23502:
// return extractUsingTemplate( "null value in column \"","\" violates not-null constraint", sqle.getMessage() );
// // TODO: RESTRICT VIOLATION
// case 23001:
// return null;
// ALL OTHER
default:
return null;
if ( sqlState != null ) {
switch ( sqlState ) {
// UNIQUE VIOLATION
case "S1000":
if ( 2601 == errorCode ) {
return extractUsingTemplate( "with unique index '", "'", sqle.getMessage() );
}
break;
case "23000":
if ( 546 == errorCode ) {
// Foreign key violation
return extractUsingTemplate( "constraint name = '", "'", sqle.getMessage() );
}
break;
// // FOREIGN KEY VIOLATION
// case 23503:
// return extractUsingTemplate( "violates foreign key constraint \"","\"", sqle.getMessage() );
// // NOT NULL VIOLATION
// case 23502:
// return extractUsingTemplate( "null value in column \"","\" violates not-null constraint", sqle.getMessage() );
// // TODO: RESTRICT VIOLATION
// case 23001:
// return null;
// ALL OTHER
}
}
return null;
} );
@ -660,34 +661,39 @@ public class SybaseASEDialect extends SybaseDialect {
return (sqlException, message, sql) -> {
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException );
switch ( sqlState ) {
case "JZ0TO":
case "JZ006":
throw new LockTimeoutException( message, sqlException, sql );
case "S1000":
switch ( errorCode ) {
case 515:
if ( sqlState != null ) {
switch ( sqlState ) {
case "JZ0TO":
case "JZ006":
throw new LockTimeoutException( message, sqlException, sql );
case "S1000":
switch ( errorCode ) {
case 515:
// Attempt to insert NULL value into column; column does not allow nulls.
case 2601:
// Unique constraint violation
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName(
sqlException );
return new ConstraintViolationException( message, sqlException, sql, constraintName );
}
break;
case "ZZZZZ":
if ( 515 == errorCode ) {
// Attempt to insert NULL value into column; column does not allow nulls.
case 2601:
// Unique constraint violation
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName( sqlException );
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName(
sqlException );
return new ConstraintViolationException( message, sqlException, sql, constraintName );
}
break;
case "ZZZZZ":
if (515 == errorCode) {
// Attempt to insert NULL value into column; column does not allow nulls.
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName( sqlException );
return new ConstraintViolationException( message, sqlException, sql, constraintName );
}
break;
case "23000":
if (546 == errorCode) {
// Foreign key violation
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName( sqlException );
return new ConstraintViolationException( message, sqlException, sql, constraintName );
}
break;
}
break;
case "23000":
if ( 546 == errorCode ) {
// Foreign key violation
final String constraintName = getViolatedConstraintNameExtractor().extractConstraintName(
sqlException );
return new ConstraintViolationException( message, sqlException, sql, constraintName );
}
break;
}
}
return null;
};

View File

@ -0,0 +1,34 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.orm.test.dialect;
import java.sql.SQLException;
import org.hibernate.dialect.Dialect;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DialectContext;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Test;
public class DialectSQLExceptionConversionTest {
private final Dialect dialect = DialectContext.getDialect();
@Test
@TestForIssue(jiraKey = "HHH-15592")
public void testExceptionConversionDoesntNPE() {
final SQLExceptionConversionDelegate conversionDelegate = dialect.buildSQLExceptionConversionDelegate();
Assumptions.assumeTrue( conversionDelegate != null );
conversionDelegate.convert(
new SQLException(),
"test",
"test"
);
}
}