Re: Rel 7.0beta5: view on table* crashes backend

Started by Bruce Momjianalmost 26 years ago1 messageshackers
Jump to latest
#1Bruce Momjian
bruce@momjian.us

This has been fixed in 7.0.

"Oliver Elphick" <olly@lfix.co.uk> writes:

The following commands invariably crash the backend:
morejunk=# create table test_t(id int4);
CREATE
morejunk=# create table test_d() inherits(test_t);
CREATE
morejunk=# create view test_v as select * from test_t*;
CREATE 135069 1
morejunk=# select * from test_v;
pqReadData() -- backend closed the channel unexpectedly.
This probably means the backend terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.

The problem appears to be in this routine in optimizer/prep/prepunion.c:

static RangeTblEntry *
new_rangetable_entry(Oid new_relid, RangeTblEntry *old_entry)
{
RangeTblEntry *new_entry = copyObject(old_entry);

/* ??? someone tell me what the following is doing! - ay 11/94 */
if (!strcmp(new_entry->eref->relname, "*CURRENT*") ||
!strcmp(new_entry->eref->relname, "*NEW*"))
new_entry->ref->relname = get_rel_name(new_relid);
else
new_entry->relname = get_rel_name(new_relid);

new_entry->relid = new_relid;
return new_entry;
}

It bombs on a RangeTblEntry that's been inserted by rule expansion,
because the entry's eref is NULL. The reason it's NULL is that we
deliberately decided not to save eref data in stored rule strings.
So RTEs coming from rule expansion have NULL eref fields.

This routine is the only one outside the parser that makes use of
eref as opposed to ref in RTEs. I am thinking we can fix the problem
by making it look at ref->relname instead of eref->relname. But I'd
like to get Thomas to look at the issue, since according to the CVS
logs he was the one who changed it from ref->relname to eref->relname
in the first place. Thomas, is there a semantic difference between
ref->relname and eref->relname?

Wait a minute ... now that I look at it, it's arguable that the entire
chunk of code is misguided in the first place. What we're doing is
making an RTE point at some inheritance child of a table that was named
(with *) in the original query. It seems to me that we should leave the
ref name alone and substitute for the true relation name regardless of
whether the ref name is *CURRENT* or not. That is, if you write
... FROM foo* ref
then the reference name ref applies to all of foo's children as well as
foo. I don't see why it would be different inside a view. In other
words the code probably should just be

new_entry->relname = get_rel_name(new_relid);
new_entry->relid = new_relid;
return new_entry;

Jan, Thomas, any comments?

regards, tom lane

-- 
  Bruce Momjian                        |  http://www.op.net/~candle
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026