OPENJPA-2775 OPENJPA-2555 fraction of seconds in MySQL

This is a first fix for supporting fractions of a second in MySQL.
This commit is contained in:
Mark Struberg 2018-10-31 20:51:31 +01:00
parent 165279436c
commit 9461ffdfcd
8 changed files with 79 additions and 27 deletions

View File

@ -21,8 +21,7 @@
version="1.0"> version="1.0">
<persistence-unit name="jestdemo"> <persistence-unit name="jestdemo">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<class>demo.Movie</class> <class>demo.Movie</class>
<class>demo.Actor</class> <class>demo.Actor</class>

View File

@ -582,17 +582,17 @@ public abstract class MappingInfo implements Serializable {
getMappingDefaults().defaultMissingInfo(); getMappingDefaults().defaultMissingInfo();
if ((!given.isEmpty() || (!adapt && !fill)) if ((!given.isEmpty() || (!adapt && !fill))
&& given.size() != tmplates.length) { && given.size() != tmplates.length) {
// also consider when this info has columns from multiple tables // also consider when this info has columns from multiple tables
given = getColumns(table.getIdentifier()); given = getColumns(table.getIdentifier());
if ((!adapt && !fill) && given.size() != tmplates.length) { if ((!adapt && !fill) && given.size() != tmplates.length) {
// try default table // try default table
given = getColumns(""); given = getColumns("");
if ((!adapt && !fill) && given.size() != tmplates.length) { if ((!adapt && !fill) && given.size() != tmplates.length) {
throw new MetaDataException(_loc.get(prefix + "-num-cols", throw new MetaDataException(_loc.get(prefix + "-num-cols",
context, String.valueOf(tmplates.length), context, String.valueOf(tmplates.length),
String.valueOf(given.size()))); String.valueOf(given.size())));
} }
} }
} }
Column[] cols = new Column[tmplates.length]; Column[] cols = new Column[tmplates.length];
@ -607,12 +607,6 @@ public abstract class MappingInfo implements Serializable {
return cols; return cols;
} }
boolean canMerge(List<Column> given, Column[] templates, boolean adapt,
boolean fill) {
return !((!given.isEmpty() || (!adapt && !fill))
&& given.size() != templates.length);
}
/** /**
* Set the proper internal column I/O metadata for the given column's flags. * Set the proper internal column I/O metadata for the given column's flags.
*/ */

View File

@ -428,6 +428,24 @@ public class DBDictionary
protected final Set<String> systemSchemaSet = new HashSet<>(); protected final Set<String> systemSchemaSet = new HashSet<>();
protected final Set<String> systemTableSet = new HashSet<>(); protected final Set<String> systemTableSet = new HashSet<>();
protected final Set<String> fixedSizeTypeNameSet = new HashSet<>(); protected final Set<String> fixedSizeTypeNameSet = new HashSet<>();
/**
* set of types that only accept a single precision...
*/
protected final Set<String> fractionalTypeNameSet = new HashSet<>();
/**
* Default amount of digits for fractional Types.
* This is not supported/required by every database.
*
* This value is only being used if no explicit {@code @Column(scale=n)} is set.
* Use {@code @Column(scale=-1)} to disable the scale
* @see #fractionalTypeNameSet
* @see #getFractionLength(Column, String)
*/
protected int defaultFractionLength = 6;
protected final Set<String> typeModifierSet = new HashSet<>(); protected final Set<String> typeModifierSet = new HashSet<>();
// NamingConfiguration properties // NamingConfiguration properties
@ -1838,15 +1856,32 @@ public class DBDictionary
* subclasses. * subclasses.
*/ */
protected String appendSize(Column col, String typeName) { protected String appendSize(Column col, String typeName) {
if (fixedSizeTypeNameSet.contains(typeName.toUpperCase(Locale.ENGLISH))) String upperCaseTypeName = typeName.toUpperCase(Locale.ENGLISH);
if (fixedSizeTypeNameSet.contains(upperCaseTypeName)) {
return typeName; return typeName;
if (typeName.indexOf('(') != -1) }
if (typeName.indexOf('(') != -1) {
return typeName; return typeName;
}
String size = null; String size = null;
if (col.getSize() > 0) { int colSize = col.getSize();
if (colSize<=0 && fractionalTypeNameSet.contains(upperCaseTypeName)){
// special handling for types with fractions
// Attention! We abuse @Column(scale=n)
// One can disable all fractions with @Column(scale=-1)
if (col.getDecimalDigits() != 0) { // the default
colSize = col.getDecimalDigits() == -1 ? 0 : col.getDecimalDigits();
}
else {
colSize = getFractionLength(col, typeName);
}
size = "(" + colSize + ")";
} else if (colSize > 0) {
StringBuilder buf = new StringBuilder(10); StringBuilder buf = new StringBuilder(10);
buf.append("(").append(col.getSize()); buf.append("(").append(colSize);
if (col.getDecimalDigits() > 0) if (col.getDecimalDigits() > 0)
buf.append(", ").append(col.getDecimalDigits()); buf.append(", ").append(col.getDecimalDigits());
buf.append(")"); buf.append(")");
@ -1856,6 +1891,16 @@ public class DBDictionary
return insertSize(typeName, size); return insertSize(typeName, size);
} }
/**
* Only get's used if no explicit scale is used.
* Attention! @{code @Column(scale=-1)} disables the scale of a column
* @return the fraction length of types which have a fraction
* @see #fractionalTypeNameSet
*/
protected int getFractionLength(Column col, String typeName) {
return defaultFractionLength;
}
/** /**
* Helper method that inserts a size clause for a given SQL type. * Helper method that inserts a size clause for a given SQL type.
* *

View File

@ -75,7 +75,7 @@ public class MySQLDictionary
* combined <code>DELETE FROM foo, bar, baz</code> syntax. * combined <code>DELETE FROM foo, bar, baz</code> syntax.
* Defaults to false, since this may fail in the presence of InnoDB tables * Defaults to false, since this may fail in the presence of InnoDB tables
* with foreign keys. * with foreign keys.
* @see http://dev.mysql.com/doc/refman/5.0/en/delete.html * @link http://dev.mysql.com/doc/refman/5.0/en/delete.html
*/ */
public boolean optimizeMultiTableDeletes = false; public boolean optimizeMultiTableDeletes = false;
@ -99,6 +99,8 @@ public class MySQLDictionary
supportsSelectStartIndex = true; supportsSelectStartIndex = true;
supportsSelectEndIndex = true; supportsSelectEndIndex = true;
concatenateFunction = "CONCAT({0},{1})"; concatenateFunction = "CONCAT({0},{1})";
maxTableNameLength = 64; maxTableNameLength = 64;
@ -195,11 +197,19 @@ public class MySQLDictionary
allowsAliasInBulkClause = false; allowsAliasInBulkClause = false;
supportsForeignKeysComposite = false; supportsForeignKeysComposite = false;
} }
if (maj > 5 || (maj == 5 && min >= 1)) if (maj > 5 || (maj == 5 && min >= 1)) {
supportsXMLColumn = true; supportsXMLColumn = true;
}
if (maj > 5 || (maj == 5 && min >= 7)) {
// from this version on MySQL supports fractions of a second
timestampTypeName = "DATETIME{0}";
fixedSizeTypeNameSet.remove(timestampTypeName);
fractionalTypeNameSet.add(timestampTypeName);
}
if (metaData.getDriverMajorVersion() < 5) if (metaData.getDriverMajorVersion() < 5) {
driverDeserializesBlobs = true; driverDeserializesBlobs = true;
}
} }
@Override @Override

View File

@ -22,6 +22,7 @@ import java.util.Date;
import javax.persistence.Access; import javax.persistence.Access;
import javax.persistence.AccessType; import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.NamedQueries; import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery; import javax.persistence.NamedQuery;

View File

@ -34,6 +34,8 @@ import org.apache.openjpa.persistence.ArgumentException;
import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI; import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
import org.apache.openjpa.persistence.test.SingleEMFTestCase; import org.apache.openjpa.persistence.test.SingleEMFTestCase;
// -ea -Dopenjpa.ConnectionDriverName=com.mysql.jdbc.Driver -Dopenjpa.ConnectionPassword=openjpatst
// -Dopenjpa.ConnectionURL=jdbc:mysql://localhost:3306/openjpatst -Dopenjpa.ConnectionUserName=openjpatst
public class TestExplicitAccess extends SingleEMFTestCase { public class TestExplicitAccess extends SingleEMFTestCase {
@Override @Override
@ -476,6 +478,7 @@ public class TestExplicitAccess extends SingleEMFTestCase {
fs.setName("EntitySuperName"); fs.setName("EntitySuperName");
// Call base setter with property access // Call base setter with property access
Date now = new Date(); Date now = new Date();
fs.setCreateDate(now); fs.setCreateDate(now);
SuperPropertyEntity spe = new SuperPropertyEntity(); SuperPropertyEntity spe = new SuperPropertyEntity();

View File

@ -84,7 +84,7 @@
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version> <version>${mysql.connector.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -75,7 +75,7 @@
<!-- common JDBC driver versions --> <!-- common JDBC driver versions -->
<derby.version>10.14.2.0</derby.version> <derby.version>10.14.2.0</derby.version>
<hsqldb.version>2.4.1</hsqldb.version> <hsqldb.version>2.4.1</hsqldb.version>
<mysql.version>8.0.12</mysql.version> <mysql.connector.version>8.0.13</mysql.connector.version>
<postgresql.version>42.2.5</postgresql.version> <postgresql.version>42.2.5</postgresql.version>
<!-- other common versions --> <!-- other common versions -->
<slf4j.version>1.7.23</slf4j.version> <slf4j.version>1.7.23</slf4j.version>
@ -532,7 +532,7 @@
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version> <version>${mysql.connector.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@ -561,7 +561,7 @@
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version> <version>${mysql.connector.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@ -1403,7 +1403,7 @@
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version> <version>${mysql.connector.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>