diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypecastAsNumber.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypecastAsNumber.java index d7c44faa14..4558e228f7 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypecastAsNumber.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypecastAsNumber.java @@ -160,7 +160,7 @@ public void appendTo(Select sel, ExpContext ctx, ExpState state, SQLBuffer sql, sql.append(part1); _val.appendTo(sel, ctx, etnstate.valueState, sql, 0); sql.append(part2); - sql.append(getDbNumberTargetTypeName(dict)); + sql.append(dict.getNumberCastTypeName(getType())); sql.append(part3); } @@ -175,23 +175,4 @@ public void acceptVisit(ExpressionVisitor visitor) { public int getId() { return Val.EXTRACTDTF_VAL; } - - private static String sanitize(String type) { - final int idx = type.indexOf('{'); - return idx < 0 ? type : type.substring(0, idx); - } - - private String getDbNumberTargetTypeName(DBDictionary dict) { - String type; - if (getType() == int.class) { - type = dict.integerCastTypeName; - } else if (getType() == long.class) { - type = dict.decimalTypeName; - } else if (getType() == float.class) { - type = dict.floatTypeName; - } else { - type = dict.doubleTypeName; - } - return sanitize(type); - } } diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypecastAsString.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypecastAsString.java index a4fb69b2a2..1db505ea77 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypecastAsString.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypecastAsString.java @@ -148,11 +148,7 @@ public void appendTo(Select sel, ExpContext ctx, ExpState state, sql.append(part1); _val.appendTo(sel, ctx, casstate.valueState, sql, 0); sql.append(part2); - if (dict.supportsUnsizedCharOnCast) { - sql.append(dict.varcharTypeName); - } else { - sql.append(dict.typecastToStringTypeName + "(" + dict.characterColumnSize + ")"); - } + sql.append(dict.getStringCastTypeName()); sql.append(part3); } diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java index 95f6bb573a..da5cdd38ab 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java @@ -18,6 +18,8 @@ */ package org.apache.openjpa.jdbc.sql; +import static java.util.Locale.ROOT; + import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.CharArrayReader; @@ -142,8 +144,6 @@ import org.apache.openjpa.util.UnsupportedException; import org.apache.openjpa.util.UserException; -import static java.util.Locale.ROOT; - /** * Class which allows the creation of SQL dynamically, in a @@ -511,7 +511,24 @@ public enum DateMillisecondBehaviors { DROP, ROUND, RETAIN } public boolean supportsUnsizedCharOnCast = true; - public String integerCastTypeName = integerTypeName; + /** + * Type name used as the target of a CAST to a 32 bit integer. + *
+ * Note: this is a field initializer, so it is evaluated before any subclass constructor runs. + * Dictionaries which change {@link #integerTypeName} do not implicitly change this value. + * Set it explicitly if the DDL type name is not a valid CAST target. + */ + public String integerCastTypeName = null; + + /** + * Type name used as the target of a CAST to a 64 bit integer. + *
+ * If null (the default), {@link #bigintTypeName} is resolved lazily by
+ * {@link #getLongCastTypeName()}. Resolving lazily rather than in a field initializer is deliberate:
+ * several dictionaries assign {@link #bigintTypeName} in their constructor or even in
+ * {@link #connectedConfiguration(java.sql.Connection)}, which happens after field initialization.
+ */
+ public String longCastTypeName = null;
// Naming utility and naming rules
private DBIdentifierUtil namingUtil = null;
@@ -2223,6 +2240,51 @@ protected int getDateFractionDigits(Column col, String typeName) {
return dateFractionDigits;
}
+ /**
+ * Return the type name to use as the target of a CAST to a 32 bit integer.
+ * Defaults to {@link #integerTypeName} unless {@link #integerCastTypeName} was set explicitly.
+ */
+ public String getIntegerCastTypeName() {
+ return integerCastTypeName == null ? integerTypeName : integerCastTypeName;
+ }
+
+ /**
+ * Return the type name to use as the target of a CAST to a 64 bit integer.
+ * Defaults to {@link #bigintTypeName} unless {@link #longCastTypeName} was set explicitly.
+ */
+ public String getLongCastTypeName() {
+ return longCastTypeName == null ? bigintTypeName : longCastTypeName;
+ }
+
+ /**
+ * Return the type name to use as the target of a CAST of a numeric value to the given java type.
+ * Any DDL size marker ({0}) is stripped, as CAST targets are not sized by the schema.
+ */
+ public String getNumberCastTypeName(Class> type) {
+ String name;
+ if (type == int.class || type == Integer.class) {
+ name = getIntegerCastTypeName();
+ } else if (type == long.class || type == Long.class) {
+ name = getLongCastTypeName();
+ } else if (type == float.class || type == Float.class) {
+ name = floatTypeName;
+ } else {
+ name = doubleTypeName;
+ }
+ return insertSize(name, null);
+ }
+
+ /**
+ * Return the type name to use as the target of a CAST to a string.
+ * Any DDL size marker ({0}) is stripped.
+ */
+ public String getStringCastTypeName() {
+ if (supportsUnsizedCharOnCast) {
+ return insertSize(varcharTypeName, null);
+ }
+ return insertSize(typecastToStringTypeName, null) + "(" + characterColumnSize + ")";
+ }
+
/**
* Helper method that inserts a size clause for a given SQL type.
*
@@ -5302,27 +5364,32 @@ public void startConfiguration() {
@Override
public void endConfiguration() {
// add additional reserved words set by user
- if (reservedWords != null)
+ if (reservedWords != null) {
reservedWordSet.addAll(Arrays.asList(StringUtil.split(reservedWords.toUpperCase(Locale.ENGLISH), ",", 0)));
+ }
// add system schemas set by user
- if (systemSchemas != null)
+ if (systemSchemas != null) {
systemSchemaSet.addAll(Arrays.asList(StringUtil.split(systemSchemas.toUpperCase(Locale.ENGLISH), ",", 0)));
+ }
// add system tables set by user
- if (systemTables != null)
+ if (systemTables != null) {
systemTableSet.addAll(Arrays.asList(StringUtil.split(systemTables.toUpperCase(Locale.ENGLISH), ",", 0)));
+ }
// add fixed size type names set by the user
- if (fixedSizeTypeNames != null)
+ if (fixedSizeTypeNames != null) {
fixedSizeTypeNameSet.addAll(Arrays.asList(StringUtil.split(fixedSizeTypeNames.toUpperCase(Locale.ENGLISH), ",", 0)));
+ }
// if user has unset sequence sql, null it out so we know sequences
// aren't supported
nextSequenceQuery = StringUtil.trimToNull(nextSequenceQuery);
- if (selectWords != null)
+ if (selectWords != null) {
selectWordSet.addAll(Arrays.asList(StringUtil.split(selectWords.toUpperCase(Locale.ENGLISH), ",", 0)));
+ }
if (invalidColumnWordSet.isEmpty()) {
Collection