Skip to content

Commit bd9ac2f

Browse files
authored
Merge pull request #4103 from katzyn/map_columns
Pass mapped columns to table filters of subqueries
2 parents 74ed2b5 + 64f2fbe commit bd9ac2f

File tree

10 files changed

+107
-17
lines changed

10 files changed

+107
-17
lines changed

h2/src/docsrc/html/changelog.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ <h1>Change Log</h1>
2121

2222
<h2>Next Version (unreleased)</h2>
2323
<ul>
24+
<li>Issue #3945: Column not found in correlated subquery, when referencing outer column from LEFT JOIN .. ON clause
25+
</li>
26+
<li>Issue #4097: StackOverflowException when using multiple SELECT statements in one query (2.3.230)
27+
</li>
28+
<li>Issue #3982: Potential issue when using ROUND
29+
</li>
30+
<li>Issue #3894: Race condition causing stale data in query last result cache
31+
</li>
32+
<li>Issue #4075: infinite loop in compact
33+
</li>
34+
<li>Issue #4091: Wrong case with linked table to postgresql
35+
</li>
2436
<li>Issue #4088: BadGrammarException when the same alias is used within two different CTEs
2537
</li>
2638
<li>Issue #4079: [2.3.230] Regression in ORDER BY ... DESC on dates

h2/src/main/org/h2/command/query/Query.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,10 @@ public TypeInfo getRowDataType() {
336336
* @param level
337337
* the subquery level (0 is the top level query, 1 is the first
338338
* subquery level)
339+
* @param outer
340+
* whether this method was called from the outer query
339341
*/
340-
public abstract void mapColumns(ColumnResolver resolver, int level);
342+
public abstract void mapColumns(ColumnResolver resolver, int level, boolean outer);
341343

342344
/**
343345
* Change the evaluatable flag. This is used when building the execution

h2/src/main/org/h2/command/query/Select.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,7 @@ public void init() {
11551155
}
11561156
// map columns in select list and condition
11571157
for (TableFilter f : filters) {
1158-
mapColumns(f, 0);
1158+
mapColumns(f, 0, false);
11591159
}
11601160
mapCondition(havingIndex);
11611161
mapCondition(qualifyIndex);
@@ -1596,13 +1596,16 @@ public void setForUpdate(ForUpdate b) {
15961596
}
15971597

15981598
@Override
1599-
public void mapColumns(ColumnResolver resolver, int level) {
1599+
public void mapColumns(ColumnResolver resolver, int level, boolean outer) {
16001600
for (Expression e : expressions) {
16011601
e.mapColumns(resolver, level, Expression.MAP_INITIAL);
16021602
}
16031603
if (condition != null) {
16041604
condition.mapColumns(resolver, level, Expression.MAP_INITIAL);
16051605
}
1606+
for (TableFilter tableFilter : topFilters) {
1607+
tableFilter.mapColumns(resolver, level, outer);
1608+
}
16061609
}
16071610

16081611
@Override

h2/src/main/org/h2/command/query/SelectUnion.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -303,9 +303,9 @@ public void setForUpdate(ForUpdate forUpdate) {
303303
}
304304

305305
@Override
306-
public void mapColumns(ColumnResolver resolver, int level) {
307-
left.mapColumns(resolver, level);
308-
right.mapColumns(resolver, level);
306+
public void mapColumns(ColumnResolver resolver, int level, boolean outer) {
307+
left.mapColumns(resolver, level, outer);
308+
right.mapColumns(resolver, level, outer);
309309
}
310310

311311
@Override

h2/src/main/org/h2/command/query/TableValueConstructor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ public void setForUpdate(ForUpdate forUpdate) {
262262
}
263263

264264
@Override
265-
public void mapColumns(ColumnResolver resolver, int level) {
265+
public void mapColumns(ColumnResolver resolver, int level, boolean outer) {
266266
int columnCount = visibleColumnCount;
267267
for (ArrayList<Expression> row : rows) {
268268
for (int i = 0; i < columnCount; i++) {

h2/src/main/org/h2/expression/ArrayConstructorByQuery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public TypeInfo getType() {
6565

6666
@Override
6767
public void mapColumns(ColumnResolver resolver, int level, int state) {
68-
query.mapColumns(resolver, level + 1);
68+
query.mapColumns(resolver, level + 1, true);
6969
}
7070

7171
@Override

h2/src/main/org/h2/expression/Subquery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public TypeInfo getType() {
9090
@Override
9191
public void mapColumns(ColumnResolver resolver, int level, int state) {
9292
outerResolvers.add(resolver);
93-
query.mapColumns(resolver, level + 1);
93+
query.mapColumns(resolver, level + 1, true);
9494
}
9595

9696
@Override

h2/src/main/org/h2/expression/condition/PredicateWithSubquery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ abstract class PredicateWithSubquery extends Condition {
2929

3030
@Override
3131
public void mapColumns(ColumnResolver resolver, int level, int state) {
32-
query.mapColumns(resolver, level + 1);
32+
query.mapColumns(resolver, level + 1, true);
3333
}
3434

3535
@Override

h2/src/main/org/h2/table/TableFilter.java

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,6 @@ public void addFilterCondition(Expression condition, boolean isJoin) {
635635
*/
636636
public void addJoin(TableFilter filter, boolean outer, Expression on) {
637637
if (on != null) {
638-
on.mapColumns(this, 0, Expression.MAP_INITIAL);
639638
TableFilterVisitor visitor = new MapColumnsVisitor(on);
640639
visit(visitor);
641640
filter.visit(visitor);
@@ -647,7 +646,7 @@ public void addJoin(TableFilter filter, boolean outer, Expression on) {
647646
filter.visit(JOI_VISITOR);
648647
}
649648
if (on != null) {
650-
filter.mapAndAddFilter(on);
649+
filter.addFilter(on);
651650
}
652651
} else {
653652
join.addJoin(filter, outer, on);
@@ -664,18 +663,40 @@ public void setNestedJoin(TableFilter filter) {
664663
}
665664

666665
/**
667-
* Map the columns and add the join condition.
666+
* Add the join condition.
668667
*
669668
* @param on the condition
670669
*/
671-
public void mapAndAddFilter(Expression on) {
672-
on.mapColumns(this, 0, Expression.MAP_INITIAL);
670+
public void addFilter(Expression on) {
673671
addFilterCondition(on, true);
672+
if (join != null) {
673+
join.addFilter(on);
674+
}
675+
}
676+
677+
/**
678+
* Map the columns to the given column resolver.
679+
*
680+
* @param resolver
681+
* the resolver
682+
* @param level
683+
* the subquery level (0 is the top level query, 1 is the first
684+
* subquery level)
685+
* @param outer
686+
* whether this method was called from the outer query
687+
*/
688+
public void mapColumns(ColumnResolver resolver, int level, boolean outer) {
689+
if (!outer && joinOuter) {
690+
return;
691+
}
692+
if (joinCondition != null) {
693+
joinCondition.mapColumns(resolver, level, Expression.MAP_INITIAL);
694+
}
674695
if (nestedJoin != null) {
675-
on.mapColumns(nestedJoin, 0, Expression.MAP_INITIAL);
696+
nestedJoin.mapColumns(resolver, level, outer);
676697
}
677698
if (join != null) {
678-
join.mapAndAddFilter(on);
699+
join.mapColumns(resolver, level, outer);
679700
}
680701
}
681702

h2/src/test/org/h2/test/scripts/queries/joins.sql

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,3 +1044,55 @@ FROM (SELECT 1 A) X JOIN (
10441044
> - - -
10451045
> 1 1 1
10461046
> rows: 1
1047+
1048+
EXPLAIN
1049+
WITH TEST(ID) AS (VALUES 1)
1050+
SELECT * FROM TEST A INNER JOIN TEST B ON TRUE LEFT OUTER JOIN TEST C ON C.ID = A.ID;
1051+
> PLAN
1052+
> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1053+
> WITH "TEST"("ID") AS ( VALUES (1) ) SELECT "A"."ID", "B"."ID", "C"."ID" FROM "TEST" "A" /* VALUES (1) */ INNER JOIN "TEST" "B" /* VALUES (1) */ ON 1=1 LEFT OUTER JOIN "TEST" "C" /* VALUES (1) */ ON "C"."ID" = "A"."ID"
1054+
> rows: 1
1055+
1056+
-- Column A.ID cannot be referenced from this part of the query
1057+
EXPLAIN
1058+
WITH TEST(ID) AS (VALUES 1)
1059+
SELECT * FROM TEST A INNER JOIN TEST B LEFT OUTER JOIN TEST C ON C.ID = A.ID ON TRUE;
1060+
> exception COLUMN_NOT_FOUND_1
1061+
1062+
WITH
1063+
A(A) AS (VALUES (1)),
1064+
B(B) AS (VALUES (1)),
1065+
C(C) AS (VALUES (1))
1066+
SELECT
1067+
A.A,
1068+
(
1069+
SELECT B.B
1070+
FROM B
1071+
JOIN C
1072+
ON B.B = A.A
1073+
AND C.C = B.B
1074+
)
1075+
FROM A;
1076+
> A (SELECT B.B FROM B B INNER JOIN C C ON 1=1 WHERE (B.B = A.A) AND (C.C = B.B))
1077+
> - -----------------------------------------------------------------------------
1078+
> 1 1
1079+
> rows: 1
1080+
1081+
WITH
1082+
A(A) AS (VALUES (1)),
1083+
B(B) AS (VALUES (1)),
1084+
C(C) AS (VALUES (1))
1085+
SELECT
1086+
A.A,
1087+
(
1088+
SELECT B.B
1089+
FROM B
1090+
LEFT JOIN C
1091+
ON B.B = A.A
1092+
AND C.C = B.B
1093+
)
1094+
FROM A;
1095+
> A (SELECT B.B FROM B B LEFT OUTER JOIN C C ON (B.B = A.A) AND (C.C = B.B))
1096+
> - ------------------------------------------------------------------------
1097+
> 1 1
1098+
> rows: 1

0 commit comments

Comments
 (0)