Skip to content

Commit 2b1b02f

Browse files
committed
HHH-19300 more constraint interpretation improvements for HSQL, SQL Server, and Sybase ASE
1 parent 28b7432 commit 2b1b02f

File tree

4 files changed

+88
-47
lines changed

4 files changed

+88
-47
lines changed

hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -452,23 +452,33 @@ public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() {
452452
// messages may be localized, therefore use the common, non-locale element " table: "
453453
new TemplatedViolatedConstraintNameExtractor( sqle ->
454454
switch ( extractErrorCode( sqle ) ) {
455-
case -8, -9, -104, -177 -> extractUsingTemplate( "; ", " table: ", sqle.getMessage() );
455+
case -8, -9, -104, -177, -157 -> extractUsingTemplate( "; ", " table: ", sqle.getMessage() );
456456
default -> null;
457457
});
458458

459459
@Override
460460
public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
461461
return (sqlException, message, sql) ->
462462
switch ( extractErrorCode( sqlException ) ) {
463+
case -10 ->
464+
// Not null constraint violation
465+
new ConstraintViolationException( message, sqlException, sql,
466+
ConstraintViolationException.ConstraintKind.NOT_NULL, null );
463467
case -104 ->
464468
// Unique constraint violation
465-
new ConstraintViolationException(
466-
message,
467-
sqlException,
468-
sql,
469+
new ConstraintViolationException( message, sqlException, sql,
469470
ConstraintViolationException.ConstraintKind.UNIQUE,
470-
getViolatedConstraintNameExtractor().extractConstraintName(sqlException)
471-
);
471+
getViolatedConstraintNameExtractor().extractConstraintName(sqlException) );
472+
case -157 ->
473+
// Check constraint violation
474+
new ConstraintViolationException( message, sqlException, sql,
475+
ConstraintViolationException.ConstraintKind.CHECK,
476+
getViolatedConstraintNameExtractor().extractConstraintName(sqlException) );
477+
case -177 ->
478+
// Foreign key constraint violation
479+
new ConstraintViolationException( message, sqlException, sql,
480+
ConstraintViolationException.ConstraintKind.CHECK,
481+
getViolatedConstraintNameExtractor().extractConstraintName(sqlException) );
472482
default -> null;
473483
};
474484
}

hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -802,40 +802,50 @@ public boolean supportsFetchClause(FetchClauseType type) {
802802
@Override
803803
public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() {
804804
return new TemplatedViolatedConstraintNameExtractor(
805-
sqle -> {
806-
switch ( extractErrorCode( sqle ) ) {
807-
case 2627:
808-
case 2601:
809-
String message = sqle.getMessage();
810-
if ( message.contains("unique index ") ) {
811-
return extractUsingTemplate( "unique index '", "'", message);
812-
}
813-
else {
814-
return extractUsingTemplate( "'", "'", message);
815-
}
816-
default:
817-
return null;
805+
sqle -> switch ( extractErrorCode( sqle ) ) {
806+
case 2627, 2601 -> {
807+
final String message = sqle.getMessage();
808+
yield message.contains( "unique index " )
809+
? extractUsingTemplate( "unique index '", "'", message )
810+
: extractUsingTemplate( "'", "'", message );
818811
}
812+
case 547 -> extractUsingTemplate( "constraint \"", "\"", sqle.getMessage() );
813+
case 515 -> extractUsingTemplate( "column '", "'", sqle.getMessage() );
814+
default -> null;
819815
}
820816
);
821817
}
822818

823819
@Override
824820
public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
825821
return (sqlException, message, sql) -> {
826-
final String sqlState = extractSqlState( sqlException );
827-
if ( "HY008".equals( sqlState ) ) {
822+
if ( "HY008".equals( extractSqlState( sqlException ) ) ) {
828823
return new QueryTimeoutException( message, sqlException, sql );
829824
}
830825

831826
return switch ( extractErrorCode( sqlException ) ) {
832827
case 1222 -> new LockTimeoutException( message, sqlException, sql );
833828
case 2627, 2601 -> new ConstraintViolationException( message, sqlException, sql,
834829
ConstraintViolationException.ConstraintKind.UNIQUE,
835-
getViolatedConstraintNameExtractor().extractConstraintName( sqlException )
836-
);
830+
getViolatedConstraintNameExtractor().extractConstraintName( sqlException ) );
837831
case 515 -> new ConstraintViolationException( message, sqlException, sql,
838-
ConstraintViolationException.ConstraintKind.NOT_NULL, null );
832+
ConstraintViolationException.ConstraintKind.NOT_NULL,
833+
getViolatedConstraintNameExtractor().extractConstraintName( sqlException ) );
834+
case 547 -> {
835+
if ( message.contains( " CHECK " ) ) {
836+
yield new ConstraintViolationException( message, sqlException, sql,
837+
ConstraintViolationException.ConstraintKind.CHECK,
838+
getViolatedConstraintNameExtractor().extractConstraintName( sqlException ) );
839+
}
840+
else if ( message.contains( " FOREIGN KEY " ) ) {
841+
yield new ConstraintViolationException( message, sqlException, sql,
842+
ConstraintViolationException.ConstraintKind.FOREIGN_KEY,
843+
getViolatedConstraintNameExtractor().extractConstraintName( sqlException ) );
844+
}
845+
else {
846+
yield null;
847+
}
848+
}
839849
default -> null;
840850
};
841851
};

hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
2929
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
3030
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
31-
import org.hibernate.internal.util.JdbcExceptionHelper;
3231
import org.hibernate.query.sqm.IntervalType;
3332
import org.hibernate.query.common.TemporalUnit;
3433
import org.hibernate.service.ServiceRegistry;
@@ -50,6 +49,8 @@
5049
import static org.hibernate.cfg.DialectSpecificSettings.SYBASE_ANSI_NULL;
5150
import static org.hibernate.cfg.DialectSpecificSettings.SYBASE_PAGE_SIZE;
5251
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
52+
import static org.hibernate.internal.util.JdbcExceptionHelper.extractErrorCode;
53+
import static org.hibernate.internal.util.JdbcExceptionHelper.extractSqlState;
5354
import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean;
5455
import static org.hibernate.internal.util.config.ConfigurationHelper.getInt;
5556
import static org.hibernate.type.SqlTypes.BOOLEAN;
@@ -665,37 +666,34 @@ public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() {
665666
return EXTRACTOR;
666667
}
667668

668-
/**
669-
* Constraint-name extractor for Sybase ASE constraint violation exceptions.
670-
* Orginally contributed by Denny Bartelt.
671-
*/
672669
private static final ViolatedConstraintNameExtractor EXTRACTOR =
673670
new TemplatedViolatedConstraintNameExtractor( sqle -> {
674-
final String sqlState = JdbcExceptionHelper.extractSqlState( sqle );
675-
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
671+
final String sqlState = extractSqlState( sqle );
676672
if ( sqlState != null ) {
677-
switch ( sqlState ) {
678-
case "S1000":
679-
case "23000":
680-
switch ( errorCode ) {
681-
case 2601:
682-
// UNIQUE VIOLATION
683-
return extractUsingTemplate( "with unique index '", "'", sqle.getMessage() );
684-
case 546:
685-
// Foreign key violation
686-
return extractUsingTemplate( "constraint name = '", "'", sqle.getMessage() );
687-
}
688-
break;
689-
}
673+
return switch ( sqlState ) {
674+
case "S1000", "23000" -> switch ( extractErrorCode( sqle ) ) {
675+
case 2601 ->
676+
// Unique constraint violation
677+
extractUsingTemplate( "with unique index '", "'", sqle.getMessage() );
678+
case 546, 548 ->
679+
// Foreign key or check constraint violation
680+
extractUsingTemplate( "constraint name = '", "'", sqle.getMessage() );
681+
case 151 ->
682+
// Not null violation
683+
extractUsingTemplate( "column '", "'", sqle.getMessage() );
684+
default -> null;
685+
};
686+
default -> null;
687+
};
690688
}
691689
return null;
692690
} );
693691

694692
@Override
695693
public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
696694
return (sqlException, message, sql) -> {
697-
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
698-
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException );
695+
final String sqlState = extractSqlState( sqlException );
696+
final int errorCode = extractErrorCode( sqlException );
699697
if ( sqlState != null ) {
700698
switch ( sqlState ) {
701699
case "HY008":
@@ -716,6 +714,11 @@ public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
716714
return new ConstraintViolationException( message, sqlException, sql,
717715
ConstraintViolationException.ConstraintKind.FOREIGN_KEY,
718716
getViolatedConstraintNameExtractor().extractConstraintName( sqlException ) );
717+
case 548:
718+
// Check constraint violation
719+
return new ConstraintViolationException( message, sqlException, sql,
720+
ConstraintViolationException.ConstraintKind.CHECK,
721+
getViolatedConstraintNameExtractor().extractConstraintName( sqlException ) );
719722
case 2601:
720723
// Unique constraint violation
721724
return new ConstraintViolationException( message, sqlException, sql,

hibernate-core/src/main/java/org/hibernate/exception/ConstraintViolationException.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,29 @@ public ConstraintKind getKind() {
5656
return kind;
5757
}
5858

59+
/**
60+
* Enumerates the kinds of constraint violation recognized by Hibernate.
61+
*/
5962
public enum ConstraintKind {
63+
/**
64+
* A {@code not null} constraint violation.
65+
*/
6066
NOT_NULL,
67+
/**
68+
* A {@code unique} or {@code primary key} constraint violation.
69+
*/
6170
UNIQUE,
71+
/**
72+
* A {@code foreign key} constraint violation.
73+
*/
6274
FOREIGN_KEY,
75+
/**
76+
* A {@code check} constraint violation.
77+
*/
6378
CHECK,
79+
/**
80+
* A constraint violation whose kind was unknown or unrecognized.
81+
*/
6482
OTHER
6583
}
6684
}

0 commit comments

Comments
 (0)