[jOOQ/jOOQ#12704] DefaultRecordUnmapper.IterableUnmapper uses name based
field access instead of index based ones, leading to ambiguities
This commit is contained in:
parent
c079eac3c9
commit
82a565f566
@ -408,6 +408,10 @@ abstract class AbstractRecord extends AbstractStore implements Record {
|
||||
public final <T> void set(Field<T> field, T value) {
|
||||
int index = fields.indexOf(field);
|
||||
|
||||
set(field, index, value);
|
||||
}
|
||||
|
||||
final <T> void set(Field<T> field, int index, T value) {
|
||||
if (index >= 0)
|
||||
set(index, field, value);
|
||||
else if (Tools.nonReplacingEmbeddable(field)) {
|
||||
@ -904,109 +908,93 @@ abstract class AbstractRecord extends AbstractStore implements Record {
|
||||
return (@NotNull E) mapper.map(this);
|
||||
}
|
||||
|
||||
private final void from0(Object source, FieldsImpl f) {
|
||||
private final void from0(Object source, int[] targetIndexMapping) {
|
||||
if (source == null) return;
|
||||
|
||||
// [#2520] TODO: Benchmark this from() method. There's probably a better implementation
|
||||
from(Tools.configuration(this).recordUnmapperProvider().provide(source.getClass(), f).unmap(prepareArrayForUnmap(source, f)));
|
||||
from(
|
||||
Tools.configuration(this).recordUnmapperProvider().provide(source.getClass(), (FieldsImpl) fields.fields).unmap(source),
|
||||
targetIndexMapping
|
||||
);
|
||||
|
||||
// [#2700] [#3582] If a POJO attribute is NULL, but the column is NOT NULL
|
||||
// then we should let the database apply DEFAULT values
|
||||
resetChangedOnNotNull(this);
|
||||
}
|
||||
|
||||
private final Object prepareArrayForUnmap(Object source, FieldsImpl f) {
|
||||
if (source instanceof Object[]) { Object[] array = (Object[]) source;
|
||||
if (array.length != f.size()) {
|
||||
Object[] result = new Object[f.size()];
|
||||
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
int index = fields.indexOf(f.field(i));
|
||||
result[i] = index >= 0 && index < array.length ? array[index] : null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return source;
|
||||
}
|
||||
else
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void from(Object source) {
|
||||
from0(source, fields.fields);
|
||||
from0(source, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void from(Object source, Field<?>... f) {
|
||||
from0(source, new FieldsImpl(f));
|
||||
from0(source, fields.fields.indexesOf(f));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void from(Object source, String... fieldNames) {
|
||||
from(source, fields(fieldNames));
|
||||
from0(source, fields.fields.indexesOf(fieldNames));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void from(Object source, Name... fieldNames) {
|
||||
from(source, fields(fieldNames));
|
||||
from0(source, fields.fields.indexesOf(fieldNames));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void from(Object source, int... fieldIndexes) {
|
||||
from(source, fields(fieldIndexes));
|
||||
from0(source, fieldIndexes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fromMap(Map<String, ?> map) {
|
||||
from(map, fields());
|
||||
from(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fromMap(Map<String, ?> map, Field<?>... f) {
|
||||
from0(map, new FieldsImpl(f));
|
||||
from(map, f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fromMap(Map<String, ?> map, String... fieldNames) {
|
||||
fromMap(map, fields(fieldNames));
|
||||
from(map, fieldNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fromMap(Map<String, ?> map, Name... fieldNames) {
|
||||
fromMap(map, fields(fieldNames));
|
||||
from(map, fieldNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fromMap(Map<String, ?> map, int... fieldIndexes) {
|
||||
fromMap(map, fields(fieldIndexes));
|
||||
from(map, fieldIndexes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fromArray(Object... array) {
|
||||
fromArray(array, fields());
|
||||
from(array);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fromArray(Object[] array, Field<?>... f) {
|
||||
from0(array, new FieldsImpl(f));
|
||||
from(array, f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fromArray(Object[] array, String... fieldNames) {
|
||||
fromArray(array, fields(fieldNames));
|
||||
from(array, fieldNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fromArray(Object[] array, Name... fieldNames) {
|
||||
fromArray(array, fields(fieldNames));
|
||||
from(array, fieldNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fromArray(Object[] array, int... fieldIndexes) {
|
||||
fromArray(array, fields(fieldIndexes));
|
||||
from(array, fieldIndexes);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1022,6 +1010,18 @@ abstract class AbstractRecord extends AbstractStore implements Record {
|
||||
}
|
||||
}
|
||||
|
||||
final void from(Record source, int[] indexMapping) {
|
||||
int s = source.size();
|
||||
int t = indexMapping == null ? s : indexMapping.length;
|
||||
|
||||
for (int i = 0; i < s && i < t; i++) {
|
||||
int j = indexMapping == null ? i : indexMapping[i];
|
||||
|
||||
if (source.field(j) != null && source.changed(j))
|
||||
Tools.setValue(this, field(j), j, source, j);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Formatting methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -135,19 +135,15 @@ public class DefaultRecordUnmapper<E, R extends Record> implements RecordUnmappe
|
||||
|
||||
private final class ArrayUnmapper implements RecordUnmapper<E, R> {
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
@Override
|
||||
public final R unmap(E source) {
|
||||
if (source instanceof Object[]) { Object[] array = (Object[]) source;
|
||||
int size = rowType.size();
|
||||
Record record = newRecord();
|
||||
AbstractRecord record = (AbstractRecord) newRecord();
|
||||
|
||||
for (int i = 0; i < size && i < array.length; i++) {
|
||||
Field field = rowType.field(i);
|
||||
|
||||
if (rowType.field(field) != null)
|
||||
Tools.setValue(record, field, array[i]);
|
||||
}
|
||||
for (int i = 0; i < size && i < array.length; i++)
|
||||
Tools.setValue(record, rowType.field(i), i, array[i]);
|
||||
|
||||
return (R) record;
|
||||
}
|
||||
@ -158,20 +154,16 @@ public class DefaultRecordUnmapper<E, R extends Record> implements RecordUnmappe
|
||||
|
||||
private final class IterableUnmapper implements RecordUnmapper<E, R> {
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
@Override
|
||||
public final R unmap(E source) {
|
||||
if (source instanceof Iterable) { Iterable<?> iterable = (Iterable<?>) source;
|
||||
Iterator<?> it = iterable.iterator();
|
||||
int size = rowType.size();
|
||||
Record record = newRecord();
|
||||
AbstractRecord record = (AbstractRecord) newRecord();
|
||||
|
||||
for (int i = 0; i < size && it.hasNext(); i++) {
|
||||
Field field = rowType.field(i);
|
||||
|
||||
if (rowType.field(field) != null)
|
||||
Tools.setValue(record, field, it.next());
|
||||
}
|
||||
for (int i = 0; i < size && it.hasNext(); i++)
|
||||
Tools.setValue(record, rowType.field(i), i, it.next());
|
||||
|
||||
return (R) record;
|
||||
}
|
||||
|
||||
@ -49,9 +49,7 @@ import java.sql.SQLWarning;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jooq.Configuration;
|
||||
@ -63,7 +61,6 @@ import org.jooq.Name;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.RecordMapper;
|
||||
import org.jooq.RecordType;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.Row;
|
||||
import org.jooq.SelectField;
|
||||
import org.jooq.Table;
|
||||
@ -473,10 +470,6 @@ final class FieldsImpl<R extends Record> extends AbstractQueryPart implements Re
|
||||
return dataType(indexOrFail(this, fieldName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated - 3.14.5 - [#11058] - These are used for the deprecated interning feature only.
|
||||
*/
|
||||
@Deprecated
|
||||
final int[] indexesOf(Field<?>... f) {
|
||||
int[] result = new int[f.length];
|
||||
|
||||
@ -486,10 +479,6 @@ final class FieldsImpl<R extends Record> extends AbstractQueryPart implements Re
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated - 3.14.5 - [#11058] - These are used for the deprecated interning feature only.
|
||||
*/
|
||||
@Deprecated
|
||||
final int[] indexesOf(String... fieldNames) {
|
||||
int[] result = new int[fieldNames.length];
|
||||
|
||||
@ -499,10 +488,6 @@ final class FieldsImpl<R extends Record> extends AbstractQueryPart implements Re
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated - 3.14.5 - [#11058] - These are used for the deprecated interning feature only.
|
||||
*/
|
||||
@Deprecated
|
||||
final int[] indexesOf(Name... fieldNames) {
|
||||
int[] result = new int[fieldNames.length];
|
||||
|
||||
@ -512,7 +497,6 @@ final class FieldsImpl<R extends Record> extends AbstractQueryPart implements Re
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void accept(Context<?> ctx) {
|
||||
ctx.visit(wrap(fields));
|
||||
|
||||
@ -3154,6 +3154,13 @@ final class Tools {
|
||||
setValue(target, targetField, source.get(sourceField));
|
||||
}
|
||||
|
||||
/**
|
||||
* Type-safely copy a value from one record to another
|
||||
*/
|
||||
static final <T> void setValue(AbstractRecord target, Field<T> targetField, int targetIndex, Record source, int sourceIndex) {
|
||||
setValue(target, targetField, targetIndex, source.get(sourceIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Type-safely set a value to a record
|
||||
*/
|
||||
@ -3161,6 +3168,13 @@ final class Tools {
|
||||
target.set(targetField, targetField.getDataType().convert(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Type-safely set a value to a record
|
||||
*/
|
||||
static final <T> void setValue(AbstractRecord target, Field<T> targetField, int targetIndex, Object value) {
|
||||
target.set(targetField, targetIndex, targetField.getDataType().convert(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* [#2591] Type-safely copy a value from one record to another, preserving flags.
|
||||
*/
|
||||
|
||||
@ -105,7 +105,7 @@ final class XMLHandler<R extends Record> extends DefaultHandler {
|
||||
XMLHandler(DSLContext ctx, AbstractRow<R> row, Class<? extends R> recordType) {
|
||||
this.ctx = ctx;
|
||||
this.states = new ArrayDeque<>();
|
||||
s = new State<>(row, recordType);
|
||||
this.s = new State<>(row, recordType);
|
||||
}
|
||||
|
||||
Result<R> read(String string) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user