[jOOQ/jOOQ#12328] Empty select() should not project asterisk if unknown table is used with leftSemiJoin() or leftAntiJoin()

This commit is contained in:
Lukas Eder 2021-08-18 16:36:03 +02:00
parent 6dd904d3d4
commit e523b43b7e
3 changed files with 52 additions and 14 deletions

View File

@ -237,7 +237,7 @@ final class DeleteQueryImpl<R extends Record> extends AbstractDMLQuery<R> implem
if (multiTableJoin)
// No table declarations in this case, but references
ctx.visit(K_FROM).sql(' ').visit(traverseJoins(t, new TableList(), x -> false, (r, x) -> { r.add(x); return r; })).formatSeparator();
ctx.visit(K_FROM).sql(' ').visit(traverseJoins(t, new TableList(), null, (r, x) -> { r.add(x); return r; })).formatSeparator();

View File

@ -3815,7 +3815,20 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
}
private final boolean knownTableSource() {
return traverseJoins(getFrom(), true, r -> !r, (r, t) -> r && t.fieldsRow().size() > 0);
return traverseJoins(
getFrom(),
true,
r -> !r,
null,
// [#12328] Don't recurse into the RHS if the join does not affect the projection
j -> j.type != JoinType.LEFT_ANTI_JOIN && j.type != JoinType.LEFT_SEMI_JOIN,
null,
// TODO: PostgreSQL supports tables without columns, see e.g.
// https://blog.jooq.org/creating-tables-dum-and-dee-in-postgresql/
(r, t) -> r && t.fieldsRow().size() > 0
);
}
@SuppressWarnings("unchecked")

View File

@ -6260,7 +6260,7 @@ final class Tools {
}
static final void traverseJoins(Table<?> t, Consumer<? super Table<?>> consumer) {
traverseJoins(t, null, x -> false, (result, x) -> { consumer.accept(x); return result; });
traverseJoins(t, null, null, (result, x) -> { consumer.accept(x); return result; });
}
static final <T> T traverseJoins(
@ -6270,7 +6270,7 @@ final class Tools {
BiFunction<? super T, ? super Table<?>, ? extends T> function
) {
for (Table<?> t : i)
if (abort.test(result))
if (abort != null && abort.test(result))
return result;
else
result = traverseJoins(t, result, abort, function);
@ -6284,33 +6284,58 @@ final class Tools {
Predicate<? super T> abort,
BiFunction<? super T, ? super Table<?>, ? extends T> function
) {
return traverseJoins(t, result, abort, null, function);
return traverseJoins(t, result, abort, null, null, null, function);
}
static final <T> T traverseJoins(
Iterable<? extends Table<?>> i,
T result,
Predicate<? super T> abort,
Predicate<? super JoinTable> recurseLhs,
Predicate<? super JoinTable> recurseRhs,
BiFunction<? super T, ? super JoinType, ? extends T> joinTypeFunction,
BiFunction<? super T, ? super Table<?>, ? extends T> tableFunction
) {
for (Table<?> t : i)
if (abort != null && abort.test(result))
return result;
else
result = traverseJoins(t, result, abort, recurseLhs, recurseRhs, joinTypeFunction, tableFunction);
return result;
}
static final <T> T traverseJoins(
Table<?> t,
T result,
Predicate<? super T> abort,
Predicate<? super JoinTable> recurseLhs,
Predicate<? super JoinTable> recurseRhs,
BiFunction<? super T, ? super JoinType, ? extends T> joinTypeFunction,
BiFunction<? super T, ? super Table<?>, ? extends T> tableFunction
) {
if (abort.test(result))
if (abort != null && abort.test(result))
return result;
if (t instanceof JoinTable) {
result = traverseJoins(((JoinTable) t).lhs, result, abort, joinTypeFunction, tableFunction);
JoinTable j = (JoinTable) t;
if (abort.test(result))
return result;
if (recurseLhs == null || recurseLhs.test(j)) {
result = traverseJoins(j.lhs, result, abort, recurseLhs, recurseRhs, joinTypeFunction, tableFunction);
if (joinTypeFunction != null) {
result = joinTypeFunction.apply(result, ((JoinTable) t).type);
if (abort.test(result))
if (abort != null && abort.test(result))
return result;
}
result = traverseJoins(((JoinTable) t).rhs, result, abort, joinTypeFunction, tableFunction);
if (joinTypeFunction != null) {
result = joinTypeFunction.apply(result, j.type);
if (abort != null && abort.test(result))
return result;
}
if (recurseRhs == null || recurseRhs.test(j))
result = traverseJoins(j.rhs, result, abort, recurseLhs, recurseRhs, joinTypeFunction, tableFunction);
}
else if (tableFunction != null)
result = tableFunction.apply(result, t);