[jOOQ/jOOQ#14671] Wrong column resolved by JoinTable.field(Field), when JoinTable contains aliased tables and lookup uses unaliased tables
This commit is contained in:
parent
9051dc1899
commit
8c2cebaee9
@ -44,6 +44,7 @@ import static org.jooq.impl.Tools.converterOrFail;
|
||||
import static org.jooq.impl.Tools.indexOrFail;
|
||||
import static org.jooq.impl.Tools.map;
|
||||
import static org.jooq.impl.Tools.newRecord;
|
||||
import static org.jooq.impl.Tools.unaliasTable;
|
||||
|
||||
import java.sql.SQLWarning;
|
||||
import java.util.ArrayList;
|
||||
@ -244,10 +245,16 @@ final class FieldsImpl<R extends Record> extends AbstractQueryPart implements Re
|
||||
return result.result(f, i);
|
||||
}
|
||||
|
||||
// [#4283] table / column matches are better than only column matches
|
||||
Field<?> columnMatch = null;
|
||||
Field<?> columnMatch2 = null;
|
||||
int indexMatch = -1;
|
||||
// [#4283] table / column matches are better than column only matches
|
||||
Field<?> columnOnlyMatch = null;
|
||||
Field<?> columnOnlyMatch2 = null;
|
||||
int columnOnlyIndexMatch = -1;
|
||||
|
||||
// [#14671] column only matches might still match on the unaliased table
|
||||
Field<?> unaliased = null;
|
||||
Field<?> aliasMatch = null;
|
||||
Field<?> aliasMatch2 = null;
|
||||
int aliasIndexMatch = -1;
|
||||
|
||||
String tableName = tableName(field);
|
||||
String fieldName = field.getName();
|
||||
@ -265,26 +272,44 @@ final class FieldsImpl<R extends Record> extends AbstractQueryPart implements Re
|
||||
|
||||
// In case no exact match was found, return the first field with matching name
|
||||
if (fName.equals(fieldName)) {
|
||||
if (columnMatch == null) {
|
||||
columnMatch = f;
|
||||
indexMatch = i;
|
||||
|
||||
// [#14671] Prefer matches by unaliased tables, if applicable
|
||||
if (unaliased == null)
|
||||
unaliased = unaliasTable(field);
|
||||
|
||||
if (unaliased != null && unaliased.equals(unaliasTable(f))) {
|
||||
if (aliasMatch == null) {
|
||||
aliasMatch = f;
|
||||
aliasIndexMatch = i;
|
||||
}
|
||||
else
|
||||
aliasMatch2 = f;
|
||||
}
|
||||
|
||||
if (columnOnlyMatch == null) {
|
||||
columnOnlyMatch = f;
|
||||
columnOnlyIndexMatch = i;
|
||||
}
|
||||
|
||||
// [#4476] [#4477] This might be unintentional from a user
|
||||
// perspective, e.g. when ambiguous ID columns are present.
|
||||
// [#5578] Finish the loop, though, as we might have an exact match
|
||||
// despite some ambiguity
|
||||
else {
|
||||
columnMatch2 = f;
|
||||
}
|
||||
else
|
||||
columnOnlyMatch2 = f;
|
||||
}
|
||||
}
|
||||
|
||||
if (columnMatch2 != null)
|
||||
if (log.isInfoEnabled())
|
||||
log.info("Ambiguous match found for " + fieldName + ". Both " + columnMatch + " and " + columnMatch2 + " match.", new SQLWarning());
|
||||
if (aliasMatch2 != null && log.isInfoEnabled())
|
||||
log.info("Ambiguous match found for " + fieldName + ". Both " + aliasMatch + " and " + aliasMatch2 + " match.", new SQLWarning());
|
||||
|
||||
return result.result(columnMatch, indexMatch);
|
||||
if (aliasMatch != null)
|
||||
return result.result(aliasMatch, aliasIndexMatch);
|
||||
|
||||
if (columnOnlyMatch2 != null && log.isInfoEnabled())
|
||||
log.info("Ambiguous match found for " + fieldName + ". Both " + columnOnlyMatch + " and " + columnOnlyMatch2 + " match.", new SQLWarning());
|
||||
|
||||
return result.result(columnOnlyMatch, columnOnlyIndexMatch);
|
||||
}
|
||||
|
||||
private final String tableName(Field<?> field) {
|
||||
|
||||
@ -6132,6 +6132,21 @@ final class Tools {
|
||||
return result != null ? result : field;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static final <T> Field<T> unaliasTable(Field<T> field) {
|
||||
if (field instanceof TableField<?, ?> tf) {
|
||||
Table<?> t = aliased(tf.getTable());
|
||||
|
||||
// [#14671] Use only the Field::getName for lookups to avoid:
|
||||
// - StackOverflowError
|
||||
// - Otherwise Field or Name related lookup efforts
|
||||
if (t != null)
|
||||
return (Field<T>) t.field(field.getName());
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
static final <T> Field<T> aliased(Field<T> field) {
|
||||
if (field instanceof FieldAlias<T> f)
|
||||
return f.getAliasedField();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user