Skip to content

Commit

Permalink
HHH-11473 - Refactor MySQL Dialects
Browse files Browse the repository at this point in the history
  • Loading branch information
vladmihalcea committed Feb 20, 2017
1 parent d82b336 commit 2b79644
Show file tree
Hide file tree
Showing 28 changed files with 342 additions and 61 deletions.
2 changes: 1 addition & 1 deletion databases.gradle
Expand Up @@ -38,7 +38,7 @@ ext {
'jdbc.url' : 'jdbc:postgresql:hibernate_orm_test'
],
mysql : [
'db.dialect' : 'org.hibernate.dialect.MySQL57InnoDBDialect',
'db.dialect' : 'org.hibernate.dialect.MySQL57Dialect',
'jdbc.driver': 'com.mysql.jdbc.Driver',
'jdbc.user' : 'hibernateormtest',
'jdbc.pass' : 'hibernateormtest',
Expand Down
Expand Up @@ -137,20 +137,16 @@ There are several dialects for MySQL:

`MySQLSpatialDialect`:::
a spatially-extended version of Hibernate `MySQLDialect`
`MySQLSpatialInnoDBDialect`:::
a spatially-extended version of Hibernate `MySQLInnoDBDialect`
`MySQLSpatial56Dialect`:::
a spatially-extended version of Hibernate `MySQL5DBDialect`.
`MySQLSpatial5InnoDBDialect`:::
the same as `MySQLSpatial56Dialect`, but with support for the InnoDB storage engine.

[NOTE]
====
MySQL versions before 5.6.1 had only limited support for spatial operators.
Most operators only took account of the minimum bounding rectangles (MBR) of the geometries, and not the geometries themselves.
This changed in version 5.6.1 were MySQL introduced `ST_*` spatial operators.
The dialects `MySQLSpatial56Dialect` and `MySQLSpatial5InnoDBDialect` use these newer, more precise operators.
The dialect `MySQLSpatial56Dialect` uses these newer, more precise operators.
These dialects may therefore produce results that differ from that of the other spatial dialects.
Expand Down
2 changes: 0 additions & 2 deletions etc/hibernate.properties.template
Expand Up @@ -43,8 +43,6 @@ hibernate.connection.url @DB_URL@


#hibernate.dialect org.hibernate.dialect.MySQLDialect
#hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
#hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
#hibernate.connection.driver_class org.gjt.mm.mysql.Driver
#hibernate.connection.driver_class com.mysql.jdbc.Driver
#hibernate.connection.url jdbc:mysql:///test
Expand Down
Expand Up @@ -44,6 +44,7 @@
import org.hibernate.dialect.JDataStoreDialect;
import org.hibernate.dialect.MckoiDialect;
import org.hibernate.dialect.MimerSQLDialect;
import org.hibernate.dialect.MySQL57Dialect;
import org.hibernate.dialect.MySQL57InnoDBDialect;
import org.hibernate.dialect.MySQL5Dialect;
import org.hibernate.dialect.MySQL5InnoDBDialect;
Expand Down Expand Up @@ -212,6 +213,7 @@ private void addDialects(StrategySelectorImpl strategySelector) {
addDialect( strategySelector, MySQL5Dialect.class );
addDialect( strategySelector, MySQL5InnoDBDialect.class );
addDialect( strategySelector, MySQL57InnoDBDialect.class );
addDialect( strategySelector, MySQL57Dialect.class );
addDialect( strategySelector, Oracle8iDialect.class );
addDialect( strategySelector, Oracle9iDialect.class );
addDialect( strategySelector, Oracle10gDialect.class );
Expand Down
Expand Up @@ -379,6 +379,15 @@ public interface AvailableSettings {
*/
String DIALECT_RESOLVERS = "hibernate.dialect_resolvers";

/**
* Defines the default storage engine for the relational databases that support multiple storage engines.
* This property must be set either as an Environment variable or JVM System Property.
* That is because the Dialect is bootstrapped prior to Hibernate property resolution.
*
* @since 5.2.9
*/
String STORAGE_ENGINE = "hibernate.dialect.storage_engine";

/**
* Used to specify the {@link org.hibernate.tool.schema.spi.SchemaManagementTool} to use for performing
* schema management. The default is to use {@link org.hibernate.tool.schema.internal.HibernateSchemaManagementTool}
Expand Down
Expand Up @@ -256,7 +256,6 @@ public static Dialect getDialect() throws HibernateException {
return instantiateDialect( Environment.getProperties().getProperty( Environment.DIALECT ) );
}


/**
* Get an instance of the dialect specified by the given properties or by
* the current <tt>System</tt> properties.
Expand Down
@@ -0,0 +1,31 @@
package org.hibernate.dialect;

/**
* Represents the InnoDB storage engine.
*
* @author Vlad Mihalcea
*/
public class InnoDBStorageEngine implements MySQLStorageEngine{

public static final MySQLStorageEngine INSTANCE = new InnoDBStorageEngine();

@Override
public boolean supportsCascadeDelete() {
return true;
}

@Override
public String getTableTypeString(String engineKeyword) {
return String.format( " %s=InnoDB", engineKeyword );
}

@Override
public boolean hasSelfReferentialForeignKeyBug() {
return true;
}

@Override
public boolean dropConstraints() {
return true;
}
}
Expand Up @@ -9,7 +9,7 @@
/**
* @author Vlad Mihalcea
*/
public class MariaDBDialect extends MySQL5InnoDBDialect {
public class MariaDBDialect extends MySQL5Dialect {
public MariaDBDialect() {
super();
}
Expand Down
@@ -0,0 +1,31 @@
package org.hibernate.dialect;

/**
* Represents the MyISAM storage engine.
*
* @author Vlad Mihalcea
*/
public class MyISAMStorageEngine implements MySQLStorageEngine{

public static final MySQLStorageEngine INSTANCE = new MyISAMStorageEngine();

@Override
public boolean supportsCascadeDelete() {
return false;
}

@Override
public String getTableTypeString(String engineKeyword) {
return String.format( " %s=MyISAM", engineKeyword );
}

@Override
public boolean hasSelfReferentialForeignKeyBug() {
return false;
}

@Override
public boolean dropConstraints() {
return false;
}
}
@@ -0,0 +1,20 @@
/*
* 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.dialect;

/**
* An SQL dialect for MySQL 5.5.x specific features.
*
* @author Vlad Mihalcea
*/
public class MySQL55Dialect extends MySQL5Dialect {

@Override
protected MySQLStorageEngine getDefaultMySQLStorageEngine() {
return InnoDBStorageEngine.INSTANCE;
}
}
@@ -0,0 +1,76 @@
/*
* 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.dialect;

import java.sql.Types;

import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.dialect.function.StaticPrecisionFspTimestampFunction;

/**
* @author Gail Badner
*/
public class MySQL57Dialect extends MySQL55Dialect {
public MySQL57Dialect() {
super();

// For details about MySQL 5.7 support for fractional seconds
// precision (fsp): http://dev.mysql.com/doc/refman/5.7/en/fractional-seconds.html
// Regarding datetime(fsp), "The fsp value, if given, must be
// in the range 0 to 6. A value of 0 signifies that there is
// no fractional part. If omitted, the default precision is 0.
// (This differs from the standard SQL default of 6, for
// compatibility with previous MySQL versions.)".

// The following is defined because Hibernate currently expects
// the SQL 1992 default of 6 (which is inconsistent with the MySQL
// default).
registerColumnType( Types.TIMESTAMP, "datetime(6)" );

// MySQL 5.7 brings JSON native support with a dedicated datatype.
// For more details about MySql new JSON datatype support, see:
// https://dev.mysql.com/doc/refman/5.7/en/json.html
registerColumnType( Types.JAVA_OBJECT, "json" );

// MySQL also supports fractional seconds precision for time values
// (time(fsp)). According to SQL 1992, the default for <time precision>
// is 0. The MySQL default is time(0), there's no need to override
// the setting for Types.TIME columns.

// For details about MySQL support for timestamp functions, see:
// http://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html

// The following are synonyms for now(fsp), where fsp defaults to 0 on MySQL 5.7:
// current_timestamp([fsp]), localtime(fsp), localtimestamp(fsp).
// Register the same StaticPrecisionFspTimestampFunction for all 4 functions.
final SQLFunction currentTimestampFunction = new StaticPrecisionFspTimestampFunction("now", 6 );

registerFunction( "now", currentTimestampFunction );
registerFunction( "current_timestamp", currentTimestampFunction );
registerFunction( "localtime", currentTimestampFunction );
registerFunction( "localtimestamp", currentTimestampFunction );

// sysdate is different from now():
// "SYSDATE() returns the time at which it executes. This differs
// from the behavior for NOW(), which returns a constant time that
// indicates the time at which the statement began to execute.
// (Within a stored function or trigger, NOW() returns the time at
// which the function or triggering statement began to execute.)
registerFunction( "sysdate", new StaticPrecisionFspTimestampFunction( "sysdate", 6 ) );

// from_unixtime(), timestamp() are functions that return TIMESTAMP that do not support a
// fractional seconds precision argument (so there's no need to override them here):
}

/**
* @see <a href="https://dev.mysql.com/worklog/task/?id=7019">MySQL 5.7 work log</a>
* @return supports IN clause row value expressions
*/
public boolean supportsRowValueConstructorSyntaxInInList() {
return true;
}
}
Expand Up @@ -13,7 +13,9 @@

/**
* @author Gail Badner
* @deprecated Use "hibernate.dialect.storage_engine=innodb" environment variable or JVM system property instead.
*/
@SuppressWarnings("deprecation")
public class MySQL57InnoDBDialect extends MySQL5InnoDBDialect {
public MySQL57InnoDBDialect() {
super();
Expand Down
Expand Up @@ -6,13 +6,13 @@
*/
package org.hibernate.dialect;

import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
import org.hibernate.internal.util.JdbcExceptionHelper;

import java.sql.SQLException;
import java.sql.Types;

/**
* An SQL dialect for MySQL 5.x specific features.
*
Expand All @@ -36,6 +36,10 @@ public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
return EXTRACTER;
}

protected String getEngineKeyword() {
return "engine";
}

private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {

@Override
Expand Down
Expand Up @@ -10,7 +10,9 @@
*
* @author Gavin King,
* @author Scott Marlow
* @deprecated Use "hibernate.dialect.storage_engine=innodb" environment variable or JVM system property instead.
*/
@SuppressWarnings("deprecation")
public class MySQL5InnoDBDialect extends MySQL5Dialect {
@Override
public boolean supportsCascadeDelete() {
Expand Down
Expand Up @@ -310,11 +310,6 @@ public String getSelectGUIDString() {
return "select uuid()";
}

@Override
public boolean supportsCascadeDelete() {
return false;
}

@Override
public String getTableComment(String comment) {
return " comment='" + comment + "'";
Expand Down Expand Up @@ -541,4 +536,51 @@ public IdentityColumnSupport getIdentityColumnSupport() {
public boolean isJdbcLogWarningsEnabledByDefault() {
return false;
}

@Override
public boolean supportsCascadeDelete() {
return getMySQLStorageEngine().supportsCascadeDelete();
}

@Override
public String getTableTypeString() {
return getMySQLStorageEngine().getTableTypeString(getEngineKeyword());
}

protected String getEngineKeyword() {
return "type";
}

@Override
public boolean hasSelfReferentialForeignKeyBug() {
return getMySQLStorageEngine().hasSelfReferentialForeignKeyBug();
}

@Override
public boolean dropConstraints() {
return getMySQLStorageEngine().dropConstraints();
}

protected MySQLStorageEngine getMySQLStorageEngine() {
String storageEngine = Environment.getProperties().getProperty( Environment.STORAGE_ENGINE );
if(storageEngine == null) {
storageEngine = System.getProperty( Environment.STORAGE_ENGINE );
}
if(storageEngine == null) {
return getDefaultMySQLStorageEngine();
}
if( "innodb".equals( storageEngine.toLowerCase() ) ) {
return InnoDBStorageEngine.INSTANCE;
}
else if( "myisam".equals( storageEngine.toLowerCase() ) ) {
return MyISAMStorageEngine.INSTANCE;
}
else {
throw new UnsupportedOperationException( "The " + storageEngine + " storage engine is not supported!" );
}
}

protected MySQLStorageEngine getDefaultMySQLStorageEngine() {
return MyISAMStorageEngine.INSTANCE;
}
}
Expand Up @@ -10,7 +10,9 @@
* A Dialect for MySQL using InnoDB engine
*
* @author Gavin King
* @deprecated Use "hibernate.dialect.storage_engine=innodb" environment variable or JVM system property instead.
*/
@SuppressWarnings("deprecation")
public class MySQLInnoDBDialect extends MySQLDialect {
@Override
public boolean supportsCascadeDelete() {
Expand Down
Expand Up @@ -10,7 +10,9 @@
* A Dialect for MySQL using the MyISAM engine
*
* @author Gavin King
* @deprecated Use "hibernate.dialect.storage_engine=myisam" environment variable or JVM system property instead.
*/
@SuppressWarnings("deprecation")
public class MySQLMyISAMDialect extends MySQLDialect {
@Override
public String getTableTypeString() {
Expand Down

0 comments on commit 2b79644

Please sign in to comment.