[#3188] [#3889] Add DataType.getBinding()

This commit is contained in:
Lukas Eder 2015-02-25 16:22:30 +01:00
parent b6f1fd0573
commit 67caf5b24c
7 changed files with 117 additions and 53 deletions

View File

@ -74,6 +74,16 @@ public interface DataType<T> extends Serializable {
*/
int getSQLType();
/**
* Get the data type binding associated with this data type.
*/
Binding<?, T> getBinding();
/**
* Get the converter associated with this data type.
*/
Converter<?, T> getConverter();
/**
* Retrieve the Java type associated with this data type.
*/

View File

@ -113,25 +113,18 @@ abstract class AbstractField<T> extends AbstractQueryPart implements Field<T> {
private final String name;
private final String comment;
private final DataType<T> dataType;
private final Binding<?, T> binding;
AbstractField(String name, DataType<T> type) {
this(name, type, null, null);
this(name, type, null, type.getBinding());
}
@SuppressWarnings("unchecked")
AbstractField(String name, DataType<T> type, String comment, Binding<?, T> binding) {
super();
this.name = name;
this.comment = defaultString(comment);
this.dataType = type;
this.binding =
binding != null
? binding
: type instanceof ConvertedDataType
? ((ConvertedDataType<?, T>) type).binding()
: new DefaultBinding<T, T>(new IdentityConverter<T>(type.getType()), type.isLob());
this.dataType = type.asConvertedDataType((Binding<T, T>) binding);
}
// ------------------------------------------------------------------------
@ -172,12 +165,12 @@ abstract class AbstractField<T> extends AbstractQueryPart implements Field<T> {
@Override
public final Converter<?, T> getConverter() {
return binding.converter();
return getBinding().converter();
}
@Override
public final Binding<?, T> getBinding() {
return binding;
return dataType.getBinding();
}
@Override

View File

@ -49,7 +49,10 @@ import org.jooq.DataType;
* A <code>DataType</code> used for converted types using {@link Converter}
*
* @author Lukas Eder
* @deprecated - 3.6.0 - [#3889] - Remove this type, it should not be needed any
* longer
*/
@Deprecated
class ConvertedDataType<T, U> extends DefaultDataType<U> {
/**
@ -58,12 +61,12 @@ class ConvertedDataType<T, U> extends DefaultDataType<U> {
private static final long serialVersionUID = -2321926692580974126L;
private final DataType<T> delegate;
private final Binding<? super T, U> binding;
ConvertedDataType(DataType<T> delegate, Binding<? super T, U> binding) {
super(
null,
binding.converter().toType(),
binding,
delegate.getTypeName(),
delegate.getCastTypeName(),
delegate.precision(),
@ -74,7 +77,6 @@ class ConvertedDataType<T, U> extends DefaultDataType<U> {
);
this.delegate = delegate;
this.binding = binding;
}
@Override
@ -95,21 +97,13 @@ class ConvertedDataType<T, U> extends DefaultDataType<U> {
@SuppressWarnings("unchecked")
@Override
public U convert(Object object) {
if (binding.converter().toType().isInstance(object)) {
if (getConverter().toType().isInstance(object)) {
return (U) object;
}
// [#3200] Try to convert arbitrary objects to T
else {
return binding.converter().from(delegate.convert(object));
return ((Converter<T, U>) getConverter()).from(delegate.convert(object));
}
}
Binding<? super T, U> binding() {
return binding;
}
Converter<? super T, U> converter() {
return binding.converter();
}
}

View File

@ -109,6 +109,7 @@ import org.jooq.Converters;
import org.jooq.DataType;
import org.jooq.EnumType;
import org.jooq.Field;
import org.jooq.Record;
import org.jooq.RenderContext;
import org.jooq.Result;
import org.jooq.Row;
@ -168,7 +169,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
if (converter == null && binding == null) {
theBinding = (Binding) new DefaultBinding<T, T>(new IdentityConverter<T>(type.getType()), type.isLob());
theBinding = (Binding) type.getBinding();
}
else if (converter == null) {
theBinding = (Binding) binding;
@ -1218,19 +1219,15 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
xxxx xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x
xx xxxxxxx xx xxx xxxxxx xxxxxx xxxx xxxxxxxxxxxxxxxxxx xxx xxxx
xx xxx xx xxxxxxxxxxxxxxxxxxx xxxxx xx xxxxxxxxxxx xxxxxx xx xxxxxx
xx xxx xx xxxxxxxxxxxxxxxxxxx xxxxx xx xxxxxxxxxxx xxxxxx xx xxxxxxxxx
xxxxxxxxxxxxxx xxxxxxxxxxx x xxxxxxxxxxxxxxxx xxxxxx
xxxxxxxx xxxxx x xxxxxxxxxxxxxxxxxx
xxxxxxxx xxxxxxxxx x xxx xxxxxxxxxxxxxxxxxxxxx
xx xxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxxxxxx x
xxxxxxxx xxxxxxxxx x xxx xxxxxxxxxxxxxxxxxxxxx
xxx xxxx x x xx x x xxxxxxxxxxxxxxxxx xxxx
xxxxxxxxxxxx x xxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxx xxxx x x xx x x xxxxxxxxxxxxxxxxx xxxx
xxxxxxxxxxxx x xxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxx x xxxxxxxxxx
x
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxx
x
xx [/pro] */
else if (EnumType.class.isAssignableFrom(type)) {
@ -2006,7 +2003,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
* @return The converted {@link UDTRecord}
*/
@SuppressWarnings("unchecked")
private static final UDTRecord<?> pgNewUDTRecord(Class<?> type, final Object object) throws SQLException {
static final UDTRecord<?> pgNewUDTRecord(Class<?> type, final Object object) throws SQLException {
if (object == null) {
return null;
}
@ -2126,7 +2123,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
}
}
private static final <T> void pgSetValue(UDTRecord<?> record, Field<T> field, String value) throws SQLException {
static final <T> void pgSetValue(Record record, Field<T> field, String value) throws SQLException {
record.setValue(field, pgFromString(field.getType(), value));
}

View File

@ -177,6 +177,11 @@ public class DefaultDataType<T> implements DataType<T> {
*/
private final Class<T> type;
/**
* The data type binding corresponding to this data type.
*/
private final Binding<?, T> binding;
/**
* The Java class corresponding to arrays of this data type.
*/
@ -242,7 +247,15 @@ public class DefaultDataType<T> implements DataType<T> {
this(dialect, null, type, typeName, castTypeName, precision, scale, length, nullable, defaulted);
}
DefaultDataType(SQLDialect dialect, Class<T> type, Binding<?, T> binding, String typeName, String castTypeName, int precision, int scale, int length, boolean nullable, boolean defaulted) {
this(dialect, null, type, binding, typeName, castTypeName, precision, scale, length, nullable, defaulted);
}
DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, Class<T> type, String typeName, String castTypeName, int precision, int scale, int length, boolean nullable, boolean defaulted) {
this(dialect, sqlDataType, type, null, typeName, castTypeName, precision, scale, length, nullable, defaulted);
}
DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, Class<T> type, Binding<?, T> binding, String typeName, String castTypeName, int precision, int scale, int length, boolean nullable, boolean defaulted) {
// Initialise final instance members
// ---------------------------------
@ -307,6 +320,10 @@ public class DefaultDataType<T> implements DataType<T> {
SQL_DATATYPES_BY_TYPE.put(type, this);
}
}
this.binding = binding != null
? binding
: new DefaultBinding<T, T>(new IdentityConverter<T>(type), this.isLob());
}
@Override
@ -529,6 +546,16 @@ public class DefaultDataType<T> implements DataType<T> {
return type;
}
@Override
public final Binding<?, T> getBinding() {
return binding;
}
@Override
public final Converter<?, T> getConverter() {
return binding.converter();
}
@Override
public final Class<T[]> getArrayType() {
return arrayType;
@ -590,9 +617,16 @@ public class DefaultDataType<T> implements DataType<T> {
return asConvertedDataType(DefaultBinding.newBinding(converter, this, null));
}
@SuppressWarnings("deprecation")
@Override
public final <U> DataType<U> asConvertedDataType(Binding<? super T, U> binding) {
return new ConvertedDataType<T, U>(this, binding);
public final <U> DataType<U> asConvertedDataType(Binding<? super T, U> newBinding) {
if (binding == newBinding)
return (DataType<U>) this;
if (newBinding == null)
newBinding = (Binding<? super T, U>) new DefaultBinding<T, T>(new IdentityConverter<T>(getType()), isLob());
return new ConvertedDataType<T, U>(this, newBinding);
}
@Override
@ -748,7 +782,11 @@ public class DefaultDataType<T> implements DataType<T> {
@Override
public final boolean isLob() {
DataType<T> t = getSQLDataType();
return (t == BLOB || t == CLOB || t == NCLOB);
if (t == this)
return getTypeName().endsWith("lob");
else
return (t == BLOB || t == CLOB || t == NCLOB);
}
@Override

View File

@ -61,21 +61,13 @@ class ParameterImpl<T> extends AbstractQueryPart implements Parameter<T> {
private final String name;
private final DataType<T> type;
private final Binding<?, T> binding;
private final boolean isDefaulted;
@SuppressWarnings({ "unchecked" })
@SuppressWarnings("unchecked")
ParameterImpl(String name, DataType<T> type, boolean isDefaulted, Binding<?, T> binding) {
this.name = name;
this.isDefaulted = isDefaulted;
this.type = type;
this.binding =
binding != null
? binding
: type instanceof ConvertedDataType
? ((ConvertedDataType<?, T>) type).binding()
: new DefaultBinding<T, T>(new IdentityConverter<T>(type.getType()), type.isLob());
this.type = type.asConvertedDataType((Binding<T, T>) binding);
}
@Override
@ -85,12 +77,12 @@ class ParameterImpl<T> extends AbstractQueryPart implements Parameter<T> {
@Override
public final Converter<?, T> getConverter() {
return binding.converter();
return type.getBinding().converter();
}
@Override
public final Binding<?, T> getBinding() {
return binding;
return type.getBinding();
}
@Override

View File

@ -42,11 +42,16 @@ package org.jooq.impl;
import static org.jooq.impl.Utils.DATA_LIST_ALREADY_INDENTED;
import java.sql.SQLException;
import java.util.List;
import org.jooq.Context;
import org.jooq.Converter;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.Record;
import org.jooq.Row;
import org.jooq.util.postgres.PostgresUtils;
/**
* @author Lukas Eder
@ -66,8 +71,43 @@ class RowField<ROW extends Row, REC extends Record> extends AbstractField<REC> {
this(row, "row");
}
RowField(ROW row, String as) {
super(as, (DataType) SQLDataType.RECORD);
RowField(final ROW row, String as) {
super(as, (DataType) SQLDataType.RECORD, "", new DefaultBinding<Object, REC>(new Converter<Object, REC>() {
@Override
public REC from(final Object t) {
return t == null ? null : Utils.newRecord(true, (Class<REC>) RecordImpl.class, row.fields()).operate(new RecordOperation<REC, RuntimeException>() {
@Override
public REC operate(REC record) {
List<String> values = PostgresUtils.toPGObject(t.toString());
for (int i = 0; i < row.size(); i++) {
try {
DefaultBinding.pgSetValue(record, row.field(i), values.get(i));
}
catch (SQLException ignore) {}
}
return record;
}
});
}
@Override
public Object to(REC u) {
return null;
}
@Override
public Class<Object> fromType() {
return Object.class;
}
@Override
public Class<REC> toType() {
return (Class<REC>) RecordImpl.class;
}}));
this.row = row;
this.as = as;