diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONReader.java b/jOOQ/src/main/java/org/jooq/impl/JSONReader.java index 955626727d..2dabc76159 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONReader.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONReader.java @@ -54,6 +54,7 @@ import static org.jooq.impl.DSL.name; import static org.jooq.impl.DefaultDataType.getDataType; import static org.jooq.impl.SQLDataType.VARCHAR; import static org.jooq.impl.Tools.convertHexToBytes; +import static org.jooq.impl.Tools.converterContext; import static org.jooq.impl.Tools.fields; import static org.jooq.impl.Tools.newRecord; import static org.jooq.tools.StringUtils.defaultIfBlank; @@ -68,7 +69,10 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.jooq.ContextConverter; +import org.jooq.ConverterContext; import org.jooq.DSLContext; +import org.jooq.DataType; import org.jooq.Field; import org.jooq.Fields; import org.jooq.Record; @@ -247,13 +251,16 @@ final class JSONReader { private static final Set ENCODE_BINARY_AS_TEXT = SQLDialect.supportedBy(MARIADB); private static final List patchRecord(DSLContext ctx, boolean multiset, Fields result, List record) { + ConverterContext cc = null; + for (int i = 0; i < result.fields().length; i++) { Field field = result.field(i); Object value = record.get(i); + DataType t = field.getDataType(); // [#8829] LoaderImpl expects binary data to be encoded in base64, // not according to org.jooq.tools.Convert - if (field.getDataType().isBinary() && value instanceof String s) { + if (t.isBinary() && value instanceof String s) { if (multiset) { // [#12134] PostgreSQL encodes binary data as hex @@ -278,12 +285,26 @@ final class JSONReader { record.set(i, Base64.getDecoder().decode(s)); } + // [#18190] For historic reasons, Record.from() will not apply Converter, so any potential + // Converter should be applied eagerly, before loading data into the record. + else if (multiset + && t instanceof ConvertedDataType + && t.getFromType() == String.class + && t.getToType() == String.class + && (value == null || value instanceof String) + ) { + record.set(i, ((ContextConverter) t.getConverter()).from( + (String) value, + cc == null ? (cc = converterContext(ctx.configuration())) : cc + )); + } + // [#12155] Recurse for nested MULTISET - else if (multiset && field.getDataType().isMultiset()) { + else if (multiset && t.isMultiset()) { record.set(i, read( ctx, - (AbstractRow) field.getDataType().getRow(), - (Class) field.getDataType().getRecordType(), + (AbstractRow) t.getRow(), + (Class) t.getRecordType(), multiset, value )); @@ -291,9 +312,9 @@ final class JSONReader { // [#14657] Recurse for nested ROW // [#18152] Handle also the Map encoding of nested ROW values - else if (multiset && field.getDataType().isRecord() && (value instanceof List || value instanceof Map)) { - AbstractRow actualRow = (AbstractRow) field.getDataType().getRow(); - Class recordType = field.getDataType().getRecordType(); + else if (multiset && t.isRecord() && (value instanceof List || value instanceof Map)) { + AbstractRow actualRow = (AbstractRow) t.getRow(); + Class recordType = t.getRecordType(); List l; diff --git a/jOOQ/src/main/java/org/jooq/impl/XMLHandler.java b/jOOQ/src/main/java/org/jooq/impl/XMLHandler.java index eea8f2542b..79622bb10d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/XMLHandler.java +++ b/jOOQ/src/main/java/org/jooq/impl/XMLHandler.java @@ -44,6 +44,7 @@ import static org.jooq.impl.DefaultDataType.getDataType; import static org.jooq.impl.SQLDataType.VARCHAR; import static org.jooq.impl.Tools.EMPTY_FIELD; import static org.jooq.impl.Tools.allMatch; +import static org.jooq.impl.Tools.converterContext; import static org.jooq.impl.Tools.fields; import static org.jooq.impl.Tools.newRecord; import static org.jooq.impl.Tools.row0; @@ -60,6 +61,9 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import org.jooq.ContextConverter; +import org.jooq.Converter; +import org.jooq.ConverterContext; import org.jooq.DSLContext; import org.jooq.DataType; import org.jooq.Field; @@ -108,11 +112,15 @@ final class XMLHandler extends DefaultHandler { } final R into(R r) { + ConverterContext cc = null; // [#12134] Patch base64 encoded binary values for (int i = 0; i < fields.size(); i++) { - if (fields.get(i).getDataType().isBinary()) { - if (values.get(i) instanceof String s) { + Object v = values.get(i); + DataType t = fields.get(i).getDataType(); + + if (v instanceof String s) { + if (t.isBinary()) { @@ -121,6 +129,17 @@ final class XMLHandler extends DefaultHandler { values.set(i, Base64.getDecoder().decode(s)); } } + + // [#18190] For historic reasons, Record.from() will not apply Converter, so any potential + // Converter should be applied eagerly, before loading data into the record. + if (v == null || v instanceof String) { + if (t instanceof ConvertedDataType && t.getFromType() == String.class && t.getToType() == String.class) { + values.set(i, ((ContextConverter) t.getConverter()).from( + (String) v, + cc == null ? (cc = converterContext(ctx.configuration())) : cc + )); + } + } } r.from(values);