Skip to content

Commit 3eb1c82

Browse files
committed
Fix planner and rewriter to follow SQL semantics for tables that are
mentioned in FROM but not elsewhere in the query: such tables should be joined over anyway. Aside from being more standards-compliant, this allows removal of some very ugly hacks for COUNT(*) processing. Also, allow HAVING clause without aggregate functions, since SQL does. Clean up CREATE RULE statement-list syntax the same way Bruce just fixed the main stmtmulti production. CAUTION: addition of a field to RangeTblEntry nodes breaks stored rules; you will have to initdb if you have any rules.
1 parent 4040fcf commit 3eb1c82

File tree

21 files changed

+398
-380
lines changed

21 files changed

+398
-380
lines changed

src/backend/commands/view.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright (c) 1994, Regents of the University of California
77
*
8-
* $Id: view.c,v 1.38 1999/10/03 23:55:27 tgl Exp $
8+
* $Id: view.c,v 1.39 1999/10/07 04:23:00 tgl Exp $
99
*
1010
*-------------------------------------------------------------------------
1111
*/
@@ -225,9 +225,9 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
225225
* table... CURRENT first, then NEW....
226226
*/
227227
rt_entry1 = addRangeTableEntry(NULL, (char *) viewName, "*CURRENT*",
228-
FALSE, FALSE);
228+
FALSE, FALSE, FALSE);
229229
rt_entry2 = addRangeTableEntry(NULL, (char *) viewName, "*NEW*",
230-
FALSE, FALSE);
230+
FALSE, FALSE, FALSE);
231231
new_rt = lcons(rt_entry2, old_rt);
232232
new_rt = lcons(rt_entry1, new_rt);
233233

src/backend/executor/execMain.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.96 1999/09/29 16:06:02 wieck Exp $
29+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.97 1999/10/07 04:23:01 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -1514,8 +1514,7 @@ ExecRelCheck(Relation rel, HeapTuple tuple, EState *estate)
15141514
rte->relname = nameout(&(rel->rd_rel->relname));
15151515
rte->refname = rte->relname;
15161516
rte->relid = RelationGetRelid(rel);
1517-
rte->inh = false;
1518-
rte->inFromCl = true;
1517+
/* inh, inFromCl, inJoinSet, skipAcl won't be used, leave them zero */
15191518
rtlist = lcons(rte, NIL);
15201519
econtext->ecxt_scantuple = slot; /* scan tuple slot */
15211520
econtext->ecxt_innertuple = NULL; /* inner tuple slot */

src/backend/nodes/copyfuncs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.92 1999/08/21 03:48:57 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.93 1999/10/07 04:23:03 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -1316,9 +1316,9 @@ _copyRangeTblEntry(RangeTblEntry *from)
13161316
newnode->relid = from->relid;
13171317
newnode->inh = from->inh;
13181318
newnode->inFromCl = from->inFromCl;
1319+
newnode->inJoinSet = from->inJoinSet;
13191320
newnode->skipAcl = from->skipAcl;
13201321

1321-
13221322
return newnode;
13231323
}
13241324

src/backend/nodes/equalfuncs.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.49 1999/09/26 02:28:21 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.50 1999/10/07 04:23:04 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -597,6 +597,8 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
597597
return false;
598598
if (a->inFromCl != b->inFromCl)
599599
return false;
600+
if (a->inJoinSet != b->inJoinSet)
601+
return false;
600602
if (a->skipAcl != b->skipAcl)
601603
return false;
602604

src/backend/nodes/outfuncs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright (c) 1994, Regents of the University of California
77
*
8-
* $Id: outfuncs.c,v 1.96 1999/10/03 23:55:29 tgl Exp $
8+
* $Id: outfuncs.c,v 1.97 1999/10/07 04:23:04 tgl Exp $
99
*
1010
* NOTES
1111
* Every (plan) node in POSTGRES has an associated "out" routine which
@@ -864,12 +864,13 @@ static void
864864
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
865865
{
866866
appendStringInfo(str,
867-
" RTE :relname %s :refname %s :relid %u :inh %s :inFromCl %s :skipAcl %s",
867+
" RTE :relname %s :refname %s :relid %u :inh %s :inFromCl %s :inJoinSet %s :skipAcl %s",
868868
stringStringInfo(node->relname),
869869
stringStringInfo(node->refname),
870870
node->relid,
871871
node->inh ? "true" : "false",
872872
node->inFromCl ? "true" : "false",
873+
node->inJoinSet ? "true" : "false",
873874
node->skipAcl ? "true" : "false");
874875
}
875876

src/backend/nodes/readfuncs.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.73 1999/08/21 03:48:58 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.74 1999/10/07 04:23:04 tgl Exp $
1111
*
1212
* NOTES
1313
* Most of the read functions for plan nodes are tested. (In fact, they
@@ -1380,6 +1380,10 @@ _readRangeTblEntry()
13801380
token = lsptok(NULL, &length); /* get :inFromCl */
13811381
local_node->inFromCl = (token[0] == 't') ? true : false;
13821382

1383+
token = lsptok(NULL, &length); /* eat :inJoinSet */
1384+
token = lsptok(NULL, &length); /* get :inJoinSet */
1385+
local_node->inJoinSet = (token[0] == 't') ? true : false;
1386+
13831387
token = lsptok(NULL, &length); /* eat :skipAcl */
13841388
token = lsptok(NULL, &length); /* get :skipAcl */
13851389
local_node->skipAcl = (token[0] == 't') ? true : false;

src/backend/optimizer/plan/initsplan.c

Lines changed: 26 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/optimizer/plan/initsplan.c,v 1.39 1999/08/26 05:07:41 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.40 1999/10/07 04:23:06 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -77,37 +77,43 @@ add_vars_to_targetlist(Query *root, List *vars)
7777
}
7878

7979
/*
80-
* add_missing_vars_to_tlist
81-
* If we have range variable(s) in the FROM clause that does not appear
82-
* in the target list nor qualifications, we add it to the base relation
83-
* list. For instance, "select f.x from foo f, foo f2" is a join of f and
84-
* f2. Note that if we have "select foo.x from foo f", it also gets turned
85-
* into a join.
80+
* add_missing_rels_to_query
81+
*
82+
* If we have a range variable in the FROM clause that does not appear
83+
* in the target list nor qualifications, we must add it to the base
84+
* relation list so that it will be joined. For instance, "select f.x
85+
* from foo f, foo f2" is a join of f and f2. Note that if we have
86+
* "select foo.x from foo f", it also gets turned into a join (between
87+
* foo as foo and foo as f).
88+
*
89+
* To avoid putting useless entries into the per-relation targetlists,
90+
* this should only be called after all the variables in the targetlist
91+
* and quals have been processed by the routines above.
8692
*/
8793
void
88-
add_missing_vars_to_tlist(Query *root, List *tlist)
94+
add_missing_rels_to_query(Query *root)
8995
{
9096
int varno = 1;
9197
List *l;
9298

9399
foreach(l, root->rtable)
94100
{
95101
RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
96-
Relids relids;
97102

98-
relids = lconsi(varno, NIL);
99-
if (rte->inFromCl && !rel_member(relids, root->base_rel_list))
103+
if (rte->inJoinSet)
100104
{
101-
RelOptInfo *rel;
102-
Var *var;
103-
104-
/* add it to base_rel_list */
105-
rel = get_base_rel(root, varno);
106-
/* give it a dummy tlist entry for its OID */
107-
var = makeVar(varno, ObjectIdAttributeNumber, OIDOID, -1, 0);
108-
add_var_to_tlist(rel, var);
105+
RelOptInfo *rel = get_base_rel(root, varno);
106+
107+
/* If the rel isn't otherwise referenced, give it a dummy
108+
* targetlist consisting of its own OID.
109+
*/
110+
if (rel->targetlist == NIL)
111+
{
112+
Var *var = makeVar(varno, ObjectIdAttributeNumber,
113+
OIDOID, -1, 0);
114+
add_var_to_tlist(rel, var);
115+
}
109116
}
110-
pfree(relids);
111117
varno++;
112118
}
113119
}

0 commit comments

Comments
 (0)