Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb4def32

Browse files
author
Thomas G. Lockhart
committed
Include some new code for outer joins. Disabled by default, but enable by
including the following in your Makefile.custom: CFLAGS+= -DENABLE_OUTER_JOINS -DEXEC_MERGEJOINDEBUG
1 parent449020f commitb4def32

File tree

1 file changed

+222
-20
lines changed

1 file changed

+222
-20
lines changed

‎src/backend/parser/parse_clause.c

Lines changed: 222 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.28 1999/02/13 23:17:07 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.29 1999/02/23 07:46:42 thomas Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -26,7 +26,9 @@
2626
#include"parser/parse_relation.h"
2727
#include"parser/parse_target.h"
2828
#include"parser/parse_coerce.h"
29+
#include"nodes/print.h"
2930

31+
#include"parse.h"
3032

3133

3234
#defineORDER_CLAUSE 0
@@ -37,7 +39,15 @@ static char *clauseText[] = {"ORDER", "GROUP"};
3739
staticTargetEntry*
3840
findTargetlistEntry(ParseState*pstate,Node*node,List*tlist,intclause);
3941

40-
staticvoidparseFromClause(ParseState*pstate,List*frmList);
42+
staticvoidparseFromClause(ParseState*pstate,List*frmList,Node**qual);
43+
44+
Attr*makeAttr(char*relname,char*attname);
45+
46+
#ifdefENABLE_OUTER_JOINS
47+
Node*transformUsingClause(ParseState*pstate,List*onList,char*lname,char*rname);
48+
#endif
49+
50+
char*transformTableEntry(ParseState*pstate,RangeVar*r);
4151

4252

4353
/*
@@ -46,18 +56,18 @@ static void parseFromClause(ParseState *pstate, List *frmList);
4656
* from_clause.
4757
*/
4858
void
49-
makeRangeTable(ParseState*pstate,char*relname,List*frmList)
59+
makeRangeTable(ParseState*pstate,char*relname,List*frmList,Node**qual)
5060
{
5161
RangeTblEntry*rte;
5262
intsublevels_up;
5363

54-
parseFromClause(pstate,frmList);
64+
parseFromClause(pstate,frmList,qual);
5565

5666
if (relname==NULL)
5767
return;
5868

59-
if (refnameRangeTablePosn(pstate,relname,&sublevels_up)==0||
60-
sublevels_up!=0)
69+
if ((refnameRangeTablePosn(pstate,relname,&sublevels_up)==0)
70+
|| (sublevels_up!=0))
6171
rte=addRangeTableEntry(pstate,relname,relname, FALSE, FALSE);
6272
else
6373
rte=refnameRangeTableEntry(pstate,relname);
@@ -77,17 +87,35 @@ makeRangeTable(ParseState *pstate, char *relname, List *frmList)
7787
* transformWhereClause -
7888
* transforms the qualification and make sure it is of type Boolean
7989
*
90+
* Now accept an additional argument, which is a qualification derived
91+
* from the JOIN/ON or JOIN/USING syntax.
92+
* - thomas 1998-12-16
8093
*/
8194
Node*
82-
transformWhereClause(ParseState*pstate,Node*a_expr)
95+
transformWhereClause(ParseState*pstate,Node*a_expr,Node*o_expr)
8396
{
97+
A_Expr*expr;
8498
Node*qual;
8599

86-
if (a_expr==NULL)
100+
if ((a_expr==NULL)&& (o_expr==NULL))
87101
returnNULL;/* no qualifiers */
88102

103+
if ((a_expr!=NULL)&& (o_expr!=NULL))
104+
{
105+
A_Expr*a=makeNode(A_Expr);
106+
a->oper=AND;
107+
a->opname=NULL;
108+
a->lexpr=o_expr;
109+
a->rexpr=a_expr;
110+
expr=a;
111+
}
112+
elseif (o_expr!=NULL)
113+
expr= (A_Expr*)o_expr;
114+
else
115+
expr= (A_Expr*)a_expr;
116+
89117
pstate->p_in_where_clause= true;
90-
qual=transformExpr(pstate,a_expr,EXPR_COLUMN_FIRST);
118+
qual=transformExpr(pstate,(Node*)expr,EXPR_COLUMN_FIRST);
91119
pstate->p_in_where_clause= false;
92120

93121
if (exprType(qual)!=BOOLOID)
@@ -98,6 +126,122 @@ transformWhereClause(ParseState *pstate, Node *a_expr)
98126
returnqual;
99127
}
100128

129+
Attr*
130+
makeAttr(char*relname,char*attname)
131+
{
132+
Attr*a=makeNode(Attr);
133+
a->relname=relname;
134+
a->paramNo=NULL;
135+
a->attrs=lcons(makeString(attname),NIL);
136+
a->indirection=NULL;
137+
138+
returna;
139+
}
140+
141+
#ifdefENABLE_OUTER_JOINS
142+
/* transformUsingClause()
143+
* Take an ON or USING clause from a join expression and expand if necessary.
144+
*/
145+
Node*
146+
transformUsingClause(ParseState*pstate,List*onList,char*lname,char*rname)
147+
{
148+
A_Expr*expr=NULL;
149+
List*on;
150+
Node*qual;
151+
152+
foreach (on,onList)
153+
{
154+
qual=lfirst(on);
155+
156+
/* Ident node means it is just a column name from a real USING clause... */
157+
if (IsA(qual,Ident))
158+
{
159+
Ident*i= (Ident*)qual;
160+
Attr*lattr=makeAttr(lname,i->name);
161+
Attr*rattr=makeAttr(rname,i->name);
162+
A_Expr*e=makeNode(A_Expr);
163+
164+
#ifdefPARSEDEBUG
165+
printf("transformUsingClause- transform %s",nodeToString(i));
166+
#endif
167+
168+
e->oper=OP;
169+
e->opname="=";
170+
e->lexpr= (Node*)lattr;
171+
e->rexpr= (Node*)rattr;
172+
173+
if (expr!=NULL)
174+
{
175+
A_Expr*a=makeNode(A_Expr);
176+
a->oper=AND;
177+
a->opname=NULL;
178+
a->lexpr= (Node*)expr;
179+
a->rexpr= (Node*)e;
180+
expr=a;
181+
}
182+
else
183+
expr=e;
184+
}
185+
186+
/* otherwise, we have an expression from an ON clause... */
187+
else
188+
{
189+
if (expr!=NULL)
190+
{
191+
A_Expr*a=makeNode(A_Expr);
192+
a->oper=AND;
193+
a->opname=NULL;
194+
a->lexpr= (Node*)expr;
195+
a->rexpr= (Node*)qual;
196+
expr=a;
197+
}
198+
else
199+
{
200+
expr= (A_Expr*)qual;
201+
}
202+
203+
#ifdefPARSEDEBUG
204+
printf("transformUsingClause- transform %s",nodeToString(qual));
205+
#endif
206+
207+
}
208+
209+
#ifdefPARSEDEBUG
210+
printf(" to %s\n",nodeToString(expr));
211+
#endif
212+
}
213+
return ((Node*)transformExpr(pstate, (Node*)expr,EXPR_COLUMN_FIRST));
214+
}
215+
#endif
216+
217+
char*
218+
transformTableEntry(ParseState*pstate,RangeVar*r)
219+
{
220+
RelExpr*baserel=r->relExpr;
221+
char*relname=baserel->relname;
222+
char*refname=r->name;
223+
RangeTblEntry*rte;
224+
225+
if (refname==NULL)
226+
refname=relname;
227+
228+
/*
229+
* marks this entry to indicate it comes from the FROM clause. In
230+
* SQL, the target list can only refer to range variables
231+
* specified in the from clause but we follow the more powerful
232+
* POSTQUEL semantics and automatically generate the range
233+
* variable if not specified. However there are times we need to
234+
* know whether the entries are legitimate.
235+
*
236+
* eg. select * from foo f where f.x = 1; will generate wrong answer
237+
* if we expand * to foo.x.
238+
*/
239+
240+
rte=addRangeTableEntry(pstate,relname,refname,baserel->inh, TRUE);
241+
242+
returnrefname;
243+
}
244+
101245
/*
102246
* parseFromClause -
103247
* turns the table references specified in the from-clause into a
@@ -106,23 +250,23 @@ transformWhereClause(ParseState *pstate, Node *a_expr)
106250
* allow references to relations not specified in the from-clause. We
107251
* also allow now as an extension.)
108252
*
253+
* The FROM clause can now contain JoinExpr nodes, which contain parsing info
254+
* for inner and outer joins. The USING clause must be expanded into a qualification
255+
* for an inner join at least, since that is compatible with the old syntax.
256+
* Not sure yet how to handle outer joins, but it will become clear eventually?
257+
* - thomas 1998-12-16
109258
*/
110259
staticvoid
111-
parseFromClause(ParseState*pstate,List*frmList)
260+
parseFromClause(ParseState*pstate,List*frmList,Node**qual)
112261
{
113262
List*fl;
114263

264+
if (qual!=NULL)
265+
*qual=NULL;
266+
115267
foreach(fl,frmList)
116268
{
117-
RangeVar*r=lfirst(fl);
118-
RelExpr*baserel=r->relExpr;
119-
char*relname=baserel->relname;
120-
char*refname=r->name;
121-
RangeTblEntry*rte;
122-
123-
if (refname==NULL)
124-
refname=relname;
125-
269+
Node*n=lfirst(fl);
126270
/*
127271
* marks this entry to indicate it comes from the FROM clause. In
128272
* SQL, the target list can only refer to range variables
@@ -134,7 +278,65 @@ parseFromClause(ParseState *pstate, List *frmList)
134278
* eg. select * from foo f where f.x = 1; will generate wrong answer
135279
* if we expand * to foo.x.
136280
*/
137-
rte=addRangeTableEntry(pstate,relname,refname,baserel->inh, TRUE);
281+
if (IsA(n,RangeVar))
282+
{
283+
transformTableEntry(pstate, (RangeVar*)n);
284+
}
285+
elseif (IsA(n,JoinExpr))
286+
{
287+
JoinExpr*j= (JoinExpr*)n;
288+
char*lname=transformTableEntry(pstate, (RangeVar*)j->larg);
289+
char*rname;
290+
291+
if (IsA((Node*)j->rarg,RangeVar))
292+
rname=transformTableEntry(pstate, (RangeVar*)j->rarg);
293+
else
294+
elog(ERROR,"Nested JOINs are not yet supported");
295+
296+
#ifdefENABLE_OUTER_JOINS
297+
if (j->jointype==INNER_P)
298+
{
299+
/* This is an inner join, so rip apart the join node
300+
* and transform into a traditional FROM list.
301+
* NATURAL JOIN and USING clauses both change the shape
302+
* of the result. Need to generate a list of result columns
303+
* to use for target list expansion and validation.
304+
* Not doing this yet though!
305+
*/
306+
if (IsA(j->quals,List))
307+
j->quals=lcons(transformUsingClause(pstate, (List*)j->quals,lname,rname),NIL);
308+
309+
Assert(qual!=NULL);
310+
311+
if (*qual==NULL)
312+
*qual=lfirst(j->quals);
313+
else
314+
elog(ERROR,"Multiple JOIN/ON clauses not handled (internal error)");
315+
316+
/* if we are transforming this node back into a FROM list,
317+
* then we will need to replace the node with two nodes.
318+
* Will need access to the previous list item to change
319+
* the link pointer to reference these new nodes.
320+
* Try accumulating and returning a new list.
321+
* - thomas 1999-01-08
322+
* Not doing this yet though!
323+
*/
324+
325+
}
326+
elseif ((j->jointype==LEFT)
327+
|| (j->jointype==RIGHT)
328+
|| (j->jointype==FULL))
329+
elog(ERROR,"OUTER JOIN is not implemented");
330+
else
331+
elog(ERROR,"Unrecognized JOIN clause; tag is %d (internal error)",
332+
j->jointype);
333+
#else
334+
elog(ERROR,"JOIN expressions are not yet implemented");
335+
#endif
336+
}
337+
else
338+
elog(ERROR,"parseFromClause: unexpected FROM clause node (internal error)"
339+
"\n\t%s",nodeToString(n));
138340
}
139341
}
140342

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp