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 @@ -295,9 +295,10 @@ public interface SchemaToolingSettings {

/**
* Specifies the default storage engine for a relational database that supports
* multiple storage engines. This property must be set either as an {@link Environment}
* variable or JVM System Property, since the {@link org.hibernate.dialect.Dialect} is
* instantiated before Hibernate property resolution.
* multiple storage engines.
*
* This property can be set as an {@link Environment} variable, a JVM System Property
* or a configuration property.
* <p>
* For MySQL, the legal values are {@code innodb} (the default) and {@code myisam}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import static java.lang.Integer.parseInt;
Expand Down Expand Up @@ -146,7 +147,7 @@ public class MySQLDialect extends Dialect {

private static final DatabaseVersion MINIMUM_VERSION = DatabaseVersion.make( 8 );

private final MySQLStorageEngine storageEngine = createStorageEngine();
private final MySQLStorageEngine storageEngine;

private final SizeStrategy sizeStrategy = new SizeStrategyImpl() {
@Override
Expand Down Expand Up @@ -207,14 +208,19 @@ public MySQLDialect(DatabaseVersion version, int bytesPerCharacter) {
}

public MySQLDialect(DatabaseVersion version, MySQLServerConfiguration serverConfiguration) {
this( version, serverConfiguration.getBytesPerCharacter(), serverConfiguration.isNoBackslashEscapesEnabled() );
super( version );
maxVarcharLength = maxVarcharLength( getMySQLVersion(), serverConfiguration.getBytesPerCharacter() ); //conservative assumption
maxVarbinaryLength = maxVarbinaryLength( getMySQLVersion() );
noBackslashEscapesEnabled = serverConfiguration.isNoBackslashEscapesEnabled();
storageEngine = createStorageEngine( serverConfiguration.getConfiguredStorageEngine() );
}

public MySQLDialect(DatabaseVersion version, int bytesPerCharacter, boolean noBackslashEscapes) {
super( version );
maxVarcharLength = maxVarcharLength( getMySQLVersion(), bytesPerCharacter ); //conservative assumption
maxVarbinaryLength = maxVarbinaryLength( getMySQLVersion() );
noBackslashEscapesEnabled = noBackslashEscapes;
storageEngine = createStorageEngine( Environment.getProperties().getProperty( AvailableSettings.STORAGE_ENGINE ) );
}

public MySQLDialect(DialectResolutionInfo info) {
Expand Down Expand Up @@ -257,13 +263,10 @@ protected void initDefaultProperties() {
getDefaultProperties().setProperty( FetchSettings.MAX_FETCH_DEPTH, "2" );
}

private MySQLStorageEngine createStorageEngine() {
final String storageEngine =
Environment.getProperties()
.getProperty( AvailableSettings.STORAGE_ENGINE );
return storageEngine == null
private MySQLStorageEngine createStorageEngine(String configuredStorageEngine) {
return configuredStorageEngine == null
? getDefaultMySQLStorageEngine()
: switch ( storageEngine ) {
: switch ( configuredStorageEngine.toLowerCase(Locale.ROOT) ) {
case "innodb" -> InnoDBStorageEngine.INSTANCE;
case "myisam" -> MyISAMStorageEngine.INSTANCE;
default -> throw new UnsupportedOperationException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import java.sql.SQLException;

import org.hibernate.Internal;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.internal.util.config.ConfigurationHelper;

import static org.hibernate.cfg.DialectSpecificSettings.MYSQL_BYTES_PER_CHARACTER;
import static org.hibernate.cfg.DialectSpecificSettings.MYSQL_NO_BACKSLASH_ESCAPES;
Expand All @@ -26,10 +28,18 @@
public class MySQLServerConfiguration {
private final int bytesPerCharacter;
private final boolean noBackslashEscapesEnabled;
private final String storageEngine;

public MySQLServerConfiguration(int bytesPerCharacter, boolean noBackslashEscapesEnabled) {
this.bytesPerCharacter = bytesPerCharacter;
this.noBackslashEscapesEnabled = noBackslashEscapesEnabled;
this.storageEngine = null;
}

public MySQLServerConfiguration(int bytesPerCharacter, boolean noBackslashEscapesEnabled, String storageEngine) {
this.bytesPerCharacter = bytesPerCharacter;
this.noBackslashEscapesEnabled = noBackslashEscapesEnabled;
this.storageEngine = storageEngine;
}

public int getBytesPerCharacter() {
Expand All @@ -40,6 +50,10 @@ public boolean isNoBackslashEscapesEnabled() {
return noBackslashEscapesEnabled;
}

public String getConfiguredStorageEngine() {
return storageEngine;
}

static Integer getBytesPerCharacter(String characterSet) {
final int collationIndex = characterSet.indexOf( '_' );
// According to https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html
Expand Down Expand Up @@ -78,7 +92,11 @@ public static MySQLServerConfiguration fromDialectResolutionInfo(DialectResoluti
if ( noBackslashEscapes == null ) {
noBackslashEscapes = getBoolean( MYSQL_NO_BACKSLASH_ESCAPES, info.getConfigurationValues(), false );
}
return new MySQLServerConfiguration( bytesPerCharacter, noBackslashEscapes );

return new MySQLServerConfiguration(
bytesPerCharacter,
noBackslashEscapes,
ConfigurationHelper.getString( AvailableSettings.STORAGE_ENGINE, info.getConfigurationValues() ) );
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,87 @@
*/
package org.hibernate.orm.test.dialect.unit.lockhint;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.MySQLDialect;

import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.orm.test.dialect.resolver.TestingDialectResolutionInfo;
import org.hibernate.testing.orm.junit.BaseUnitTest;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

@RequiresDialect(MySQLDialect.class)
public class MySQLStorageEngineTest extends BaseUnitTestCase {
@BaseUnitTest
public class MySQLStorageEngineTest {

@Test
public void testDefaultStorage() {
assertEquals( " engine=InnoDB", new MySQLDialect().getTableTypeString() );
assertThat( new MySQLDialect().getTableTypeString() ).isEqualTo( " engine=InnoDB" );
}

@Test
public void testOverrideStorage() throws NoSuchFieldException, IllegalAccessException {
final Field globalPropertiesField = Environment.class.getDeclaredField( "GLOBAL_PROPERTIES" );
globalPropertiesField.setAccessible( true );
final Properties systemProperties = (Properties) globalPropertiesField.get( null );
assertNotNull( systemProperties );
assertThat( systemProperties ).isNotNull();
final Object previousValue = systemProperties.setProperty( AvailableSettings.STORAGE_ENGINE, "myisam" );
try {
assertThat( new MySQLDialect().getTableTypeString() ).isEqualTo( " engine=MyISAM" );
}
finally {
if ( previousValue != null ) {
systemProperties.setProperty( AvailableSettings.STORAGE_ENGINE, previousValue.toString() );
}
else {
systemProperties.remove( AvailableSettings.STORAGE_ENGINE );
}
}
}

@Test
@SessionFactory
@ServiceRegistry(settings = {@Setting(name = AvailableSettings.STORAGE_ENGINE, value = "myisam")})
@DomainModel(annotatedClasses = {TestEntity.class})
public void testOverrideStorageWithConfigurationProperties(SessionFactoryScope scope) {
Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect();
assertThat( dialect.getTableTypeString() ).isEqualTo( " engine=MyISAM" );
}

@Test
public void testOverrideStorageEngineConfigurationPropertyHasPrecedenceOverSystemProperty()
throws Exception {
final Field globalPropertiesField = Environment.class.getDeclaredField( "GLOBAL_PROPERTIES" );
globalPropertiesField.setAccessible( true );
final Properties systemProperties = (Properties) globalPropertiesField.get( null );
assertThat( systemProperties ).isNotNull();
final Object previousValue = systemProperties.setProperty( AvailableSettings.STORAGE_ENGINE, "myisam" );
try {
assertEquals( " engine=MyISAM", new MySQLDialect().getTableTypeString() );
final Map<String, Object> configurationValues = new HashMap<>();
configurationValues.put( AvailableSettings.STORAGE_ENGINE, "innodb" );
Dialect dialect = new MySQLDialect(
TestingDialectResolutionInfo.forDatabaseInfo(
"MySQL",
null,
DatabaseVersion.NO_VERSION,
DatabaseVersion.NO_VERSION,
configurationValues ) );
assertThat( dialect.getTableTypeString() ).isEqualTo( " engine=InnoDB" );
}
finally {
if ( previousValue != null ) {
Expand All @@ -46,4 +96,12 @@ public void testOverrideStorage() throws NoSuchFieldException, IllegalAccessExce
}
}

@Entity(name = "TestEntity")
public static class TestEntity{
@Id
private Long id;

private String name;
}

}