[#3108] Local Fields' Converters should be preferred over globally registered Converters
This commit is contained in:
parent
7e59c58a1a
commit
50da819acb
@ -94,6 +94,7 @@ import org.jooq.tools.StringUtils;
|
|||||||
import org.jooq.tools.reflect.Reflect;
|
import org.jooq.tools.reflect.Reflect;
|
||||||
import org.jooq.tools.reflect.ReflectException;
|
import org.jooq.tools.reflect.ReflectException;
|
||||||
import org.jooq.util.GeneratorStrategy.Mode;
|
import org.jooq.util.GeneratorStrategy.Mode;
|
||||||
|
import org.jooq.util.jaxb.CustomType;
|
||||||
import org.jooq.util.postgres.PostgresDatabase;
|
import org.jooq.util.postgres.PostgresDatabase;
|
||||||
|
|
||||||
|
|
||||||
@ -1748,14 +1749,24 @@ public class JavaGenerator extends AbstractGenerator {
|
|||||||
final String columnId = getStrategy().getJavaIdentifier(column);
|
final String columnId = getStrategy().getJavaIdentifier(column);
|
||||||
final String columnName = column.getName();
|
final String columnName = column.getName();
|
||||||
final String columnComment = StringUtils.defaultString(column.getComment());
|
final String columnComment = StringUtils.defaultString(column.getComment());
|
||||||
|
final CustomType columnCustomType = database.getConfiguredCustomType(column.getType().getUserType());
|
||||||
|
|
||||||
String isStatic = generateInstanceFields() ? "" : "static ";
|
String isStatic = generateInstanceFields() ? "" : "static ";
|
||||||
String tableRef = generateInstanceFields() ? "this" : getStrategy().getJavaIdentifier(table);
|
String tableRef = generateInstanceFields() ? "this" : getStrategy().getJavaIdentifier(table);
|
||||||
|
|
||||||
out.tab(1).javadoc("The column <code>%s</code>.%s", column.getQualifiedOutputName(), defaultIfBlank(" " + columnComment, ""));
|
out.tab(1).javadoc("The column <code>%s</code>.%s", column.getQualifiedOutputName(), defaultIfBlank(" " + 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\");",
|
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));
|
isStatic, TableField.class, recordType, columnType, columnId, columnName, columnTypeRef, tableRef, escapeString(columnComment));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// [#1255] With instance fields, the table constructor may
|
// [#1255] With instance fields, the table constructor may
|
||||||
// be public, as tables are no longer singletons
|
// be public, as tables are no longer singletons
|
||||||
@ -2884,12 +2895,6 @@ public class JavaGenerator extends AbstractGenerator {
|
|||||||
if (dataType.defaulted()) {
|
if (dataType.defaulted()) {
|
||||||
sb.append(".defaulted(true)");
|
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.
|
// Otherwise, reference the dialect-specific DataType itself.
|
||||||
|
|||||||
@ -51,6 +51,7 @@ import static junit.framework.Assert.fail;
|
|||||||
// ...
|
// ...
|
||||||
import static org.jooq.SQLDialect.SQLITE;
|
import static org.jooq.SQLDialect.SQLITE;
|
||||||
import static org.jooq.impl.DSL.count;
|
import static org.jooq.impl.DSL.count;
|
||||||
|
import static org.jooq.impl.DSL.table;
|
||||||
|
|
||||||
import java.sql.Date;
|
import java.sql.Date;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
@ -65,6 +66,7 @@ import org.jooq.Record1;
|
|||||||
import org.jooq.Record2;
|
import org.jooq.Record2;
|
||||||
import org.jooq.Record3;
|
import org.jooq.Record3;
|
||||||
import org.jooq.Record6;
|
import org.jooq.Record6;
|
||||||
|
import org.jooq.SQLDialect;
|
||||||
import org.jooq.StoreQuery;
|
import org.jooq.StoreQuery;
|
||||||
import org.jooq.Table;
|
import org.jooq.Table;
|
||||||
import org.jooq.TableField;
|
import org.jooq.TableField;
|
||||||
|
|||||||
@ -49,6 +49,7 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import java.sql.Date;
|
import java.sql.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jooq.DSLContext;
|
||||||
import org.jooq.EnumType;
|
import org.jooq.EnumType;
|
||||||
import org.jooq.Field;
|
import org.jooq.Field;
|
||||||
import org.jooq.Record1;
|
import org.jooq.Record1;
|
||||||
@ -58,6 +59,8 @@ import org.jooq.Record6;
|
|||||||
import org.jooq.Result;
|
import org.jooq.Result;
|
||||||
import org.jooq.TableRecord;
|
import org.jooq.TableRecord;
|
||||||
import org.jooq.UpdatableRecord;
|
import org.jooq.UpdatableRecord;
|
||||||
|
import org.jooq.conf.Settings;
|
||||||
|
import org.jooq.conf.StatementType;
|
||||||
import org.jooq.test.BaseTest;
|
import org.jooq.test.BaseTest;
|
||||||
import org.jooq.test.jOOQAbstractTest;
|
import org.jooq.test.jOOQAbstractTest;
|
||||||
import org.jooq.test._.converters.Boolean_10;
|
import org.jooq.test._.converters.Boolean_10;
|
||||||
@ -128,6 +131,15 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public <R extends TableRecord<R>> void testCustomEnums() throws Exception {
|
public <R extends TableRecord<R>> void testCustomEnums() throws Exception {
|
||||||
|
testCustomEnums0(create());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public <R extends TableRecord<R>> void testCustomEnumsWithInline() throws Exception {
|
||||||
|
testCustomEnums0(create(new Settings().withStatementType(StatementType.STATIC_STATEMENT)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private <R extends TableRecord<R>> void testCustomEnums0(DSLContext create) throws Exception {
|
||||||
jOOQAbstractTest.reset = false;
|
jOOQAbstractTest.reset = false;
|
||||||
|
|
||||||
// This does not yet work correctly for Sybase ASE, Postgres
|
// This does not yet work correctly for Sybase ASE, Postgres
|
||||||
@ -141,7 +153,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
|||||||
// Insertion
|
// Insertion
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
assertEquals(1,
|
assertEquals(1,
|
||||||
create().insertInto(TBooleans())
|
create .insertInto(TBooleans())
|
||||||
.set(TBooleans_ID(), 1)
|
.set(TBooleans_ID(), 1)
|
||||||
.set(TBooleans_BOOLEAN_10(), Boolean_10.ZERO)
|
.set(TBooleans_BOOLEAN_10(), Boolean_10.ZERO)
|
||||||
.set(TBooleans_Boolean_TF_LC(), Boolean_TF_LC.FALSE)
|
.set(TBooleans_Boolean_TF_LC(), Boolean_TF_LC.FALSE)
|
||||||
@ -156,7 +168,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
|||||||
.execute());
|
.execute());
|
||||||
|
|
||||||
assertEquals(1,
|
assertEquals(1,
|
||||||
create().insertInto(TBooleans())
|
create .insertInto(TBooleans())
|
||||||
.set(TBooleans_ID(), 2)
|
.set(TBooleans_ID(), 2)
|
||||||
.set(TBooleans_BOOLEAN_10(), Boolean_10.ONE)
|
.set(TBooleans_BOOLEAN_10(), Boolean_10.ONE)
|
||||||
.set(TBooleans_Boolean_TF_LC(), Boolean_TF_LC.TRUE)
|
.set(TBooleans_Boolean_TF_LC(), Boolean_TF_LC.TRUE)
|
||||||
@ -171,7 +183,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
|||||||
.execute());
|
.execute());
|
||||||
|
|
||||||
assertEquals(1,
|
assertEquals(1,
|
||||||
create().insertInto(TBooleans())
|
create .insertInto(TBooleans())
|
||||||
.set(TBooleans_ID(), 3)
|
.set(TBooleans_ID(), 3)
|
||||||
.set(TBooleans_BOOLEAN_10(), (Boolean_10) null)
|
.set(TBooleans_BOOLEAN_10(), (Boolean_10) null)
|
||||||
.set(TBooleans_Boolean_TF_LC(), (Boolean_TF_LC) null)
|
.set(TBooleans_Boolean_TF_LC(), (Boolean_TF_LC) null)
|
||||||
@ -188,7 +200,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
|||||||
// Selection
|
// Selection
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
Result<?> result =
|
Result<?> result =
|
||||||
create().selectFrom(TBooleans())
|
create .selectFrom(TBooleans())
|
||||||
.where(TBooleans_ID().in(1, 2, 3))
|
.where(TBooleans_ID().in(1, 2, 3))
|
||||||
.and(TBooleans_BOOLEAN_10().in(Boolean_10.ONE, Boolean_10.ZERO)
|
.and(TBooleans_BOOLEAN_10().in(Boolean_10.ONE, Boolean_10.ZERO)
|
||||||
.or(TBooleans_BOOLEAN_10().isNull()))
|
.or(TBooleans_BOOLEAN_10().isNull()))
|
||||||
@ -258,7 +270,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
List<Object> b =
|
List<Object> b =
|
||||||
create().selectFrom(TBooleans())
|
create .selectFrom(TBooleans())
|
||||||
.orderBy(TBooleans_ID().asc())
|
.orderBy(TBooleans_ID().asc())
|
||||||
.fetchInto(TBooleansPojo());
|
.fetchInto(TBooleansPojo());
|
||||||
|
|
||||||
|
|||||||
@ -2296,6 +2296,11 @@ public abstract class jOOQAbstractTest<
|
|||||||
new EnumTests(this).testCustomEnums();
|
new EnumTests(this).testCustomEnums();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public <R extends TableRecord<R>> void testCustomEnumsWithInline() throws Exception {
|
||||||
|
new EnumTests(this).testCustomEnumsWithInline();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSerialisation() throws Exception {
|
public void testSerialisation() throws Exception {
|
||||||
new GeneralTests(this).testSerialisation();
|
new GeneralTests(this).testSerialisation();
|
||||||
|
|||||||
@ -56,43 +56,48 @@ xxx
|
|||||||
xxxxxx xxxxxxxxx xxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxx xxxxxxxxxxx x
|
xxxxxx xxxxxxxxx xxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxx xxxxxxxxxxx x
|
||||||
|
|
||||||
xxx
|
xxx
|
||||||
x xxx xxx xxxxxxxxx xxxxx
|
x xxx xxx xxxxxxxxx xxxxxx
|
||||||
xx
|
xx
|
||||||
xxx xxxxxx
|
xxx xxxxxx
|
||||||
|
|
||||||
xxx
|
xxx
|
||||||
x xxx xxx xxxxxxxxx xxxxx xx x xxxxxx xxxxx
|
x xxx xxx xxxxxxxxx xxxxx xx x xxxxxx xxxxxx
|
||||||
xx
|
xx
|
||||||
xxxxxxx xxxxxxxxxx
|
xxxxxxx xxxxxxxxxx
|
||||||
|
|
||||||
xxx
|
xxx
|
||||||
x xxx xxx xxxxxxxxx xxxxx
|
x xxx xxx xxxxxxxxx xxxxxx
|
||||||
xx
|
xx
|
||||||
xxxx xxxxxxxxx xxxxxx xxxxxx xxxxxxxxxxxxx
|
xxxx xxxxxxxxx xxxxxx xxxxxx xxxxxxxxxxxxx
|
||||||
|
|
||||||
xxx
|
xxx
|
||||||
x xxx xxx xxxxxxxxx xxxxx
|
x xxx xxx xxxxxxxxx xxxxxx
|
||||||
xx
|
xx
|
||||||
xxxx xxxxxxxx xxxxxxx
|
xxxx xxxxxxxx xxxxxxx
|
||||||
|
|
||||||
xxx
|
xxx
|
||||||
x xxx xxx xxxxxxxxx xxxxx xx x xxxxxx xxxxx
|
x xxx xxx xxxxxxxxx xxxxx xx x xxxxxx xxxxxx
|
||||||
xx
|
xx
|
||||||
xxxx xxxxxxxxxxxxxx xxxxxxx xx xxxxxx
|
xxxx xxxxxxxxxxxxxx xxxxxxx xx xxxxxx
|
||||||
|
|
||||||
xxx
|
xxx
|
||||||
x xxx xxx xxxx xx xxx xxxxxxxxx xxxxx
|
x xxx xxx xxxx xx xxx xxxxxxxxx xxxxxx
|
||||||
xx
|
xx
|
||||||
xxx xxxxxxx
|
xxx xxxxxxx
|
||||||
|
|
||||||
xxx
|
xxx
|
||||||
x xxx xxx xxxx xx xxx xxxxx xxxx
|
x xxx xxx xxxx xx xxx xxxxx xxxxx
|
||||||
xx
|
xx
|
||||||
xxxxxx xxxxxxxxxx
|
xxxxxx xxxxxxxxxx
|
||||||
|
|
||||||
xxx
|
xxx
|
||||||
x xxx xxx xxxx xxxx xx xxx xxxxx xxxx
|
x xxx xxx xxxx xxxx xx xxx xxxxxxx xxxx xxxxx
|
||||||
xx
|
xx
|
||||||
xxxxxxxxxxx xxxxxxxxxxxxxx
|
xxxxxxxxxxx xxxxxxxxxxxxxx
|
||||||
|
|
||||||
|
xxx
|
||||||
|
x xxx xxx xxxx xxxx xx xxx xxxxxx
|
||||||
|
xx
|
||||||
|
xxxxxxxxxxx xxxxxxxxxxxxxxx
|
||||||
x
|
x
|
||||||
xx [/pro] */
|
xx [/pro] */
|
||||||
@ -102,7 +102,9 @@ public interface BindContext extends Context<BindContext> {
|
|||||||
*
|
*
|
||||||
* @throws DataAccessException If something went wrong while binding a
|
* @throws DataAccessException If something went wrong while binding a
|
||||||
* variable
|
* variable
|
||||||
|
* @deprecated - 3.4.0 - [#3114] - Use {@link #bindValue(Object, Field)} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
BindContext bindValue(Object value, Class<?> type) throws DataAccessException;
|
BindContext bindValue(Object value, Class<?> type) throws DataAccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,6 +112,18 @@ public interface BindContext extends Context<BindContext> {
|
|||||||
*
|
*
|
||||||
* @throws DataAccessException If something went wrong while binding a
|
* @throws DataAccessException If something went wrong while binding a
|
||||||
* variable
|
* variable
|
||||||
|
* @deprecated - 3.4.0 - [#3114] - Use {@link #bindValue(Object, Field)} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
BindContext bindValues(Object... values) throws DataAccessException;
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -126,6 +126,15 @@ public interface Field<T> extends GroupField {
|
|||||||
*/
|
*/
|
||||||
String getComment();
|
String getComment();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The field's underlying {@link Converter}.
|
||||||
|
* <p>
|
||||||
|
* By default, all fields reference an identity-converter
|
||||||
|
* <code>Converter<T, T></code>. Custom data types may be obtained by a
|
||||||
|
* custom {@link Converter} placed on the generated {@link TableField}.
|
||||||
|
*/
|
||||||
|
Converter<?, T> getConverter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Java type of the field.
|
* The Java type of the field.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -47,8 +47,10 @@ import java.util.Collection;
|
|||||||
|
|
||||||
import org.jooq.BindContext;
|
import org.jooq.BindContext;
|
||||||
import org.jooq.Configuration;
|
import org.jooq.Configuration;
|
||||||
|
import org.jooq.Field;
|
||||||
import org.jooq.QueryPart;
|
import org.jooq.QueryPart;
|
||||||
import org.jooq.QueryPartInternal;
|
import org.jooq.QueryPartInternal;
|
||||||
|
import org.jooq.exception.DataAccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base class for {@link BindContext} implementations
|
* A base class for {@link BindContext} implementations
|
||||||
@ -89,6 +91,7 @@ abstract class AbstractBindContext extends AbstractContext<BindContext> implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public final BindContext bindValues(Object... values) {
|
public final BindContext bindValues(Object... values) {
|
||||||
|
|
||||||
// [#724] When values is null, this is probably due to API-misuse
|
// [#724] When values is null, this is probably due to API-misuse
|
||||||
@ -99,7 +102,7 @@ abstract class AbstractBindContext extends AbstractContext<BindContext> implemen
|
|||||||
else {
|
else {
|
||||||
for (Object value : values) {
|
for (Object value : values) {
|
||||||
Class<?> type = (value == null) ? Object.class : value.getClass();
|
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<BindContext> implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public final BindContext bindValue(Object value, Class<?> type) {
|
public final BindContext bindValue(Object value, Class<?> type) {
|
||||||
try {
|
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) {
|
catch (SQLException e) {
|
||||||
throw Utils.translate(null, e);
|
throw Utils.translate(null, e);
|
||||||
@ -131,7 +145,7 @@ abstract class AbstractBindContext extends AbstractContext<BindContext> implemen
|
|||||||
* Subclasses may override this method to achieve different behaviour
|
* Subclasses may override this method to achieve different behaviour
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
protected BindContext bindValue0(Object value, Class<?> type) throws SQLException {
|
protected BindContext bindValue0(Object value, Field<?> field) throws SQLException {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -87,6 +87,7 @@ import org.jooq.Comparator;
|
|||||||
import org.jooq.Condition;
|
import org.jooq.Condition;
|
||||||
import org.jooq.Configuration;
|
import org.jooq.Configuration;
|
||||||
import org.jooq.Context;
|
import org.jooq.Context;
|
||||||
|
import org.jooq.Converter;
|
||||||
import org.jooq.DataType;
|
import org.jooq.DataType;
|
||||||
import org.jooq.DatePart;
|
import org.jooq.DatePart;
|
||||||
import org.jooq.Field;
|
import org.jooq.Field;
|
||||||
@ -114,17 +115,25 @@ abstract class AbstractField<T> extends AbstractQueryPart implements Field<T> {
|
|||||||
private final String name;
|
private final String name;
|
||||||
private final String comment;
|
private final String comment;
|
||||||
private final DataType<T> dataType;
|
private final DataType<T> dataType;
|
||||||
|
private final Converter<?, T> converter;
|
||||||
|
|
||||||
AbstractField(String name, DataType<T> type) {
|
AbstractField(String name, DataType<T> type) {
|
||||||
this(name, type, null);
|
this(name, type, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractField(String name, DataType<T> type, String comment) {
|
@SuppressWarnings("unchecked")
|
||||||
|
AbstractField(String name, DataType<T> type, String comment, Converter<?, T> converter) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.comment = defaultString(comment);
|
this.comment = defaultString(comment);
|
||||||
this.dataType = type;
|
this.dataType = type;
|
||||||
|
this.converter =
|
||||||
|
converter != null
|
||||||
|
? converter
|
||||||
|
: type instanceof ConvertedDataType
|
||||||
|
? ((ConvertedDataType<?, T>) type).converter()
|
||||||
|
: new IdentityConverter<T>(type.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -161,6 +170,11 @@ abstract class AbstractField<T> extends AbstractQueryPart implements Field<T> {
|
|||||||
return comment;
|
return comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Converter<?, T> getConverter() {
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final DataType<T> getDataType() {
|
public final DataType<T> getDataType() {
|
||||||
return dataType;
|
return dataType;
|
||||||
|
|||||||
@ -62,6 +62,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.jooq.Clause;
|
import org.jooq.Clause;
|
||||||
import org.jooq.Context;
|
import org.jooq.Context;
|
||||||
|
import org.jooq.Converter;
|
||||||
import org.jooq.DataType;
|
import org.jooq.DataType;
|
||||||
import org.jooq.DivideByOnStep;
|
import org.jooq.DivideByOnStep;
|
||||||
import org.jooq.Field;
|
import org.jooq.Field;
|
||||||
@ -325,7 +326,23 @@ abstract class AbstractTable<R extends Record> extends AbstractQueryPart impleme
|
|||||||
* @param type The data type of the field
|
* @param type The data type of the field
|
||||||
*/
|
*/
|
||||||
protected static final <R extends Record, T> TableField<R, T> createField(String name, DataType<T> type, Table<R> table, String comment) {
|
protected static final <R extends Record, T> TableField<R, T> createField(String name, DataType<T> type, Table<R> table, String comment) {
|
||||||
final TableFieldImpl<R, T> tableField = new TableFieldImpl<R, T>(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 <R extends Record, T, U> TableField<R, U> createField(String name, DataType<T> type, Table<R> table, String comment, Converter<T, U> converter) {
|
||||||
|
final DataType<U> actualType = converter == null
|
||||||
|
? (DataType<U>) type
|
||||||
|
: type.asConvertedDataType(converter);
|
||||||
|
|
||||||
|
final TableFieldImpl<R, U> tableField = new TableFieldImpl<R, U>(name, actualType, table, comment, converter);
|
||||||
|
|
||||||
// [#1199] The public API of Table returns immutable field lists
|
// [#1199] The public API of Table returns immutable field lists
|
||||||
if (table instanceof TableImpl) {
|
if (table instanceof TableImpl) {
|
||||||
|
|||||||
@ -57,12 +57,18 @@ xxxxx xxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxxxxx x
|
|||||||
|
|
||||||
xxxxxxx xxxxxx xxxxx xxxx xxxxxxxxxxxxxxxx x xxxxxxxxxxxxxxxxxxxxxx
|
xxxxxxx xxxxxx xxxxx xxxx xxxxxxxxxxxxxxxx x xxxxxxxxxxxxxxxxxxxxxx
|
||||||
xxxxxxx xxxxx x xxxxxx
|
xxxxxxx xxxxx x xxxxxx
|
||||||
|
xxxxxxx xxxxx xxxxxxxxxxx xxxxxxxxx
|
||||||
|
|
||||||
xxxxxxxxxxxxxxxxxxx xxxxxxxxxxx xxxxxxxxxxx xx
|
xxxxxxxxxxxxxxxxxxx xxxxxxxxxxx xxxxxxxxxxx xx
|
||||||
xxxxxxxxxxxxxxx xxxxxx x
|
xxxxxxxxxxxxxxx xxxxxx x
|
||||||
xxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxxxxxxxxx
|
xxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
|
||||||
xxxxxxxxxx x xxxxxx
|
xxxxxxxxxx x xxxxxx
|
||||||
|
xxxxxxxxxxxxx x xxxxxxxxxxxxxxxxxxxx
|
||||||
|
x
|
||||||
|
|
||||||
|
xxxxx xxxxxxxxxxx xxxxxxxxxxxxx x
|
||||||
|
xxxxxx xxxxxxxxx
|
||||||
x
|
x
|
||||||
|
|
||||||
xxxxxxxxx
|
xxxxxxxxx
|
||||||
@ -88,7 +94,7 @@ xxxxx xxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxxxxx x
|
|||||||
|
|
||||||
xxxxxxxxx
|
xxxxxxxxx
|
||||||
xxxxxx xxxxx xxxx xxxxxxxxxxxxxxxx xxxxxxxx x
|
xxxxxx xxxxx xxxx xxxxxxxxxxxxxxxx xxxxxxxx x
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxx
|
xxxxxxxxxxxxxxxxxxxxxxxx xxxxxx
|
||||||
x
|
x
|
||||||
x
|
x
|
||||||
xx [/pro] */
|
xx [/pro] */
|
||||||
@ -72,6 +72,7 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx
|
|||||||
xxxxxxx xxxxxx xxxxx xxxx xxxxxxxxxxxxxxxx x xxxxxxxxxxxxxxxxxxxxx
|
xxxxxxx xxxxxx xxxxx xxxx xxxxxxxxxxxxxxxx x xxxxxxxxxxxxxxxxxxxxx
|
||||||
|
|
||||||
xxxxxxx xxxxx xxxxxx xxxxxxx
|
xxxxxxx xxxxx xxxxxx xxxxxxx
|
||||||
|
xxxxxxx xxxxx xxxxxxxxxxx xxxxxxxxx
|
||||||
xxxxxxx xxxxx xxxxxxxxxxx xxxxx
|
xxxxxxx xxxxx xxxxxxxxxxx xxxxx
|
||||||
xxxxxxx xxxxx xxxxxx xxxxx
|
xxxxxxx xxxxx xxxxxx xxxxx
|
||||||
xxxxxxx xxx xxxxxx
|
xxxxxxx xxx xxxxxx
|
||||||
@ -85,10 +86,10 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx
|
|||||||
|
|
||||||
xxxxxxxxxxx x xxxxxxx
|
xxxxxxxxxxx x xxxxxxx
|
||||||
xxxxxxxxx x xxxxx
|
xxxxxxxxx x xxxxx
|
||||||
xxxxxxxxx x xxxxx
|
xxxxxxxxxxxxx x xxxxx
|
||||||
|
|
||||||
xx xxxxx xxxx xxxx xxxxxxxxxxxxxx
|
xx xxxxx xxxx xxxx xxxxxxxxxxxxxx
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
xxxxxxxxx x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
x
|
x
|
||||||
|
|
||||||
xxx
|
xxx
|
||||||
@ -106,7 +107,7 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx
|
|||||||
xxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx x
|
xxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx x
|
||||||
xxxxxxxxxxxxxxxx xxxxxx x xxx xxxxxxxxxxxxxxxxxxxxxxxx
|
xxxxxxxxxxxxxxxx xxxxxx x xxx xxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
|
||||||
xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x
|
xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x
|
||||||
xxx xx xxxxxxx x xxxxxx x
|
xxx xx xxxxxxx x xxxxxx x
|
||||||
xxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxx
|
xxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxx
|
||||||
x
|
x
|
||||||
@ -128,7 +129,7 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx
|
|||||||
xxxxxxxxx
|
xxxxxxxxx
|
||||||
xxxxxx xxxxx xxx xxxxx x
|
xxxxxx xxxxx xxx xxxxx x
|
||||||
xx xxxxxx xx xxxxx x
|
xx xxxxxx xx xxxxx x
|
||||||
xxxxxx xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxx
|
xxxxxx xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxx
|
||||||
x
|
x
|
||||||
xxxx x
|
xxxx x
|
||||||
xxxxxx xxxxxx
|
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 xxxxxx xxxxx xxxx xxxx xx xxxx xx xxxxxxx xxxx xx xxxxxx xx
|
||||||
xx xxxxxxxxx xxxxxxx xxx xxxxxx xxxxxxx
|
xx xxxxxxxxx xxxxxxx xxx xxxxxx xxxxxxx
|
||||||
x x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
x x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
xxxxxxxxxx x xxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxx
|
xxxxxxxxxx x xxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
x
|
x
|
||||||
x
|
x
|
||||||
|
|
||||||
@ -173,7 +174,7 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx
|
|||||||
xxxxx x xxxxx
|
xxxxx x xxxxx
|
||||||
x
|
x
|
||||||
xxxx x
|
xxxx x
|
||||||
xxxxx x xxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxx
|
xxxxx x xxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxx
|
||||||
x
|
x
|
||||||
x
|
x
|
||||||
|
|
||||||
@ -198,6 +199,11 @@ xxxxxx xxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx
|
|||||||
|
|
||||||
xxxxxxxxx
|
xxxxxxxxx
|
||||||
xxxxxx xxxxx xxxxxxxxxxx xxxxxxxxxxxxx x
|
xxxxxx xxxxx xxxxxxxxxxx xxxxxxxxxxxxx x
|
||||||
|
xxxxxx xxxxxxxxx
|
||||||
|
x
|
||||||
|
|
||||||
|
xxxxxxxxx
|
||||||
|
xxxxxx xxxxx xxxxxxxxxxx xxxxxxxxxxxxxx x
|
||||||
xxxxxx xxxxx
|
xxxxxx xxxxx
|
||||||
x
|
x
|
||||||
|
|
||||||
|
|||||||
@ -93,7 +93,7 @@ class ArrayTable extends AbstractTable<Record> {
|
|||||||
/* [pro] xx
|
/* [pro] xx
|
||||||
xx xxxxxxx xxxx xxxxx xx xxxxxxx xxxx xxxxxxxxxxx xx xxxxxx xxxxxx x xxxxx xxxxx
|
xx xxxxxxx xxxx xxxxx xx xxxxxxx xxxx xxxxxxxxxxx xx xxxxxx xxxxxx x xxxxx xxxxx
|
||||||
xxxx xx xxxxxx xxxxxxxxxx xxxxxxxxxxxxxx x
|
xxxx xx xxxxxx xxxxxxxxxx xxxxxxxxxxxxxx x
|
||||||
xxxxxxxxx x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
xxxxxxxxx x xxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
x
|
x
|
||||||
|
|
||||||
xx xxxxxxx xxxx xxxxx xx xxxxxxx xxxx xxxxxxxxxxx xx xxxxxx
|
xx xxxxxxx xxxx xxxxx xx xxxxxxx xxxx xxxxxxxxxxx xx xxxxxx
|
||||||
|
|||||||
@ -64,8 +64,6 @@ class ConvertedDataType<T, U> extends DefaultDataType<U> {
|
|||||||
|
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
this.converter = converter;
|
this.converter = converter;
|
||||||
|
|
||||||
DataTypes.registerConverter(converter.toType(), converter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -88,4 +86,8 @@ class ConvertedDataType<T, U> extends DefaultDataType<U> {
|
|||||||
public U convert(Object object) {
|
public U convert(Object object) {
|
||||||
return converter.from(delegate.convert(converter.to((U) object)));
|
return converter.from(delegate.convert(converter.to((U) object)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Converter<? super T, U> converter() {
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,9 +48,7 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jooq.Converter;
|
|
||||||
import org.jooq.DataType;
|
import org.jooq.DataType;
|
||||||
import org.jooq.exception.DataTypeException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A central {@link DataType} registry
|
* A central {@link DataType} registry
|
||||||
@ -59,7 +57,6 @@ import org.jooq.exception.DataTypeException;
|
|||||||
*/
|
*/
|
||||||
final class DataTypes {
|
final class DataTypes {
|
||||||
|
|
||||||
private static final Map<Class<?>, Converter<?, ?>> CONVERTERS = new HashMap<Class<?>, Converter<?, ?>>();
|
|
||||||
private static final Map<String, Class<?>> UDT_RECORDS = new HashMap<String, Class<?>>();
|
private static final Map<String, Class<?>> UDT_RECORDS = new HashMap<String, Class<?>>();
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -67,52 +64,6 @@ final class DataTypes {
|
|||||||
// (this may be rendered public in the future)
|
// (this may be rendered public in the future)
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a <code>Converter</code> for a custom type
|
|
||||||
* <p>
|
|
||||||
* 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
|
|
||||||
* <p>
|
|
||||||
* A custom type can be registered only once. Duplicate registrations will
|
|
||||||
* be ignored
|
|
||||||
* <p>
|
|
||||||
* The converter class must provide a default constructor.
|
|
||||||
*
|
|
||||||
* @see #registerConverter(Class, Converter)
|
|
||||||
*/
|
|
||||||
static final synchronized <U> void registerConverter(Class<U> customType,
|
|
||||||
Class<? extends Converter<?, U>> converter) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
converter.getConstructor().setAccessible(true);
|
|
||||||
registerConverter(customType, converter.newInstance());
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new DataTypeException("Cannot register converter", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a <code>Converter</code> for a custom type
|
|
||||||
* <p>
|
|
||||||
* 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
|
|
||||||
* <p>
|
|
||||||
* A custom type can be registered only once. Duplicate registrations will
|
|
||||||
* be ignored
|
|
||||||
*/
|
|
||||||
static final synchronized <U> void registerConverter(Class<U> customType, Converter<?, U> converter) {
|
|
||||||
|
|
||||||
// A converter can be registered only once
|
|
||||||
if (!CONVERTERS.containsKey(customType)) {
|
|
||||||
CONVERTERS.put(customType, converter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a type mapping for a UDT
|
* Register a type mapping for a UDT
|
||||||
* <p>
|
* <p>
|
||||||
@ -134,13 +85,6 @@ final class DataTypes {
|
|||||||
// XXX: Internal API
|
// XXX: Internal API
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
static final <U> Converter<?, U> converter(Class<U> customType) {
|
|
||||||
|
|
||||||
// TODO: Is synchronisation needed? How to implement it most efficiently?
|
|
||||||
return (Converter<?, U>) CONVERTERS.get(customType);
|
|
||||||
}
|
|
||||||
|
|
||||||
static final Map<String, Class<?>> udtRecords() {
|
static final Map<String, Class<?>> udtRecords() {
|
||||||
return Collections.unmodifiableMap(UDT_RECORDS);
|
return Collections.unmodifiableMap(UDT_RECORDS);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,6 +72,7 @@ import org.jooq.BindContext;
|
|||||||
import org.jooq.Configuration;
|
import org.jooq.Configuration;
|
||||||
import org.jooq.Converter;
|
import org.jooq.Converter;
|
||||||
import org.jooq.EnumType;
|
import org.jooq.EnumType;
|
||||||
|
import org.jooq.Field;
|
||||||
import org.jooq.SQLDialect;
|
import org.jooq.SQLDialect;
|
||||||
import org.jooq.UDTRecord;
|
import org.jooq.UDTRecord;
|
||||||
import org.jooq.exception.SQLDialectNotSupportedException;
|
import org.jooq.exception.SQLDialectNotSupportedException;
|
||||||
@ -106,15 +107,13 @@ class DefaultBindContext extends AbstractBindContext {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@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();
|
SQLDialect dialect = configuration.dialect();
|
||||||
|
|
||||||
// [#650] Check first, if we have a converter for the supplied type
|
// [#650] [#3108] Use the Field's Converter before actually binding any value
|
||||||
Converter<?, ?> converter = DataTypes.converter(type);
|
Converter<?, ?> converter = field.getConverter();
|
||||||
if (converter != null) {
|
Class<?> type = converter.fromType();
|
||||||
value = ((Converter) converter).to(value);
|
value = ((Converter) converter).to(value);
|
||||||
type = converter.fromType();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (log.isTraceEnabled()) {
|
if (log.isTraceEnabled()) {
|
||||||
if (value != null && value.getClass().isArray() && value.getClass() != byte[].class) {
|
if (value != null && value.getClass().isArray() && value.getClass() != byte[].class) {
|
||||||
|
|||||||
@ -126,4 +126,9 @@ public class EnumConverter<T, U extends Enum<U>> implements Converter<T, U> {
|
|||||||
*/
|
*/
|
||||||
STRING
|
STRING
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "EnumConverter [ from : " + fromType.getName() + ", to : " + toType.getName() + " ]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
84
jOOQ/src/main/java/org/jooq/impl/IdentityConverter.java
Normal file
84
jOOQ/src/main/java/org/jooq/impl/IdentityConverter.java
Normal file
@ -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<T> implements Converter<T, T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generated UID
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -1721687282753727624L;
|
||||||
|
private final Class<T> type;
|
||||||
|
|
||||||
|
IdentityConverter(Class<T> 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<T> fromType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Class<T> toType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "IdentityConverter [" + type.getName() + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -47,6 +47,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.jooq.BindContext;
|
import org.jooq.BindContext;
|
||||||
import org.jooq.Configuration;
|
import org.jooq.Configuration;
|
||||||
|
import org.jooq.Field;
|
||||||
import org.jooq.Param;
|
import org.jooq.Param;
|
||||||
import org.jooq.QueryPart;
|
import org.jooq.QueryPart;
|
||||||
import org.jooq.QueryPartInternal;
|
import org.jooq.QueryPartInternal;
|
||||||
@ -90,7 +91,7 @@ class ParamCollector extends AbstractBindContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final BindContext bindValue0(Object value, Class<?> type) throws SQLException {
|
protected final BindContext bindValue0(Object value, Field<?> field) throws SQLException {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,7 +100,7 @@ class TableAlias<R extends Record> extends AbstractTable<R> {
|
|||||||
name = fieldAliases[i];
|
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<R>(result);
|
return new Fields<R>(result);
|
||||||
|
|||||||
@ -48,6 +48,7 @@ import static org.jooq.impl.Utils.DATA_OMIT_CLAUSE_EVENT_EMISSION;
|
|||||||
import org.jooq.BindContext;
|
import org.jooq.BindContext;
|
||||||
import org.jooq.Clause;
|
import org.jooq.Clause;
|
||||||
import org.jooq.Context;
|
import org.jooq.Context;
|
||||||
|
import org.jooq.Converter;
|
||||||
import org.jooq.DataType;
|
import org.jooq.DataType;
|
||||||
import org.jooq.Record;
|
import org.jooq.Record;
|
||||||
import org.jooq.RenderContext;
|
import org.jooq.RenderContext;
|
||||||
@ -67,8 +68,8 @@ class TableFieldImpl<R extends Record, T> extends AbstractField<T> implements Ta
|
|||||||
|
|
||||||
private final Table<R> table;
|
private final Table<R> table;
|
||||||
|
|
||||||
TableFieldImpl(String name, DataType<T> type, Table<R> table, String comment) {
|
TableFieldImpl(String name, DataType<T> type, Table<R> table, String comment, Converter<?, T> converter) {
|
||||||
super(name, type, comment);
|
super(name, type, comment, converter);
|
||||||
|
|
||||||
this.table = table;
|
this.table = table;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -162,7 +162,7 @@ class UDTConstant<R extends UDTRecord<R>> extends AbstractParam<R> {
|
|||||||
xx xxxxxx xxxxxxxx xxxxxxxxxxxxxxxxx xxxxx xxx xxxxxx xxx xx xxxxx
|
xx xxxxxx xxxxxxxx xxxxxxxxxxxxxxxxx xxxxx xxx xxxxxx xxx xx xxxxx
|
||||||
xx xx xxx xxxxxxxxxxxxxxxxx xxxxxxxx
|
xx xx xxx xxxxxxxxxxxxxxxxx xxxxxxxx
|
||||||
xxxx xxxxxxx
|
xxxx xxxxxxx
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxx
|
xxxxxxxxxxxxxxxxxxxxxxxx xxxxxx
|
||||||
xxxxxx
|
xxxxxx
|
||||||
|
|
||||||
xx xx xxx xxx xxxx xxxxxxxx xxxxxx xx xx xxxxxxx xxxx xxx xxxxxxxx xxxxx
|
xx xx xxx xxx xxxx xxxxxxxx xxxxxx xx xx xxxxxxx xxxx xxx xxxxxxxx xxxxx
|
||||||
|
|||||||
@ -2255,15 +2255,9 @@ final class Utils {
|
|||||||
static final <T, U> U getFromResultSet(ExecuteContext ctx, Field<U> field, int index) throws SQLException {
|
static final <T, U> U getFromResultSet(ExecuteContext ctx, Field<U> field, int index) throws SQLException {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Converter<T, U> converter = (Converter<T, U>) DataTypes.converter(field.getType());
|
Converter<T, U> converter = (Converter<T, U>) field.getConverter();
|
||||||
|
|
||||||
if (converter != null) {
|
|
||||||
return converter.from(getFromResultSet(ctx, converter.fromType(), index));
|
return converter.from(getFromResultSet(ctx, converter.fromType(), index));
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return getFromResultSet(ctx, field.getType(), index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static final <T> T getFromResultSet(ExecuteContext ctx, Class<T> type, int index) throws SQLException {
|
private static final <T> T getFromResultSet(ExecuteContext ctx, Class<T> type, int index) throws SQLException {
|
||||||
|
|||||||
@ -108,7 +108,7 @@ class Val<T> extends AbstractParam<T> {
|
|||||||
// Casting can be enforced or prevented
|
// Casting can be enforced or prevented
|
||||||
switch (context.castMode()) {
|
switch (context.castMode()) {
|
||||||
case NEVER:
|
case NEVER:
|
||||||
toSQL(context, value, getType());
|
toSQL(context, value, getConverter());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case ALWAYS:
|
case ALWAYS:
|
||||||
@ -127,7 +127,7 @@ class Val<T> extends AbstractParam<T> {
|
|||||||
toSQLCast(context);
|
toSQLCast(context);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
toSQL(context, value, getType());
|
toSQL(context, value, getConverter());
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -140,7 +140,7 @@ class Val<T> extends AbstractParam<T> {
|
|||||||
|
|
||||||
// Most RDBMS can infer types for bind values
|
// Most RDBMS can infer types for bind values
|
||||||
else {
|
else {
|
||||||
toSQL(context, value, getType());
|
toSQL(context, value, getConverter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +245,7 @@ class Val<T> extends AbstractParam<T> {
|
|||||||
// [#1125] Also with temporal data types, casting is needed some times
|
// [#1125] Also with temporal data types, casting is needed some times
|
||||||
// [#1130] TODO type can be null for ARRAY types, etc.
|
// [#1130] TODO type can be null for ARRAY types, etc.
|
||||||
else if (family == POSTGRES && (type == null || !type.isTemporal())) {
|
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
|
// [#1727] VARCHAR types should be cast to their actual lengths in some
|
||||||
@ -291,7 +291,7 @@ class Val<T> extends AbstractParam<T> {
|
|||||||
|
|
||||||
private final void toSQLCast(RenderContext context, DataType<?> type, int length, int precision, int scale) {
|
private final void toSQLCast(RenderContext context, DataType<?> type, int length, int precision, int scale) {
|
||||||
context.keyword("cast").sql("(");
|
context.keyword("cast").sql("(");
|
||||||
toSQL(context, value, getType());
|
toSQL(context, value, getConverter());
|
||||||
context.sql(" ").keyword("as").sql(" ")
|
context.sql(" ").keyword("as").sql(" ")
|
||||||
.sql(type.length(length).precision(precision, scale).getCastTypeName(context.configuration()))
|
.sql(type.length(length).precision(precision, scale).getCastTypeName(context.configuration()))
|
||||||
.sql(")");
|
.sql(")");
|
||||||
@ -317,31 +317,16 @@ class Val<T> extends AbstractParam<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* Inlining abstraction
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
private final void toSQL(RenderContext context, Object val, Class<?> type) {
|
private final void toSQL(RenderContext context, Object val, Converter<?, T> converter) {
|
||||||
SQLDialect family = context.configuration().dialect().family();
|
SQLDialect family = context.configuration().dialect().family();
|
||||||
|
|
||||||
// [#650] Check first, if we have a converter for the supplied type
|
// [#650] [#3108] Check first, if we have a converter for the supplied type
|
||||||
Converter<?, ?> converter = DataTypes.converter(type);
|
Class<?> type = converter.fromType();
|
||||||
if (converter != null) {
|
|
||||||
val = ((Converter) converter).to(val);
|
val = ((Converter) converter).to(val);
|
||||||
type = converter.fromType();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInline(context)) {
|
if (isInline(context)) {
|
||||||
// [#2223] Some type-casts in this section may seem unnecessary, e.g.
|
// [#2223] Some type-casts in this section may seem unnecessary, e.g.
|
||||||
@ -511,7 +496,7 @@ class Val<T> extends AbstractParam<T> {
|
|||||||
|
|
||||||
for (Object o : ((Object[]) val)) {
|
for (Object o : ((Object[]) val)) {
|
||||||
context.sql(separator);
|
context.sql(separator);
|
||||||
toSQL(context, o, type.getComponentType());
|
toSQL(context, o, new IdentityConverter(type.getComponentType()));
|
||||||
separator = ", ";
|
separator = ", ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,7 +510,7 @@ class Val<T> extends AbstractParam<T> {
|
|||||||
|
|
||||||
for (Object o : ((Object[]) val)) {
|
for (Object o : ((Object[]) val)) {
|
||||||
context.sql(separator);
|
context.sql(separator);
|
||||||
toSQL(context, o, type.getComponentType());
|
toSQL(context, o, new IdentityConverter(type.getComponentType()));
|
||||||
separator = ", ";
|
separator = ", ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +523,14 @@ class Val<T> extends AbstractParam<T> {
|
|||||||
x
|
x
|
||||||
xx [/pro] */
|
xx [/pro] */
|
||||||
else if (EnumType.class.isAssignableFrom(type)) {
|
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)) {
|
else if (UDTRecord.class.isAssignableFrom(type)) {
|
||||||
context.sql("[UDT]");
|
context.sql("[UDT]");
|
||||||
@ -609,7 +601,7 @@ class Val<T> extends AbstractParam<T> {
|
|||||||
|
|
||||||
// [#1302] Bind value only if it was not explicitly forced to be inlined
|
// [#1302] Bind value only if it was not explicitly forced to be inlined
|
||||||
if (!isInline()) {
|
if (!isInline()) {
|
||||||
context.bindValue(value, getType());
|
context.bindValue(value, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -48,7 +48,6 @@ import org.jooq.Record;
|
|||||||
import org.jooq.RenderContext;
|
import org.jooq.RenderContext;
|
||||||
import org.jooq.Row;
|
import org.jooq.Row;
|
||||||
import org.jooq.Select;
|
import org.jooq.Select;
|
||||||
import org.jooq.Support;
|
|
||||||
import org.jooq.Table;
|
import org.jooq.Table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -973,7 +973,7 @@ public class BasicTest extends AbstractTest {
|
|||||||
public void bind(BindContext ctx) {
|
public void bind(BindContext ctx) {
|
||||||
try {
|
try {
|
||||||
ctx.statement().setInt(ctx.nextIndex(), 1);
|
ctx.statement().setInt(ctx.nextIndex(), 1);
|
||||||
ctx.bindValues(1);
|
ctx.bindValue(1, DSL.val(1));
|
||||||
}
|
}
|
||||||
catch (SQLException ignore) {}
|
catch (SQLException ignore) {}
|
||||||
}
|
}
|
||||||
@ -1064,7 +1064,7 @@ public class BasicTest extends AbstractTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bind(BindContext ctx) {
|
public void bind(BindContext ctx) {
|
||||||
ctx.bindValues(1);
|
ctx.bindValue(1, DSL.val(1));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user