[jOOQ/jOOQ#10603] Ambiguous match with complex implicit join graphs

This commit is contained in:
Lukas Eder 2020-09-08 16:39:50 +02:00
parent 2203d53b5b
commit a00eda2c02
5 changed files with 46 additions and 8 deletions

View File

@ -1066,9 +1066,8 @@ public class PostgresDatabase extends AbstractDatabase {
return
create().select(PG_ENUM.ENUMLABEL)
.from(PG_ENUM)
.join(PG_TYPE).on(PG_ENUM.ENUMTYPID.eq(oid(PG_TYPE)))
.where(PG_TYPE.pgNamespace().NSPNAME.eq(nspname))
.and(PG_TYPE.TYPNAME.eq(typname))
.where(PG_ENUM.pgType().pgNamespace().NSPNAME.eq(nspname))
.and(PG_ENUM.pgType().TYPNAME.eq(typname))
.orderBy(orderBy)
.fetch(PG_ENUM.ENUMLABEL);
}

View File

@ -53,6 +53,7 @@ import static org.jooq.impl.Tools.BooleanDataKey.DATA_OMIT_CLAUSE_EVENT_EMISSION
import java.sql.PreparedStatement;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Deque;
import java.util.LinkedHashMap;
@ -804,5 +805,10 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
ScopeStackElement(int scopeLevel) {
this.scopeLevel = scopeLevel;
}
@Override
public String toString() {
return Arrays.toString(positions) + ": " + joinNode;
}
}
}

View File

@ -154,7 +154,7 @@ final class CreateTableImpl extends AbstractRowCountQuery implements
private static final Set<SQLDialect> SUPPORT_TEMPORARY = SQLDialect.supportedBy(MARIADB, MYSQL, POSTGRES);
private static final Set<SQLDialect> EMULATE_COMMENT_IN_BLOCK = SQLDialect.supportedBy(FIREBIRD, POSTGRES);
private static final Set<SQLDialect> REQUIRE_EXECUTE_IMMEDIATE = SQLDialect.supportedBy(FIREBIRD);
private static final Set<SQLDialect> NO_SUPPORT_NULLABLE_PRIMARY_KEY = SQLDialect.supportedBy(MYSQL);
private static final Set<SQLDialect> NO_SUPPORT_NULLABLE_PRIMARY_KEY = SQLDialect.supportedBy(MARIADB, MYSQL);
@ -553,10 +553,10 @@ final class CreateTableImpl extends AbstractRowCountQuery implements
private final DataType<?> columnType(Context<?> ctx, int i) {
DataType<?> type = columnTypes.get(i);
if (NO_SUPPORT_NULLABLE_PRIMARY_KEY.contains(ctx.dialect()) && type.nullability() == Nullability.DEFAULT && isPrimaryKey(i))
type = type.nullable(false);
return type;
}
@ -567,7 +567,7 @@ final class CreateTableImpl extends AbstractRowCountQuery implements
for (Field<?> field : ((ConstraintImpl) constraint).$primaryKey())
if (field.equals(columnFields.get(i)))
return true;
return false;
}

View File

@ -179,12 +179,13 @@ public class TableImpl<R extends Record> extends AbstractTable<R> {
this(name, schema, child, path, aliased, parameters, comment, TableOptions.table());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public TableImpl(Name name, Schema schema, Table<?> child, ForeignKey<?, R> path, Table<R> aliased, Field<?>[] parameters, Comment comment, TableOptions options) {
super(options, name, schema, comment);
this.fields = new Fields<>();
this.child = child;
this.childPath = path;
this.childPath = path == null ? null : Tools.aliasedKey((ForeignKey) path, child, this);
if (aliased != null) {

View File

@ -239,6 +239,7 @@ import org.jooq.EnumType;
import org.jooq.ExecuteContext;
import org.jooq.ExecuteListener;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.JSON;
import org.jooq.JSONB;
import org.jooq.Name;
@ -264,6 +265,7 @@ import org.jooq.Select;
import org.jooq.SelectFieldOrAsterisk;
import org.jooq.SortField;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.TableRecord;
import org.jooq.UDT;
import org.jooq.UDTRecord;
@ -1391,6 +1393,19 @@ final class Tools {
return result;
}
static <R extends Record, O extends Record> ReferenceImpl<R, O> aliasedKey(ForeignKey<R, O> key, Table<R> child, Table<O> parent) {
// [#10603] [#5050] TODO: Solve aliasing constraints more generically
return new ReferenceImpl<>(
child,
key.getQualifiedName(),
Tools.fieldsByName(child, key.getFieldsArray()),
key.getKey(),
Tools.fieldsByName(parent, key.getKeyFieldsArray()),
key.enforced()
);
}
static final Field<?>[] aliasedFields(Field<?>[] fields) {
if (fields == null)
return null;
@ -1420,6 +1435,23 @@ final class Tools {
return result;
}
@SuppressWarnings("unchecked")
static final <R extends Record> TableField<R, ?>[] fieldsByName(Table<R> tableName, Field<?>[] fieldNames) {
if (fieldNames == null)
return null;
TableField<R, ?>[] result = new TableField[fieldNames.length];
if (tableName == null)
for (int i = 0; i < fieldNames.length; i++)
result[i] = (TableField<R, ?>) DSL.field(fieldNames[i].getUnqualifiedName(), fieldNames[i].getDataType());
else
for (int i = 0; i < fieldNames.length; i++)
result[i] = (TableField<R, ?>) DSL.field(tableName.getQualifiedName().append(fieldNames[i].getUnqualifiedName()), fieldNames[i].getDataType());
return result;
}
static final Field<?>[] fieldsByName(Name tableName, Name[] fieldNames) {
if (fieldNames == null)
return null;