From 50da819acbfd3ba7f5a975534801da170ddfa94f Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Sat, 8 Mar 2014 13:57:48 +0100 Subject: [PATCH] [#3108] Local Fields' Converters should be preferred over globally registered Converters --- .../java/org/jooq/util/JavaGenerator.java | 21 +++-- .../org/jooq/test/_/testcases/CRUDTests.java | 2 + .../org/jooq/test/_/testcases/EnumTests.java | 22 +++-- .../src/org/jooq/test/jOOQAbstractTest.java | 5 ++ jOOQ/src/main/java/org/jooq/ArrayRecord.java | 21 +++-- jOOQ/src/main/java/org/jooq/BindContext.java | 14 ++++ jOOQ/src/main/java/org/jooq/Field.java | 9 ++ .../org/jooq/impl/AbstractBindContext.java | 20 ++++- .../java/org/jooq/impl/AbstractField.java | 18 +++- .../java/org/jooq/impl/AbstractTable.java | 19 ++++- .../java/org/jooq/impl/ArrayConstant.java | 10 ++- .../java/org/jooq/impl/ArrayRecordImpl.java | 18 ++-- .../main/java/org/jooq/impl/ArrayTable.java | 2 +- .../java/org/jooq/impl/ConvertedDataType.java | 6 +- .../main/java/org/jooq/impl/DataTypes.java | 56 ------------- .../org/jooq/impl/DefaultBindContext.java | 13 ++- .../java/org/jooq/impl/EnumConverter.java | 5 ++ .../java/org/jooq/impl/IdentityConverter.java | 84 +++++++++++++++++++ .../java/org/jooq/impl/ParamCollector.java | 3 +- .../main/java/org/jooq/impl/TableAlias.java | 2 +- .../java/org/jooq/impl/TableFieldImpl.java | 5 +- .../main/java/org/jooq/impl/UDTConstant.java | 2 +- jOOQ/src/main/java/org/jooq/impl/Utils.java | 10 +-- jOOQ/src/main/java/org/jooq/impl/Val.java | 48 +++++------ jOOQ/src/main/java/org/jooq/impl/Values.java | 1 - .../test/java/org/jooq/test/BasicTest.java | 4 +- 26 files changed, 275 insertions(+), 145 deletions(-) create mode 100644 jOOQ/src/main/java/org/jooq/impl/IdentityConverter.java diff --git a/jOOQ-codegen/src/main/java/org/jooq/util/JavaGenerator.java b/jOOQ-codegen/src/main/java/org/jooq/util/JavaGenerator.java index eef04875b9..5248dec0ee 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/util/JavaGenerator.java +++ b/jOOQ-codegen/src/main/java/org/jooq/util/JavaGenerator.java @@ -94,6 +94,7 @@ import org.jooq.tools.StringUtils; import org.jooq.tools.reflect.Reflect; import org.jooq.tools.reflect.ReflectException; import org.jooq.util.GeneratorStrategy.Mode; +import org.jooq.util.jaxb.CustomType; import org.jooq.util.postgres.PostgresDatabase; @@ -1748,13 +1749,23 @@ public class JavaGenerator extends AbstractGenerator { final String columnId = getStrategy().getJavaIdentifier(column); final String columnName = column.getName(); final String columnComment = StringUtils.defaultString(column.getComment()); + final CustomType columnCustomType = database.getConfiguredCustomType(column.getType().getUserType()); String isStatic = generateInstanceFields() ? "" : "static "; String tableRef = generateInstanceFields() ? "this" : getStrategy().getJavaIdentifier(table); out.tab(1).javadoc("The column %s.%s", column.getQualifiedOutputName(), defaultIfBlank(" " + columnComment, "")); - out.tab(1).println("public %sfinal %s<%s, %s> %s = createField(\"%s\", %s, %s, \"%s\");", - isStatic, TableField.class, recordType, columnType, columnId, columnName, columnTypeRef, tableRef, escapeString(columnComment)); + + if (columnCustomType != null) { + String converter = columnCustomType.getConverter(); + + out.tab(1).println("public %sfinal %s<%s, %s> %s = createField(\"%s\", %s, %s, \"%s\", new %s());", + isStatic, TableField.class, recordType, columnType, columnId, columnName, columnTypeRef, tableRef, escapeString(columnComment), converter); + } + else { + out.tab(1).println("public %sfinal %s<%s, %s> %s = createField(\"%s\", %s, %s, \"%s\");", + isStatic, TableField.class, recordType, columnType, columnId, columnName, columnTypeRef, tableRef, escapeString(columnComment)); + } } // [#1255] With instance fields, the table constructor may @@ -2884,12 +2895,6 @@ public class JavaGenerator extends AbstractGenerator { if (dataType.defaulted()) { sb.append(".defaulted(true)"); } - - if (db.getConfiguredCustomType(u) != null) { - sb.append(".asConvertedDataType(new "); - sb.append(db.getConfiguredCustomType(u).getConverter()); - sb.append("())"); - } } // Otherwise, reference the dialect-specific DataType itself. diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/CRUDTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/CRUDTests.java index 7ae78eb134..2dda817d75 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/CRUDTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/CRUDTests.java @@ -51,6 +51,7 @@ import static junit.framework.Assert.fail; // ... import static org.jooq.SQLDialect.SQLITE; import static org.jooq.impl.DSL.count; +import static org.jooq.impl.DSL.table; import java.sql.Date; import java.sql.Timestamp; @@ -65,6 +66,7 @@ import org.jooq.Record1; import org.jooq.Record2; import org.jooq.Record3; import org.jooq.Record6; +import org.jooq.SQLDialect; import org.jooq.StoreQuery; import org.jooq.Table; import org.jooq.TableField; diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/EnumTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/EnumTests.java index 5f0fc27ff8..7a58aebbdd 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/EnumTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/EnumTests.java @@ -49,6 +49,7 @@ import static org.junit.Assert.assertTrue; import java.sql.Date; import java.util.List; +import org.jooq.DSLContext; import org.jooq.EnumType; import org.jooq.Field; import org.jooq.Record1; @@ -58,6 +59,8 @@ import org.jooq.Record6; import org.jooq.Result; import org.jooq.TableRecord; import org.jooq.UpdatableRecord; +import org.jooq.conf.Settings; +import org.jooq.conf.StatementType; import org.jooq.test.BaseTest; import org.jooq.test.jOOQAbstractTest; import org.jooq.test._.converters.Boolean_10; @@ -128,6 +131,15 @@ extends BaseTest> void testCustomEnums() throws Exception { + testCustomEnums0(create()); + } + + @Test + public > void testCustomEnumsWithInline() throws Exception { + testCustomEnums0(create(new Settings().withStatementType(StatementType.STATIC_STATEMENT))); + } + + private > void testCustomEnums0(DSLContext create) throws Exception { jOOQAbstractTest.reset = false; // This does not yet work correctly for Sybase ASE, Postgres @@ -141,7 +153,7 @@ extends BaseTest result = - create().selectFrom(TBooleans()) + create .selectFrom(TBooleans()) .where(TBooleans_ID().in(1, 2, 3)) .and(TBooleans_BOOLEAN_10().in(Boolean_10.ONE, Boolean_10.ZERO) .or(TBooleans_BOOLEAN_10().isNull())) @@ -258,7 +270,7 @@ extends BaseTest b = - create().selectFrom(TBooleans()) + create .selectFrom(TBooleans()) .orderBy(TBooleans_ID().asc()) .fetchInto(TBooleansPojo()); diff --git a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java index e4e798e065..ba7a40ca59 100644 --- a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java +++ b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java @@ -2296,6 +2296,11 @@ public abstract class jOOQAbstractTest< new EnumTests(this).testCustomEnums(); } + @Test + public > void testCustomEnumsWithInline() throws Exception { + new EnumTests(this).testCustomEnumsWithInline(); + } + @Test public void testSerialisation() throws Exception { new GeneralTests(this).testSerialisation(); diff --git a/jOOQ/src/main/java/org/jooq/ArrayRecord.java b/jOOQ/src/main/java/org/jooq/ArrayRecord.java index 5929f32997..3a9fc378ca 100644 --- a/jOOQ/src/main/java/org/jooq/ArrayRecord.java +++ b/jOOQ/src/main/java/org/jooq/ArrayRecord.java @@ -56,43 +56,48 @@ xxx xxxxxx xxxxxxxxx xxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxx xxxxxxxxxxx x xxx - x xxx xxx xxxxxxxxx xxxxx + x xxx xxx xxxxxxxxx xxxxxx xx xxx xxxxxx xxx - x xxx xxx xxxxxxxxx xxxxx xx x xxxxxx xxxxx + x xxx xxx xxxxxxxxx xxxxx xx x xxxxxx xxxxxx xx xxxxxxx xxxxxxxxxx xxx - x xxx xxx xxxxxxxxx xxxxx + x xxx xxx xxxxxxxxx xxxxxx xx xxxx xxxxxxxxx xxxxxx xxxxxx xxxxxxxxxxxxx xxx - x xxx xxx xxxxxxxxx xxxxx + x xxx xxx xxxxxxxxx xxxxxx xx xxxx xxxxxxxx xxxxxxx xxx - x xxx xxx xxxxxxxxx xxxxx xx x xxxxxx xxxxx + x xxx xxx xxxxxxxxx xxxxx xx x xxxxxx xxxxxx xx xxxx xxxxxxxxxxxxxx xxxxxxx xx xxxxxx xxx - x xxx xxx xxxx xx xxx xxxxxxxxx xxxxx + x xxx xxx xxxx xx xxx xxxxxxxxx xxxxxx xx xxx xxxxxxx xxx - x xxx xxx xxxx xx xxx xxxxx xxxx + x xxx xxx xxxx xx xxx xxxxx xxxxx xx xxxxxx xxxxxxxxxx xxx - x xxx xxx xxxx xxxx xx xxx xxxxx xxxx + x xxx xxx xxxx xxxx xx xxx xxxxxxx xxxx xxxxx xx xxxxxxxxxxx xxxxxxxxxxxxxx + + xxx + x xxx xxx xxxx xxxx xx xxx xxxxxx + xx + xxxxxxxxxxx xxxxxxxxxxxxxxx x xx [/pro] */ \ No newline at end of file diff --git a/jOOQ/src/main/java/org/jooq/BindContext.java b/jOOQ/src/main/java/org/jooq/BindContext.java index f6683de08b..516943f642 100644 --- a/jOOQ/src/main/java/org/jooq/BindContext.java +++ b/jOOQ/src/main/java/org/jooq/BindContext.java @@ -102,7 +102,9 @@ public interface BindContext extends Context { * * @throws DataAccessException If something went wrong while binding a * variable + * @deprecated - 3.4.0 - [#3114] - Use {@link #bindValue(Object, Field)} instead */ + @Deprecated BindContext bindValue(Object value, Class type) throws DataAccessException; /** @@ -110,6 +112,18 @@ public interface BindContext extends Context { * * @throws DataAccessException If something went wrong while binding a * variable + * @deprecated - 3.4.0 - [#3114] - Use {@link #bindValue(Object, Field)} instead */ + @Deprecated BindContext bindValues(Object... values) throws DataAccessException; + + /** + * Bind a value using a specific type. This will also increment the internal + * counter. + * + * @throws DataAccessException If something went wrong while binding a + * variable + */ + BindContext bindValue(Object value, Field field) throws DataAccessException; + } diff --git a/jOOQ/src/main/java/org/jooq/Field.java b/jOOQ/src/main/java/org/jooq/Field.java index 14913b95bf..57d86d5cd1 100644 --- a/jOOQ/src/main/java/org/jooq/Field.java +++ b/jOOQ/src/main/java/org/jooq/Field.java @@ -126,6 +126,15 @@ public interface Field extends GroupField { */ String getComment(); + /** + * The field's underlying {@link Converter}. + *

+ * By default, all fields reference an identity-converter + * Converter<T, T>. Custom data types may be obtained by a + * custom {@link Converter} placed on the generated {@link TableField}. + */ + Converter getConverter(); + /** * The Java type of the field. */ diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractBindContext.java b/jOOQ/src/main/java/org/jooq/impl/AbstractBindContext.java index 5c4867cbad..04e3cac041 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractBindContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractBindContext.java @@ -47,8 +47,10 @@ import java.util.Collection; import org.jooq.BindContext; import org.jooq.Configuration; +import org.jooq.Field; import org.jooq.QueryPart; import org.jooq.QueryPartInternal; +import org.jooq.exception.DataAccessException; /** * A base class for {@link BindContext} implementations @@ -89,6 +91,7 @@ abstract class AbstractBindContext extends AbstractContext implemen } @Override + @Deprecated public final BindContext bindValues(Object... values) { // [#724] When values is null, this is probably due to API-misuse @@ -99,7 +102,7 @@ abstract class AbstractBindContext extends AbstractContext implemen else { for (Object value : values) { Class type = (value == null) ? Object.class : value.getClass(); - bindValue(value, type); + bindValue(value, DSL.val(value, type)); } } @@ -107,9 +110,20 @@ abstract class AbstractBindContext extends AbstractContext implemen } @Override + @Deprecated public final BindContext bindValue(Object value, Class type) { try { - return bindValue0(value, type); + return bindValue0(value, DSL.val(value, type)); + } + catch (SQLException e) { + throw Utils.translate(null, e); + } + } + + @Override + public final BindContext bindValue(Object value, Field field) throws DataAccessException { + try { + return bindValue0(value, field); } catch (SQLException e) { throw Utils.translate(null, e); @@ -131,7 +145,7 @@ abstract class AbstractBindContext extends AbstractContext implemen * Subclasses may override this method to achieve different behaviour */ @SuppressWarnings("unused") - protected BindContext bindValue0(Object value, Class type) throws SQLException { + protected BindContext bindValue0(Object value, Field field) throws SQLException { return this; } diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java index f66cb062d4..db0935a1d7 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java @@ -87,6 +87,7 @@ import org.jooq.Comparator; import org.jooq.Condition; import org.jooq.Configuration; import org.jooq.Context; +import org.jooq.Converter; import org.jooq.DataType; import org.jooq.DatePart; import org.jooq.Field; @@ -114,17 +115,25 @@ abstract class AbstractField extends AbstractQueryPart implements Field { private final String name; private final String comment; private final DataType dataType; + private final Converter converter; AbstractField(String name, DataType type) { - this(name, type, null); + this(name, type, null, null); } - AbstractField(String name, DataType type, String comment) { + @SuppressWarnings("unchecked") + AbstractField(String name, DataType type, String comment, Converter converter) { super(); this.name = name; this.comment = defaultString(comment); this.dataType = type; + this.converter = + converter != null + ? converter + : type instanceof ConvertedDataType + ? ((ConvertedDataType) type).converter() + : new IdentityConverter(type.getType()); } // ------------------------------------------------------------------------ @@ -161,6 +170,11 @@ abstract class AbstractField extends AbstractQueryPart implements Field { return comment; } + @Override + public final Converter getConverter() { + return converter; + } + @Override public final DataType getDataType() { return dataType; diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java b/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java index 57909872e0..3c5c307ef6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java @@ -62,6 +62,7 @@ import java.util.List; import org.jooq.Clause; import org.jooq.Context; +import org.jooq.Converter; import org.jooq.DataType; import org.jooq.DivideByOnStep; import org.jooq.Field; @@ -325,7 +326,23 @@ abstract class AbstractTable extends AbstractQueryPart impleme * @param type The data type of the field */ protected static final TableField createField(String name, DataType type, Table table, String comment) { - final TableFieldImpl tableField = new TableFieldImpl(name, type, table, comment); + return createField(name, type, table, comment, null); + } + + /** + * Subclasses may call this method to create {@link TableField} objects that + * are linked to this table. + * + * @param name The name of the field (case-sensitive!) + * @param type The data type of the field + */ + @SuppressWarnings("unchecked") + protected static final TableField createField(String name, DataType type, Table table, String comment, Converter converter) { + final DataType actualType = converter == null + ? (DataType) type + : type.asConvertedDataType(converter); + + final TableFieldImpl tableField = new TableFieldImpl(name, actualType, table, comment, converter); // [#1199] The public API of Table returns immutable field lists if (table instanceof TableImpl) { diff --git a/jOOQ/src/main/java/org/jooq/impl/ArrayConstant.java b/jOOQ/src/main/java/org/jooq/impl/ArrayConstant.java index 0b32c49ef3..68a1225d50 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ArrayConstant.java +++ b/jOOQ/src/main/java/org/jooq/impl/ArrayConstant.java @@ -57,12 +57,18 @@ xxxxx xxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxxxxx x xxxxxxx xxxxxx xxxxx xxxx xxxxxxxxxxxxxxxx x xxxxxxxxxxxxxxxxxxxxxx xxxxxxx xxxxx x xxxxxx + xxxxxxx xxxxx xxxxxxxxxxx xxxxxxxxx xxxxxxxxxxxxxxxxxxx xxxxxxxxxxx xxxxxxxxxxx xx xxxxxxxxxxxxxxx xxxxxx x - xxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxx x xxxxxx + xxxxxxxxxxxxx x xxxxxxxxxxxxxxxxxxxx + x + + xxxxx xxxxxxxxxxx xxxxxxxxxxxxx x + xxxxxx xxxxxxxxx x xxxxxxxxx @@ -88,7 +94,7 @@ xxxxx xxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxxxxx x xxxxxxxxx xxxxxx xxxxx xxxx xxxxxxxxxxxxxxxx xxxxxxxx x - xxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxx xxxxxx x x xx [/pro] */ \ No newline at end of file diff --git a/jOOQ/src/main/java/org/jooq/impl/ArrayRecordImpl.java b/jOOQ/src/main/java/org/jooq/impl/ArrayRecordImpl.java index f84a5856c8..a49aa839ca 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ArrayRecordImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ArrayRecordImpl.java @@ -72,6 +72,7 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx xxxxxxx xxxxxx xxxxx xxxx xxxxxxxxxxxxxxxx x xxxxxxxxxxxxxxxxxxxxx xxxxxxx xxxxx xxxxxx xxxxxxx + xxxxxxx xxxxx xxxxxxxxxxx xxxxxxxxx xxxxxxx xxxxx xxxxxxxxxxx xxxxx xxxxxxx xxxxx xxxxxx xxxxx xxxxxxx xxx xxxxxx @@ -85,10 +86,10 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx xxxxxxxxxxx x xxxxxxx xxxxxxxxx x xxxxx - xxxxxxxxx x xxxxx + xxxxxxxxxxxxx x xxxxx xx xxxxx xxxx xxxx xxxxxxxxxxxxxx - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x xxx @@ -106,7 +107,7 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx xxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx x xxxxxxxxxxxxxxxx xxxxxx x xxx xxxxxxxxxxxxxxxxxxxxxxxx - xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x + xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x xxx xx xxxxxxx x xxxxxx x xxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxx x @@ -128,7 +129,7 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx xxxxxxxxx xxxxxx xxxxx xxx xxxxx x xx xxxxxx xx xxxxx x - xxxxxx xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxx + xxxxxx xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxx x xxxx x xxxxxx xxxxxx @@ -162,7 +163,7 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx xx xxxxxx xxxxx xxxx xxxx xx xxxx xx xxxxxxx xxxx xx xxxxxx xx xx xxxxxxxxx xxxxxxx xxx xxxxxx xxxxxxx x x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - xxxxxxxxxx x xxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxx x xxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxx x x @@ -173,7 +174,7 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx xxxxx x xxxxx x xxxx x - xxxxx x xxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxx + xxxxx x xxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxx x x @@ -198,6 +199,11 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx xxxxxxxxx xxxxxx xxxxx xxxxxxxxxxx xxxxxxxxxxxxx x + xxxxxx xxxxxxxxx + x + + xxxxxxxxx + xxxxxx xxxxx xxxxxxxxxxx xxxxxxxxxxxxxx x xxxxxx xxxxx x diff --git a/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java b/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java index e9a137d082..6d3498f569 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java @@ -93,7 +93,7 @@ class ArrayTable extends AbstractTable { /* [pro] xx xx xxxxxxx xxxx xxxxx xx xxxxxxx xxxx xxxxxxxxxxx xx xxxxxx xxxxxx x xxxxx xxxxx xxxx xx xxxxxx xxxxxxxxxx xxxxxxxxxxxxxx x - xxxxxxxxx x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx x xxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x xx xxxxxxx xxxx xxxxx xx xxxxxxx xxxx xxxxxxxxxxx xx xxxxxx diff --git a/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java b/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java index 928dd8ffa5..89ee41157e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java @@ -64,8 +64,6 @@ class ConvertedDataType extends DefaultDataType { this.delegate = delegate; this.converter = converter; - - DataTypes.registerConverter(converter.toType(), converter); } @Override @@ -88,4 +86,8 @@ class ConvertedDataType extends DefaultDataType { public U convert(Object object) { return converter.from(delegate.convert(converter.to((U) object))); } + + Converter converter() { + return converter; + } } diff --git a/jOOQ/src/main/java/org/jooq/impl/DataTypes.java b/jOOQ/src/main/java/org/jooq/impl/DataTypes.java index 769b7c0189..ea5b57828d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DataTypes.java +++ b/jOOQ/src/main/java/org/jooq/impl/DataTypes.java @@ -48,9 +48,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import org.jooq.Converter; import org.jooq.DataType; -import org.jooq.exception.DataTypeException; /** * A central {@link DataType} registry @@ -59,7 +57,6 @@ import org.jooq.exception.DataTypeException; */ final class DataTypes { - private static final Map, Converter> CONVERTERS = new HashMap, Converter>(); private static final Map> UDT_RECORDS = new HashMap>(); // ------------------------------------------------------------------------ @@ -67,52 +64,6 @@ final class DataTypes { // (this may be rendered public in the future) // ------------------------------------------------------------------------ - /** - * Register a Converter for a custom type - *

- * This registers a {@link Converter} for a custom type. This converter will - * be used by jOOQ to recognise custom types and to transform them back to - * well-known database types (as defined in {@link Converter#fromType()}) in - * rendering and binding steps - *

- * A custom type can be registered only once. Duplicate registrations will - * be ignored - *

- * The converter class must provide a default constructor. - * - * @see #registerConverter(Class, Converter) - */ - static final synchronized void registerConverter(Class customType, - Class> converter) { - - try { - converter.getConstructor().setAccessible(true); - registerConverter(customType, converter.newInstance()); - } - catch (Exception e) { - throw new DataTypeException("Cannot register converter", e); - } - } - - /** - * Register a Converter for a custom type - *

- * This registers a {@link Converter} for a custom type. This converter will - * be used by jOOQ to recognise custom types and to transform them back to - * well-known database types (as defined in {@link Converter#fromType()}) in - * rendering and binding steps - *

- * A custom type can be registered only once. Duplicate registrations will - * be ignored - */ - static final synchronized void registerConverter(Class customType, Converter converter) { - - // A converter can be registered only once - if (!CONVERTERS.containsKey(customType)) { - CONVERTERS.put(customType, converter); - } - } - /** * Register a type mapping for a UDT *

@@ -134,13 +85,6 @@ final class DataTypes { // XXX: Internal API // ------------------------------------------------------------------------ - @SuppressWarnings("unchecked") - static final Converter converter(Class customType) { - - // TODO: Is synchronisation needed? How to implement it most efficiently? - return (Converter) CONVERTERS.get(customType); - } - static final Map> udtRecords() { return Collections.unmodifiableMap(UDT_RECORDS); } diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java index 144913fad6..e0ff3b46c4 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java @@ -72,6 +72,7 @@ import org.jooq.BindContext; import org.jooq.Configuration; import org.jooq.Converter; import org.jooq.EnumType; +import org.jooq.Field; import org.jooq.SQLDialect; import org.jooq.UDTRecord; import org.jooq.exception.SQLDialectNotSupportedException; @@ -106,15 +107,13 @@ class DefaultBindContext extends AbstractBindContext { @Override @SuppressWarnings({ "unchecked", "rawtypes" }) - protected final BindContext bindValue0(Object value, Class type) throws SQLException { + protected final BindContext bindValue0(Object value, Field field) throws SQLException { SQLDialect dialect = configuration.dialect(); - // [#650] Check first, if we have a converter for the supplied type - Converter converter = DataTypes.converter(type); - if (converter != null) { - value = ((Converter) converter).to(value); - type = converter.fromType(); - } + // [#650] [#3108] Use the Field's Converter before actually binding any value + Converter converter = field.getConverter(); + Class type = converter.fromType(); + value = ((Converter) converter).to(value); if (log.isTraceEnabled()) { if (value != null && value.getClass().isArray() && value.getClass() != byte[].class) { diff --git a/jOOQ/src/main/java/org/jooq/impl/EnumConverter.java b/jOOQ/src/main/java/org/jooq/impl/EnumConverter.java index 5691e74db1..94981c8fe7 100644 --- a/jOOQ/src/main/java/org/jooq/impl/EnumConverter.java +++ b/jOOQ/src/main/java/org/jooq/impl/EnumConverter.java @@ -126,4 +126,9 @@ public class EnumConverter> implements Converter { */ STRING } + + @Override + public String toString() { + return "EnumConverter [ from : " + fromType.getName() + ", to : " + toType.getName() + " ]"; + } } diff --git a/jOOQ/src/main/java/org/jooq/impl/IdentityConverter.java b/jOOQ/src/main/java/org/jooq/impl/IdentityConverter.java new file mode 100644 index 0000000000..a47d5e18c4 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/IdentityConverter.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2009-2014, Data Geekery GmbH (http://www.datageekery.com) + * All rights reserved. + * + * This work is dual-licensed + * - under the Apache Software License 2.0 (the "ASL") + * - under the jOOQ License and Maintenance Agreement (the "jOOQ License") + * ============================================================================= + * You may choose which license applies to you: + * + * - If you're using this work with Open Source databases, you may choose + * either ASL or jOOQ License. + * - If you're using this work with at least one commercial database, you must + * choose jOOQ License + * + * For more information, please visit http://www.jooq.org/licenses + * + * Apache Software License 2.0: + * ----------------------------------------------------------------------------- + * Licensed 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. + * + * jOOQ License and Maintenance Agreement: + * ----------------------------------------------------------------------------- + * Data Geekery grants the Customer the non-exclusive, timely limited and + * non-transferable license to install and use the Software under the terms of + * the jOOQ License and Maintenance Agreement. + * + * This library is distributed with a LIMITED WARRANTY. See the jOOQ License + * and Maintenance Agreement for more details: http://www.jooq.org/licensing + */ +package org.jooq.impl; + +import org.jooq.Converter; + +/** + * @author Lukas Eder + */ +class IdentityConverter implements Converter { + + /** + * Generated UID + */ + private static final long serialVersionUID = -1721687282753727624L; + private final Class type; + + IdentityConverter(Class type) { + this.type = type; + } + + @Override + public final T from(T t) { + return t; + } + + @Override + public final T to(T t) { + return t; + } + + @Override + public final Class fromType() { + return type; + } + + @Override + public final Class toType() { + return type; + } + + @Override + public String toString() { + return "IdentityConverter [" + type.getName() + "]"; + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/ParamCollector.java b/jOOQ/src/main/java/org/jooq/impl/ParamCollector.java index 8b390b1168..d1298d7c45 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParamCollector.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParamCollector.java @@ -47,6 +47,7 @@ import java.util.Map; import org.jooq.BindContext; import org.jooq.Configuration; +import org.jooq.Field; import org.jooq.Param; import org.jooq.QueryPart; import org.jooq.QueryPartInternal; @@ -90,7 +91,7 @@ class ParamCollector extends AbstractBindContext { } @Override - protected final BindContext bindValue0(Object value, Class type) throws SQLException { + protected final BindContext bindValue0(Object value, Field field) throws SQLException { throw new UnsupportedOperationException(); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/TableAlias.java b/jOOQ/src/main/java/org/jooq/impl/TableAlias.java index 475210a833..ec8491f74e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TableAlias.java +++ b/jOOQ/src/main/java/org/jooq/impl/TableAlias.java @@ -100,7 +100,7 @@ class TableAlias extends AbstractTable { name = fieldAliases[i]; } - result.add(new TableFieldImpl(name, field.getDataType(), this, field.getComment())); + result.add(new TableFieldImpl(name, field.getDataType(), this, field.getComment(), field.getConverter())); } return new Fields(result); diff --git a/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java b/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java index f28ee91eeb..191e35ef6c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java @@ -48,6 +48,7 @@ import static org.jooq.impl.Utils.DATA_OMIT_CLAUSE_EVENT_EMISSION; import org.jooq.BindContext; import org.jooq.Clause; import org.jooq.Context; +import org.jooq.Converter; import org.jooq.DataType; import org.jooq.Record; import org.jooq.RenderContext; @@ -67,8 +68,8 @@ class TableFieldImpl extends AbstractField implements Ta private final Table table; - TableFieldImpl(String name, DataType type, Table table, String comment) { - super(name, type, comment); + TableFieldImpl(String name, DataType type, Table table, String comment, Converter converter) { + super(name, type, comment, converter); this.table = table; } diff --git a/jOOQ/src/main/java/org/jooq/impl/UDTConstant.java b/jOOQ/src/main/java/org/jooq/impl/UDTConstant.java index 9816afe3ae..e50e0e26cb 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UDTConstant.java +++ b/jOOQ/src/main/java/org/jooq/impl/UDTConstant.java @@ -162,7 +162,7 @@ class UDTConstant> extends AbstractParam { xx xxxxxx xxxxxxxx xxxxxxxxxxxxxxxxx xxxxx xxx xxxxxx xxx xx xxxxx xx xx xxx xxxxxxxxxxxxxxxxx xxxxxxxx xxxx xxxxxxx - xxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxx xxxxxx xxxxxx xx xx xxx xxx xxxx xxxxxxxx xxxxxx xx xx xxxxxxx xxxx xxx xxxxxxxx xxxxx diff --git a/jOOQ/src/main/java/org/jooq/impl/Utils.java b/jOOQ/src/main/java/org/jooq/impl/Utils.java index f34b31ac03..c7cb9fd018 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Utils.java +++ b/jOOQ/src/main/java/org/jooq/impl/Utils.java @@ -2255,14 +2255,8 @@ final class Utils { static final U getFromResultSet(ExecuteContext ctx, Field field, int index) throws SQLException { @SuppressWarnings("unchecked") - Converter converter = (Converter) DataTypes.converter(field.getType()); - - if (converter != null) { - return converter.from(getFromResultSet(ctx, converter.fromType(), index)); - } - else { - return getFromResultSet(ctx, field.getType(), index); - } + Converter converter = (Converter) field.getConverter(); + return converter.from(getFromResultSet(ctx, converter.fromType(), index)); } @SuppressWarnings("unchecked") diff --git a/jOOQ/src/main/java/org/jooq/impl/Val.java b/jOOQ/src/main/java/org/jooq/impl/Val.java index 961abe57ba..35511c3462 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Val.java +++ b/jOOQ/src/main/java/org/jooq/impl/Val.java @@ -108,7 +108,7 @@ class Val extends AbstractParam { // Casting can be enforced or prevented switch (context.castMode()) { case NEVER: - toSQL(context, value, getType()); + toSQL(context, value, getConverter()); return; case ALWAYS: @@ -127,7 +127,7 @@ class Val extends AbstractParam { toSQLCast(context); } else { - toSQL(context, value, getType()); + toSQL(context, value, getConverter()); } return; @@ -140,7 +140,7 @@ class Val extends AbstractParam { // Most RDBMS can infer types for bind values else { - toSQL(context, value, getType()); + toSQL(context, value, getConverter()); } } @@ -245,7 +245,7 @@ class Val extends AbstractParam { // [#1125] Also with temporal data types, casting is needed some times // [#1130] TODO type can be null for ARRAY types, etc. else if (family == POSTGRES && (type == null || !type.isTemporal())) { - toSQL(context, value, getType()); + toSQL(context, value, getConverter()); } // [#1727] VARCHAR types should be cast to their actual lengths in some @@ -291,7 +291,7 @@ class Val extends AbstractParam { private final void toSQLCast(RenderContext context, DataType type, int length, int precision, int scale) { context.keyword("cast").sql("("); - toSQL(context, value, getType()); + toSQL(context, value, getConverter()); context.sql(" ").keyword("as").sql(" ") .sql(type.length(length).precision(precision, scale).getCastTypeName(context.configuration())) .sql(")"); @@ -317,31 +317,16 @@ class Val extends AbstractParam { } } - /** - * Inlining abstraction - */ - private final void toSQL(RenderContext context, Object val) { - if (val == null) { - toSQL(context, val, Object.class); - } - else { - toSQL(context, val, val.getClass()); - } - } - /** * Inlining abstraction */ @SuppressWarnings({ "unchecked", "rawtypes" }) - private final void toSQL(RenderContext context, Object val, Class type) { + private final void toSQL(RenderContext context, Object val, Converter converter) { SQLDialect family = context.configuration().dialect().family(); - // [#650] Check first, if we have a converter for the supplied type - Converter converter = DataTypes.converter(type); - if (converter != null) { - val = ((Converter) converter).to(val); - type = converter.fromType(); - } + // [#650] [#3108] Check first, if we have a converter for the supplied type + Class type = converter.fromType(); + val = ((Converter) converter).to(val); if (isInline(context)) { // [#2223] Some type-casts in this section may seem unnecessary, e.g. @@ -511,7 +496,7 @@ class Val extends AbstractParam { for (Object o : ((Object[]) val)) { context.sql(separator); - toSQL(context, o, type.getComponentType()); + toSQL(context, o, new IdentityConverter(type.getComponentType())); separator = ", "; } @@ -525,7 +510,7 @@ class Val extends AbstractParam { for (Object o : ((Object[]) val)) { context.sql(separator); - toSQL(context, o, type.getComponentType()); + toSQL(context, o, new IdentityConverter(type.getComponentType())); separator = ", "; } @@ -538,7 +523,14 @@ class Val extends AbstractParam { x xx [/pro] */ else if (EnumType.class.isAssignableFrom(type)) { - toSQL(context, ((EnumType) val).getLiteral()); + String literal = ((EnumType) val).getLiteral(); + + if (literal == null) { + toSQL(context, val, new IdentityConverter(String.class)); + } + else { + toSQL(context, val, new IdentityConverter(String.class)); + } } else if (UDTRecord.class.isAssignableFrom(type)) { context.sql("[UDT]"); @@ -609,7 +601,7 @@ class Val extends AbstractParam { // [#1302] Bind value only if it was not explicitly forced to be inlined if (!isInline()) { - context.bindValue(value, getType()); + context.bindValue(value, this); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/Values.java b/jOOQ/src/main/java/org/jooq/impl/Values.java index 2d2ea63346..6cee467b6f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Values.java +++ b/jOOQ/src/main/java/org/jooq/impl/Values.java @@ -48,7 +48,6 @@ import org.jooq.Record; import org.jooq.RenderContext; import org.jooq.Row; import org.jooq.Select; -import org.jooq.Support; import org.jooq.Table; /** diff --git a/jOOQ/src/test/java/org/jooq/test/BasicTest.java b/jOOQ/src/test/java/org/jooq/test/BasicTest.java index 2f934f5d90..33fa56146c 100644 --- a/jOOQ/src/test/java/org/jooq/test/BasicTest.java +++ b/jOOQ/src/test/java/org/jooq/test/BasicTest.java @@ -973,7 +973,7 @@ public class BasicTest extends AbstractTest { public void bind(BindContext ctx) { try { ctx.statement().setInt(ctx.nextIndex(), 1); - ctx.bindValues(1); + ctx.bindValue(1, DSL.val(1)); } catch (SQLException ignore) {} } @@ -1064,7 +1064,7 @@ public class BasicTest extends AbstractTest { @Override public void bind(BindContext ctx) { - ctx.bindValues(1); + ctx.bindValue(1, DSL.val(1)); } };