/**
* Following code implements hibernate 4.3's constraint naming strategy, adapted from:
* org.hibernate.mapping.Constraint#generateName(java.lang.String, org.hibernate.mapping.Table, org.hibernate.mapping.Column...)
*/
@Override
public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {
List<String> columnNames = source.getReferencedColumnNames().stream().map(i -> i.getText()).collect(Collectors.toList());
return generateName("FK_", source.getTableName().getText(), columnNames);
}
@Override
public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source) {
List<String> columnNames = source.getColumnNames().stream().map(i -> i.getText()).collect(Collectors.toList());
return generateName("UK_", source.getTableName().getText(), columnNames);
}
/**
* If a constraint is not explicitly named, this is called to generate
* a unique hash using the table and column names.
* Static so the name can be generated prior to creating the Constraint.
* They're cached, keyed by name, in multiple locations.
*/
private Identifier generateName(String prefix, String table, List<String> columnNames) {
StringBuilder sb = new StringBuilder( "table`" + table + "`" );
columnNames.sort(String::compareTo);
for ( String column : columnNames ) {
String columnName = column == null ? "" : column;
sb.append("column`").append(columnName).append("`");
}
return new Identifier(prefix + hashedName(sb.toString()).toUpperCase(), false);
}
/**
* Hash a constraint name using MD5. Convert the MD5 digest to base 35
* (full alphanumeric), guaranteeing
* that the length of the name will always be smaller than the 30
* character identifier restriction enforced by a few dialects.
*/
public static String hashedName(String s) {
try {
MessageDigest md = MessageDigest.getInstance( "MD5" );
md.reset();
md.update( s.getBytes() );
byte[] digest = md.digest();
BigInteger bigInt = new BigInteger( 1, digest );
return bigInt.toString( 35 );
}
catch ( NoSuchAlgorithmException e ) {
throw new HibernateException( "Unable to generate a hashed Constraint name!", e );
}
}