[OPENJPA-2567] various MySql and MariaDB text types support is added - thanks @solomax - This closes #18

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1839940 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Francesco Chicchiriccò 2018-09-03 11:41:07 +00:00
parent 6c4c77aa78
commit 9a98d6a2bf
4 changed files with 258 additions and 49 deletions

View File

@ -14,7 +14,7 @@
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.openjpa.jdbc.sql; package org.apache.openjpa.jdbc.sql;
@ -30,7 +30,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.jdbc.identifier.DBIdentifier; import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.identifier.DBIdentifier.DBIdentifierType; import org.apache.openjpa.jdbc.identifier.DBIdentifier.DBIdentifierType;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration; import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
@ -41,17 +40,18 @@ import org.apache.openjpa.jdbc.schema.ForeignKey;
import org.apache.openjpa.jdbc.schema.Index; import org.apache.openjpa.jdbc.schema.Index;
import org.apache.openjpa.jdbc.schema.PrimaryKey; import org.apache.openjpa.jdbc.schema.PrimaryKey;
import org.apache.openjpa.jdbc.schema.Table; import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.util.StoreException; import org.apache.openjpa.util.StoreException;
/* /*
* Dictionary for MariaDB, based off the MySQLDictionary. * Dictionary for MariaDB, based off the MySQLDictionary.
* *
*/ */
public class MariaDBDictionary extends DBDictionary { public class MariaDBDictionary extends DBDictionary {
public static final String SELECT_HINT = "openjpa.hint.MariaDBSelectHint"; public static final String SELECT_HINT = "openjpa.hint.MariaDBSelectHint";
public static final String DELIMITER_BACK_TICK = "`"; public static final String DELIMITER_BACK_TICK = "`";
/** /**
* The MySQL table type to use when creating tables; defaults to innodb. * The MySQL table type to use when creating tables; defaults to innodb.
*/ */
@ -69,8 +69,8 @@ public class MariaDBDictionary extends DBDictionary {
public boolean driverDeserializesBlobs = false; public boolean driverDeserializesBlobs = false;
/** /**
* Whether to inline multi-table bulk-delete operations into MySQL's * Whether to inline multi-table bulk-delete operations into MySQL's
* 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 * @see http://dev.mysql.com/doc/refman/5.0/en/delete.html
@ -80,6 +80,9 @@ public class MariaDBDictionary extends DBDictionary {
public static final String tinyBlobTypeName = "TINYBLOB"; public static final String tinyBlobTypeName = "TINYBLOB";
public static final String mediumBlobTypeName = "MEDIUMBLOB"; public static final String mediumBlobTypeName = "MEDIUMBLOB";
public static final String longBlobTypeName = "LONGBLOB"; public static final String longBlobTypeName = "LONGBLOB";
public static final String tinyTextTypeName = "TINYTEXT";
public static final String mediumTextTypeName = "MEDIUMTEXT";
public static final String longTextTypeName = "LONGTEXT";
public MariaDBDictionary() { public MariaDBDictionary() {
platform = "MariaDB"; platform = "MariaDB";
@ -120,15 +123,15 @@ public class MariaDBDictionary extends DBDictionary {
reservedWordSet.addAll(Arrays.asList(new String[]{ reservedWordSet.addAll(Arrays.asList(new String[]{
"AUTO_INCREMENT", "BINARY", "BLOB", "CHANGE", "ENUM", "INFILE", "AUTO_INCREMENT", "BINARY", "BLOB", "CHANGE", "ENUM", "INFILE",
"INT1", "INT2", "INT4", "FLOAT1", "FLOAT2", "FLOAT4", "LOAD", "INT1", "INT2", "INT4", "FLOAT1", "FLOAT2", "FLOAT4", "LOAD",
"MEDIUMINT", "OUTFILE", "REPLACE", "STARTING", "TEXT", "UNSIGNED", "MEDIUMINT", "OUTFILE", "REPLACE", "STARTING", "TEXT", "UNSIGNED",
"ZEROFILL", "INDEX", "ZEROFILL", "INDEX",
})); }));
// reservedWordSet subset that CANNOT be used as valid column names // reservedWordSet subset that CANNOT be used as valid column names
// (i.e., without surrounding them with double-quotes) // (i.e., without surrounding them with double-quotes)
invalidColumnWordSet.addAll(Arrays.asList(new String[]{ invalidColumnWordSet.addAll(Arrays.asList(new String[]{
"ADD", "ALL", "ALTER", "AND", "AS", "ASC", "BETWEEN", "BINARY", "ADD", "ALL", "ALTER", "AND", "AS", "ASC", "BETWEEN", "BINARY",
"BLOB", "BOTH", "BY", "CASCADE", "CASE", "CHANGE", "CHAR", "BLOB", "BOTH", "BY", "CASCADE", "CASE", "CHANGE", "CHAR",
"CHARACTER", "CHECK", "COLLATE", "COLUMN", "CONSTRAINT", "CONTINUE", "CHARACTER", "CHECK", "COLLATE", "COLUMN", "CONSTRAINT", "CONTINUE",
"CONVERT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CONVERT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME",
"CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "DEC", "DECIMAL", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "DEC", "DECIMAL",
@ -145,7 +148,7 @@ public class MariaDBDictionary extends DBDictionary {
"STARTING", "TABLE", "THEN", "TO", "TRAILING", "TRUE", "UNION", "STARTING", "TABLE", "THEN", "TO", "TRAILING", "TRUE", "UNION",
"UNIQUE", "UNSIGNED", "UPDATE", "USAGE", "USING", "VALUES", "UNIQUE", "UNSIGNED", "UPDATE", "USAGE", "USING", "VALUES",
"VARCHAR", "VARYING", "WHEN", "WHERE", "WITH", "WRITE", "ZEROFILL", "VARCHAR", "VARYING", "WHEN", "WHERE", "WITH", "WRITE", "ZEROFILL",
"INDEX", "INDEX",
})); }));
requiresSearchStringEscapeForLike = true; requiresSearchStringEscapeForLike = true;
@ -157,7 +160,7 @@ public class MariaDBDictionary extends DBDictionary {
setLeadingDelimiter(DELIMITER_BACK_TICK); setLeadingDelimiter(DELIMITER_BACK_TICK);
setTrailingDelimiter(DELIMITER_BACK_TICK); setTrailingDelimiter(DELIMITER_BACK_TICK);
fixedSizeTypeNameSet.remove("NUMERIC"); fixedSizeTypeNameSet.remove("NUMERIC");
} }
@ -180,10 +183,11 @@ public class MariaDBDictionary extends DBDictionary {
if (log.isWarnEnabled()) if (log.isWarnEnabled())
log.warn(e.toString(), e); log.warn(e.toString(), e);
} }
supportsXMLColumn = true; supportsXMLColumn = true;
} }
@Override
protected void setDelimitedCase(DatabaseMetaData metaData) { protected void setDelimitedCase(DatabaseMetaData metaData) {
// Determination of case sensitivity is not accurate; MariaDB JIRA CONJ-55 // Determination of case sensitivity is not accurate; MariaDB JIRA CONJ-55
delimitedCase = SCHEMA_CASE_PRESERVE; delimitedCase = SCHEMA_CASE_PRESERVE;
@ -194,7 +198,7 @@ public class MariaDBDictionary extends DBDictionary {
conn = super.decorate(conn); conn = super.decorate(conn);
return conn; return conn;
} }
private static int[] getMajorMinorVersions(String versionStr) private static int[] getMajorMinorVersions(String versionStr)
throws IllegalArgumentException { throws IllegalArgumentException {
int beginIndex = 0; int beginIndex = 0;
@ -263,7 +267,7 @@ public class MariaDBDictionary extends DBDictionary {
new String[]{ "ALTER TABLE " new String[]{ "ALTER TABLE "
+ getFullName(fk.getTable(), false) + getFullName(fk.getTable(), false)
+ " DROP FOREIGN KEY " + toDBName(fkName) }; + " DROP FOREIGN KEY " + toDBName(fkName) };
return retVal; return retVal;
} }
return new String[]{ "ALTER TABLE " return new String[]{ "ALTER TABLE "
+ getFullName(fk.getTable(), false) + getFullName(fk.getTable(), false)
@ -288,7 +292,7 @@ public class MariaDBDictionary extends DBDictionary {
System.arraycopy(sql, 0, ret, cols.length, sql.length); System.arraycopy(sql, 0, ret, cols.length, sql.length);
return ret; return ret;
} }
@Override @Override
public String[] getDeleteTableContentsSQL(Table[] tables,Connection conn) { public String[] getDeleteTableContentsSQL(Table[] tables,Connection conn) {
// mysql >= 4 supports more-optimal delete syntax // mysql >= 4 supports more-optimal delete syntax
@ -343,10 +347,10 @@ public class MariaDBDictionary extends DBDictionary {
return Types.LONGVARCHAR; return Types.LONGVARCHAR;
return super.getPreferredType(type); return super.getPreferredType(type);
} }
/** /**
* Append XML comparison. * Append XML comparison.
* *
* @param buf the SQL buffer to write the comparison * @param buf the SQL buffer to write the comparison
* @param op the comparison operation to perform * @param op the comparison operation to perform
* @param lhs the left hand side of the comparison * @param lhs the left hand side of the comparison
@ -368,10 +372,10 @@ public class MariaDBDictionary extends DBDictionary {
else else
rhs.appendTo(buf); rhs.appendTo(buf);
} }
/** /**
* Append XML column value so that it can be used in comparisons. * Append XML column value so that it can be used in comparisons.
* *
* @param buf the SQL buffer to write the value * @param buf the SQL buffer to write the value
* @param val the value to be written * @param val the value to be written
*/ */
@ -382,7 +386,7 @@ public class MariaDBDictionary extends DBDictionary {
val.appendTo(buf); val.appendTo(buf);
buf.append("')"); buf.append("')");
} }
@Override @Override
public int getBatchFetchSize(int batchFetchSize) { public int getBatchFetchSize(int batchFetchSize) {
return Integer.MIN_VALUE; return Integer.MIN_VALUE;
@ -401,10 +405,10 @@ public class MariaDBDictionary extends DBDictionary {
select += " " + hint; select += " " + hint;
return select; return select;
} }
@Override @Override
protected Collection<String> getSelectTableAliases(Select sel) { protected Collection<String> getSelectTableAliases(Select sel) {
Set<String> result = new HashSet<String>(); Set<String> result = new HashSet<>();
List<String> selects = sel.getIdentifierAliases(); List<String> selects = sel.getIdentifierAliases();
for (String s : selects) { for (String s : selects) {
String tableAlias = s.substring(0, s.indexOf('.')); String tableAlias = s.substring(0, s.indexOf('.'));
@ -412,12 +416,12 @@ public class MariaDBDictionary extends DBDictionary {
} }
return result; return result;
} }
@Override @Override
protected int matchErrorState(Map<Integer,Set<String>> errorStates, SQLException ex) { protected int matchErrorState(Map<Integer,Set<String>> errorStates, SQLException ex) {
int state = super.matchErrorState(errorStates, ex); int state = super.matchErrorState(errorStates, ex);
if (state == StoreException.GENERAL && if (state == StoreException.GENERAL &&
ex.getNextException() != null && ex.getNextException() != null &&
"JZ0002".equalsIgnoreCase(ex.getNextException().getSQLState())) { "JZ0002".equalsIgnoreCase(ex.getNextException().getSQLState())) {
if (conf != null && conf.getLockTimeout() != -1) { if (conf != null && conf.getLockTimeout() != -1) {
@ -449,7 +453,7 @@ public class MariaDBDictionary extends DBDictionary {
*/ */
@Override @Override
public String getTypeName(Column col) { public String getTypeName(Column col) {
// handle blobs differently, if the DBItentifierType is NULL (e.g. no column definition is set). // handle blobs differently, if the DBItentifierType is NULL (e.g. no column definition is set).
if (col.getType() == Types.BLOB && col.getTypeIdentifier().getType() == DBIdentifierType.NULL) { if (col.getType() == Types.BLOB && col.getTypeIdentifier().getType() == DBIdentifierType.NULL) {
if (col.getSize() <= 0) // unknown size if (col.getSize() <= 0) // unknown size
return blobTypeName; // return old default of 64KB return blobTypeName; // return old default of 64KB
@ -461,6 +465,17 @@ public class MariaDBDictionary extends DBDictionary {
return mediumBlobTypeName; return mediumBlobTypeName;
else else
return longBlobTypeName; return longBlobTypeName;
} else if (col.getType() == Types.CLOB && col.getTypeIdentifier().getType() == DBIdentifierType.NULL) {
if (col.getSize() <= 0) // unknown size
return clobTypeName; // return old default of 64KB
else if (col.getSize() <= 255)
return tinyTextTypeName;
else if (col.getSize() <= 65535)
return clobTypeName; // old default of 64KB
else if (col.getSize() <= 16777215)
return mediumTextTypeName;
else
return longTextTypeName;
} else { } else {
return super.getTypeName(col); return super.getTypeName(col);
} }

View File

@ -14,7 +14,7 @@
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.openjpa.jdbc.sql; package org.apache.openjpa.jdbc.sql;
@ -30,7 +30,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.jdbc.identifier.DBIdentifier; import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.identifier.DBIdentifier.DBIdentifierType; import org.apache.openjpa.jdbc.identifier.DBIdentifier.DBIdentifierType;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration; import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
@ -41,6 +40,7 @@ import org.apache.openjpa.jdbc.schema.ForeignKey;
import org.apache.openjpa.jdbc.schema.Index; import org.apache.openjpa.jdbc.schema.Index;
import org.apache.openjpa.jdbc.schema.PrimaryKey; import org.apache.openjpa.jdbc.schema.PrimaryKey;
import org.apache.openjpa.jdbc.schema.Table; import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.util.StoreException; import org.apache.openjpa.util.StoreException;
/** /**
@ -52,7 +52,7 @@ public class MySQLDictionary
public static final String SELECT_HINT = "openjpa.hint.MySQLSelectHint"; public static final String SELECT_HINT = "openjpa.hint.MySQLSelectHint";
public static final String DELIMITER_BACK_TICK = "`"; public static final String DELIMITER_BACK_TICK = "`";
/** /**
* The MySQL table type to use when creating tables; defaults to innodb. * The MySQL table type to use when creating tables; defaults to innodb.
*/ */
@ -70,8 +70,8 @@ public class MySQLDictionary
public boolean driverDeserializesBlobs = false; public boolean driverDeserializesBlobs = false;
/** /**
* Whether to inline multi-table bulk-delete operations into MySQL's * Whether to inline multi-table bulk-delete operations into MySQL's
* 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 * @see http://dev.mysql.com/doc/refman/5.0/en/delete.html
@ -81,6 +81,9 @@ public class MySQLDictionary
public static final String tinyBlobTypeName = "TINYBLOB"; public static final String tinyBlobTypeName = "TINYBLOB";
public static final String mediumBlobTypeName = "MEDIUMBLOB"; public static final String mediumBlobTypeName = "MEDIUMBLOB";
public static final String longBlobTypeName = "LONGBLOB"; public static final String longBlobTypeName = "LONGBLOB";
public static final String tinyTextTypeName = "TINYTEXT";
public static final String mediumTextTypeName = "MEDIUMTEXT";
public static final String longTextTypeName = "LONGTEXT";
public MySQLDictionary() { public MySQLDictionary() {
platform = "MySQL"; platform = "MySQL";
@ -121,15 +124,15 @@ public class MySQLDictionary
reservedWordSet.addAll(Arrays.asList(new String[]{ reservedWordSet.addAll(Arrays.asList(new String[]{
"AUTO_INCREMENT", "BINARY", "BLOB", "CHANGE", "ENUM", "INFILE", "AUTO_INCREMENT", "BINARY", "BLOB", "CHANGE", "ENUM", "INFILE",
"INT1", "INT2", "INT4", "FLOAT1", "FLOAT2", "FLOAT4", "LOAD", "INT1", "INT2", "INT4", "FLOAT1", "FLOAT2", "FLOAT4", "LOAD",
"MEDIUMINT", "OUTFILE", "REPLACE", "STARTING", "TEXT", "UNSIGNED", "MEDIUMINT", "OUTFILE", "REPLACE", "STARTING", "TEXT", "UNSIGNED",
"ZEROFILL", "INDEX", "ZEROFILL", "INDEX",
})); }));
// reservedWordSet subset that CANNOT be used as valid column names // reservedWordSet subset that CANNOT be used as valid column names
// (i.e., without surrounding them with double-quotes) // (i.e., without surrounding them with double-quotes)
invalidColumnWordSet.addAll(Arrays.asList(new String[]{ invalidColumnWordSet.addAll(Arrays.asList(new String[]{
"ADD", "ALL", "ALTER", "AND", "AS", "ASC", "BETWEEN", "BINARY", "ADD", "ALL", "ALTER", "AND", "AS", "ASC", "BETWEEN", "BINARY",
"BLOB", "BOTH", "BY", "CASCADE", "CASE", "CHANGE", "CHAR", "BLOB", "BOTH", "BY", "CASCADE", "CASE", "CHANGE", "CHAR",
"CHARACTER", "CHECK", "COLLATE", "COLUMN", "CONSTRAINT", "CONTINUE", "CHARACTER", "CHECK", "COLLATE", "COLUMN", "CONSTRAINT", "CONTINUE",
"CONVERT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CONVERT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME",
"CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "DEC", "DECIMAL", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "DEC", "DECIMAL",
@ -146,7 +149,7 @@ public class MySQLDictionary
"STARTING", "TABLE", "THEN", "TO", "TRAILING", "TRUE", "UNION", "STARTING", "TABLE", "THEN", "TO", "TRAILING", "TRUE", "UNION",
"UNIQUE", "UNSIGNED", "UPDATE", "USAGE", "USING", "VALUES", "UNIQUE", "UNSIGNED", "UPDATE", "USAGE", "USING", "VALUES",
"VARCHAR", "VARYING", "WHEN", "WHERE", "WITH", "WRITE", "ZEROFILL", "VARCHAR", "VARYING", "WHEN", "WHERE", "WITH", "WRITE", "ZEROFILL",
"INDEX", "INDEX",
})); }));
requiresSearchStringEscapeForLike = true; requiresSearchStringEscapeForLike = true;
@ -158,7 +161,7 @@ public class MySQLDictionary
setLeadingDelimiter(DELIMITER_BACK_TICK); setLeadingDelimiter(DELIMITER_BACK_TICK);
setTrailingDelimiter(DELIMITER_BACK_TICK); setTrailingDelimiter(DELIMITER_BACK_TICK);
fixedSizeTypeNameSet.remove("NUMERIC"); fixedSizeTypeNameSet.remove("NUMERIC");
} }
@ -206,7 +209,7 @@ public class MySQLDictionary
conn.setReadOnly(true); conn.setReadOnly(true);
return conn; return conn;
} }
private static int[] getMajorMinorVersions(String versionStr) private static int[] getMajorMinorVersions(String versionStr)
throws IllegalArgumentException { throws IllegalArgumentException {
int beginIndex = 0; int beginIndex = 0;
@ -275,7 +278,7 @@ public class MySQLDictionary
new String[]{ "ALTER TABLE " new String[]{ "ALTER TABLE "
+ getFullName(fk.getTable(), false) + getFullName(fk.getTable(), false)
+ " DROP FOREIGN KEY " + toDBName(fkName) }; + " DROP FOREIGN KEY " + toDBName(fkName) };
return retVal; return retVal;
} }
return new String[]{ "ALTER TABLE " return new String[]{ "ALTER TABLE "
+ getFullName(fk.getTable(), false) + getFullName(fk.getTable(), false)
@ -300,7 +303,7 @@ public class MySQLDictionary
System.arraycopy(sql, 0, ret, cols.length, sql.length); System.arraycopy(sql, 0, ret, cols.length, sql.length);
return ret; return ret;
} }
@Override @Override
public String[] getDeleteTableContentsSQL(Table[] tables,Connection conn) { public String[] getDeleteTableContentsSQL(Table[] tables,Connection conn) {
// mysql >= 4 supports more-optimal delete syntax // mysql >= 4 supports more-optimal delete syntax
@ -356,10 +359,10 @@ public class MySQLDictionary
return Types.LONGVARCHAR; return Types.LONGVARCHAR;
return super.getPreferredType(type); return super.getPreferredType(type);
} }
/** /**
* Append XML comparison. * Append XML comparison.
* *
* @param buf the SQL buffer to write the comparison * @param buf the SQL buffer to write the comparison
* @param op the comparison operation to perform * @param op the comparison operation to perform
* @param lhs the left hand side of the comparison * @param lhs the left hand side of the comparison
@ -381,10 +384,10 @@ public class MySQLDictionary
else else
rhs.appendTo(buf); rhs.appendTo(buf);
} }
/** /**
* Append XML column value so that it can be used in comparisons. * Append XML column value so that it can be used in comparisons.
* *
* @param buf the SQL buffer to write the value * @param buf the SQL buffer to write the value
* @param val the value to be written * @param val the value to be written
*/ */
@ -395,7 +398,7 @@ public class MySQLDictionary
val.appendTo(buf); val.appendTo(buf);
buf.append("')"); buf.append("')");
} }
@Override @Override
public int getBatchFetchSize(int batchFetchSize) { public int getBatchFetchSize(int batchFetchSize) {
return Integer.MIN_VALUE; return Integer.MIN_VALUE;
@ -414,10 +417,10 @@ public class MySQLDictionary
select += " " + hint; select += " " + hint;
return select; return select;
} }
@Override @Override
protected Collection<String> getSelectTableAliases(Select sel) { protected Collection<String> getSelectTableAliases(Select sel) {
Set<String> result = new HashSet<String>(); Set<String> result = new HashSet<>();
List<String> selects = sel.getIdentifierAliases(); List<String> selects = sel.getIdentifierAliases();
for (String s : selects) { for (String s : selects) {
String tableAlias = s.substring(0, s.indexOf('.')); String tableAlias = s.substring(0, s.indexOf('.'));
@ -425,7 +428,7 @@ public class MySQLDictionary
} }
return result; return result;
} }
@Override @Override
protected int matchErrorState(Map<Integer,Set<String>> errorStates, SQLException ex) { protected int matchErrorState(Map<Integer,Set<String>> errorStates, SQLException ex) {
int state = super.matchErrorState(errorStates, ex); int state = super.matchErrorState(errorStates, ex);
@ -462,7 +465,7 @@ public class MySQLDictionary
*/ */
@Override @Override
public String getTypeName(Column col) { public String getTypeName(Column col) {
// handle blobs differently, if the DBItentifierType is NULL (e.g. no column definition is set). // handle blobs differently, if the DBItentifierType is NULL (e.g. no column definition is set).
if (col.getType() == Types.BLOB && col.getTypeIdentifier().getType() == DBIdentifierType.NULL) { if (col.getType() == Types.BLOB && col.getTypeIdentifier().getType() == DBIdentifierType.NULL) {
if (col.getSize() <= 0) // unknown size if (col.getSize() <= 0) // unknown size
return blobTypeName; // return old default of 64KB return blobTypeName; // return old default of 64KB
@ -474,6 +477,17 @@ public class MySQLDictionary
return mediumBlobTypeName; return mediumBlobTypeName;
else else
return longBlobTypeName; return longBlobTypeName;
} else if (col.getType() == Types.CLOB && col.getTypeIdentifier().getType() == DBIdentifierType.NULL) {
if (col.getSize() <= 0) // unknown size
return clobTypeName; // return old default of 64KB
else if (col.getSize() <= 255)
return tinyTextTypeName;
else if (col.getSize() <= 65535)
return clobTypeName; // old default of 64KB
else if (col.getSize() <= 16777215)
return mediumTextTypeName;
else
return longTextTypeName;
} else { } else {
return super.getTypeName(col); return super.getTypeName(col);
} }

View File

@ -0,0 +1,85 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.persistence.blob.mysql;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
@Entity
public class ClobColumnEntity {
@Id
private int id;
@Lob
@Column(length = 20)
protected String smallLob;
@Lob
@Column(length = 66000)
protected String medLob;
@Lob
@Column(length = 16777216)
protected String longLob;
@Lob
protected String defaultLob;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSmallLob() {
return smallLob;
}
public void setSmallLob(String smallLob) {
this.smallLob = smallLob;
}
public String getMedLob() {
return medLob;
}
public void setMedLob(String medLob) {
this.medLob = medLob;
}
public String getLongLob() {
return longLob;
}
public void setLongLob(String longLob) {
this.longLob = longLob;
}
public String getDefaultLob() {
return defaultLob;
}
public void setDefaultLob(String defaultLob) {
this.defaultLob = defaultLob;
}
}

View File

@ -0,0 +1,95 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.persistence.blob.mysql;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.identifier.DBIdentifier.DBIdentifierType;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.jdbc.sql.MariaDBDictionary;
import org.apache.openjpa.jdbc.sql.MySQLDictionary;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
/**
* Testcase for MySQL Blob types. OPENJPA-740 introduced intelligent column type for BLOBs, OPENJPA-1870 refined it a
* bit.
*/
public class TestClobColumnType extends SingleEMFTestCase {
private static boolean _firstRun=true;
private boolean _runTest = false; // only test with MySQL
@Override
public void setUp() throws Exception {
// create EMF solely to obtain a DBDictionary.
// need to do this without ClobColumnEntity.class since it contains a column definition which might
// not work with all databases.
super.setUp((Object) null);
if (!(getDBDictionary() instanceof MySQLDictionary || getDBDictionary() instanceof MariaDBDictionary)) {
// normal teardown will take care of the EMF.
return;
}
// remove the EMF
tearDown();
_runTest = true;
super.setUp(ClobColumnEntity.class, DROP_TABLES, "openjpa.jdbc.SchemaFactory", "native");
if(_firstRun) {
emf.createEntityManager().close(); // trigger table creation.
_firstRun = false;
}
}
private Column getCol(String name) {
ClassMapping mapping = getMapping(ClobColumnEntity.class);
Table t = mapping.getTable();
Column col = t.getColumn(DBIdentifier.newIdentifier(name, DBIdentifierType.COLUMN, true));
assertNotNull(col);
return col;
}
public void testSmallLob() {
if (_runTest) {
assertEquals(MySQLDictionary.tinyTextTypeName, getCol("smallLob").getTypeIdentifier().getName());
}
}
public void testMedLob() {
if (_runTest) {
assertEquals(MySQLDictionary.mediumTextTypeName, getCol("medLob").getTypeIdentifier().getName());
}
}
public void testLongBlob() {
if (_runTest) {
assertEquals(MySQLDictionary.longTextTypeName, getCol("longLob").getTypeIdentifier().getName());
}
}
public void testDefaultLob() {
if (_runTest) {
assertEquals(getDBDictionary().blobTypeName, getCol("defaultLob").getTypeIdentifier().getName());
}
}
}