Skip to content

Commit 01911c9

Browse files
committed
Repair list-vs-node confusion that resulted in failure for INNER JOIN ON.
Make it behave correctly when there are more than two tables being joined, also. Update regression test expected outputs.
1 parent 4624b84 commit 01911c9

File tree

3 files changed

+75
-58
lines changed

3 files changed

+75
-58
lines changed

src/backend/parser/parse_clause.c

Lines changed: 45 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.59 2000/04/12 17:15:26 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.60 2000/05/12 01:33:54 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -41,8 +41,8 @@ static List *addTargetToSortList(TargetEntry *tle, List *sortlist,
4141
static bool exprIsInSortList(Node *expr, List *sortList, List *targetList);
4242

4343
#ifndef DISABLE_OUTER_JOINS
44-
static Node *transformUsingClause(ParseState *pstate, List *using, List *left, List *right);
45-
44+
static List *transformUsingClause(ParseState *pstate, List *using,
45+
List *left, List *right);
4646
#endif
4747

4848

@@ -94,32 +94,33 @@ setTargetTable(ParseState *pstate, char *relname)
9494
}
9595

9696

97-
Node *
98-
mergeInnerJoinQuals(ParseState *pstate, Node *clause);
99-
100-
Node *
97+
static Node *
10198
mergeInnerJoinQuals(ParseState *pstate, Node *clause)
10299
{
103-
A_Expr *expr = (A_Expr *) pstate->p_join_quals;
100+
List *jquals;
104101

105-
if (expr == NULL)
106-
return clause;
107-
108-
if (clause != NULL)
102+
foreach(jquals, pstate->p_join_quals)
109103
{
110-
A_Expr *a = makeNode(A_Expr);
104+
Node *jqual = (Node *) lfirst(jquals);
105+
106+
if (clause == NULL)
107+
clause = jqual;
108+
else
109+
{
110+
A_Expr *a = makeNode(A_Expr);
111111

112-
a->oper = AND;
113-
a->opname = NULL;
114-
a->lexpr = (Node *) expr;
115-
a->rexpr = clause;
116-
expr = a;
112+
a->oper = AND;
113+
a->opname = NULL;
114+
a->lexpr = clause;
115+
a->rexpr = jqual;
116+
clause = (Node *) a;
117+
}
117118
}
118119

119-
/* Make sure that we don't do this twice... */
120-
pstate->p_join_quals = NULL;
120+
/* Make sure that we don't add same quals twice... */
121+
pstate->p_join_quals = NIL;
121122

122-
return (Node *) expr;
123+
return clause;
123124
} /* mergeInnerJoinQuals() */
124125

125126
/*
@@ -131,7 +132,7 @@ transformWhereClause(ParseState *pstate, Node *clause)
131132
{
132133
Node *qual;
133134

134-
if (pstate->p_join_quals != NULL)
135+
if (pstate->p_join_quals != NIL)
135136
clause = mergeInnerJoinQuals(pstate, clause);
136137

137138
if (clause == NULL)
@@ -275,21 +276,22 @@ ExpandAttrs(Attr *attr)
275276

276277
/* transformUsingClause()
277278
* Take an ON or USING clause from a join expression and expand if necessary.
279+
* Result is an implicitly-ANDed list of untransformed qualification clauses.
278280
*/
279-
static Node *
280-
transformUsingClause(ParseState *pstate, List *usingList, List *leftList, List *rightList)
281+
static List *
282+
transformUsingClause(ParseState *pstate, List *usingList,
283+
List *leftList, List *rightList)
281284
{
282-
A_Expr *expr = NULL;
285+
List *result = NIL;
283286
List *using;
284287

285288
foreach(using, usingList)
286289
{
287-
List *col;
288-
A_Expr *e;
289-
290290
Attr *uattr = lfirst(using);
291291
Attr *lattr = NULL,
292292
*rattr = NULL;
293+
List *col;
294+
A_Expr *e;
293295

294296
/*
295297
* find the first instances of this column in the shape list and
@@ -324,22 +326,11 @@ transformUsingClause(ParseState *pstate, List *usingList, List *leftList, List *
324326
e->lexpr = (Node *) lattr;
325327
e->rexpr = (Node *) rattr;
326328

327-
if (expr != NULL)
328-
{
329-
A_Expr *a = makeNode(A_Expr);
330-
331-
a->oper = AND;
332-
a->opname = NULL;
333-
a->lexpr = (Node *) expr;
334-
a->rexpr = (Node *) e;
335-
expr = a;
336-
}
337-
else
338-
expr = e;
329+
result = lappend(result, e);
339330
}
340331

341-
return ((Node *) transformExpr(pstate, (Node *) expr, EXPR_COLUMN_FIRST));
342-
} /* transformUsiongClause() */
332+
return result;
333+
} /* transformUsingClause() */
343334

344335
#endif
345336

@@ -632,7 +623,7 @@ parseFromClause(ParseState *pstate, List *frmList)
632623

633624
printf("JOIN/USING input quals are %s\n", nodeToString(j->quals));
634625

635-
j->quals = (List *) transformUsingClause(pstate, shape, l_cols, r_cols);
626+
j->quals = transformUsingClause(pstate, shape, l_cols, r_cols);
636627

637628
printf("JOIN/USING transformed quals are %s\n", nodeToString(j->quals));
638629

@@ -650,7 +641,12 @@ parseFromClause(ParseState *pstate, List *frmList)
650641
else
651642
j->quals = (List *) lcons(j->quals, NIL);
652643

653-
pstate->p_join_quals = (Node *) j->quals;
644+
/* listCopy may not be needed here --- will j->quals list
645+
* be used again anywhere? The #ifdef'd code below may need
646+
* it, if it ever gets used...
647+
*/
648+
pstate->p_join_quals = nconc(pstate->p_join_quals,
649+
listCopy(j->quals));
654650

655651
#if 0
656652
if (qual == NULL)
@@ -660,11 +656,13 @@ parseFromClause(ParseState *pstate, List *frmList)
660656
#endif
661657

662658
#if 0
659+
/* XXX this code is WRONG because j->quals is a List
660+
* not a simple expression. Perhaps *qual
661+
* ought also to be a List and we append to it,
662+
* similarly to the way p_join_quals is handled above?
663+
*/
663664
if (*qual == NULL)
664665
{
665-
#endif
666-
667-
#if 0
668666
/* merge qualified join clauses... */
669667
if (j->quals != NULL)
670668
{
@@ -682,9 +680,6 @@ parseFromClause(ParseState *pstate, List *frmList)
682680
else
683681
*qual = (Node *) j->quals;
684682
}
685-
#endif
686-
687-
#if 0
688683
}
689684
else
690685
{

src/include/parser/parse_node.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: parse_node.h,v 1.19 2000/04/12 17:16:45 momjian Exp $
9+
* $Id: parse_node.h,v 1.20 2000/05/12 01:33:52 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -17,9 +17,10 @@
1717
#include "utils/rel.h"
1818

1919
/* State information used during parse analysis
20-
* p_join_quals is a list of qualification expressions
21-
* found in the FROM clause. Needs to be available later
22-
* to merge with other qualifiers from the WHERE clause.
20+
* p_join_quals is a list of untransformed qualification expressions
21+
* (implicitly ANDed together) found in the FROM clause.
22+
* Needs to be available later to merge with other qualifiers from the
23+
* WHERE clause.
2324
*/
2425
typedef struct ParseState
2526
{
@@ -36,7 +37,7 @@ typedef struct ParseState
3637
RangeTblEntry *p_target_rangetblentry;
3738
List *p_shape;
3839
List *p_alias;
39-
Node *p_join_quals;
40+
List *p_join_quals;
4041
} ParseState;
4142

4243
extern ParseState *make_parsestate(ParseState *parentParseState);

src/test/regress/expected/join.out

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,22 @@ SELECT '' AS "xxx", *
274274
--
275275
SELECT '' AS "xxx", *
276276
FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.i);
277-
ERROR: transformExpr: does not know how to transform node 501 (internal error)
277+
xxx | i | j | t | i | k
278+
-----+---+---+-------+---+----
279+
| 1 | 3 | one | 1 | -1
280+
| 2 | 2 | two | 2 | 2
281+
| 2 | 2 | two | 2 | 4
282+
| 3 | 1 | three | 3 | -3
283+
(4 rows)
284+
278285
SELECT '' AS "xxx", *
279286
FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.k);
280-
ERROR: transformExpr: does not know how to transform node 501 (internal error)
287+
xxx | i | j | t | i | k
288+
-----+---+---+------+---+---
289+
| 2 | 2 | two | 2 | 2
290+
| 4 | 0 | four | 2 | 4
291+
(2 rows)
292+
281293
SELECT '' AS "xxx", *
282294
FROM J1_TBL CROSS JOIN J2_TBL;
283295
xxx | i | j | t | i | k
@@ -305,7 +317,16 @@ SELECT '' AS "xxx", *
305317
--
306318
SELECT '' AS "xxx", *
307319
FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i <= J2_TBL.k);
308-
ERROR: transformExpr: does not know how to transform node 501 (internal error)
320+
xxx | i | j | t | i | k
321+
-----+---+---+-------+---+---
322+
| 1 | 3 | one | 2 | 2
323+
| 2 | 2 | two | 2 | 2
324+
| 1 | 3 | one | 2 | 4
325+
| 2 | 2 | two | 2 | 4
326+
| 3 | 1 | three | 2 | 4
327+
| 4 | 0 | four | 2 | 4
328+
(6 rows)
329+
309330
--
310331
-- Outer joins
311332
--

0 commit comments

Comments
 (0)