Thread: Re: [HACKERS] DROP COLUMN round 4

Re: [HACKERS] DROP COLUMN round 4

From
"Christopher Kings-Lynne"
Date:
> "Christopher Kings-Lynne" <chriskl@familyhealth.com.au> writes:
> > 1. It cascade deletes objects, but it _always_ cascades, no matter what
> > behaviour I specify.  Also, it doesn't give me indications that
> it's cascade
> > deleted an object.
>
> Would you give a specific example?

test=# create table test (a int4, b int4);
CREATE TABLE
test=# create index temp on test (a);
CREATE INDEX
test=# \dt
        List of relations
 Name | Schema | Type  |  Owner
------+--------+-------+---------
 test | public | table | chriskl
(1 row)

test=# \di
            List of relations
 Name | Schema | Type  |  Owner  | Table
------+--------+-------+---------+-------
 temp | public | index | chriskl | test
(1 row)

test=# alter table test drop a restrict;
ALTER TABLE
test=# \di
No relations found.
test=#

> > + drop table child;
> > + ERROR:  RelationForgetRelation: relation 143905 is still open
>
> > What's with the RelationForgetRelation error???  Am I not closing some
> > handle somewhere?
>
> AlterTableDropColumn neglects to heap_close the relation, but I'm
> surprised that error isn't reported sooner.

Fixed.  New diff attached - fixes regression tests as well, plus re-merged
against HEAD.

Note that the check against the parent attribute when adding a foreign key
probably should be improved.  ie. It relies on the fact that the parent
column(s) should not have a unique index on them (thanks to dependencies),
rather than actually checking the attisdropped attribute.

Chris

Attachment

Re: [HACKERS] DROP COLUMN round 4

From
Tom Lane
Date:
"Christopher Kings-Lynne" <chriskl@familyhealth.com.au> writes:
> 1. It cascade deletes objects, but it _always_ cascades, no matter what
> behaviour I specify.  Also, it doesn't give me indications that
> it's cascade deleted an object.
>>
>> Would you give a specific example?

> [ dropping a column silently drops an index on the column ]

This happens because indexes are marked DEPENDENCY_AUTO on their
columns.  The drop will cascade to the index even under RESTRICT;
if you have message level set to DEBUG1 or higher you'll be told
about it, but otherwise the behavior is to zap the index quietly.

An example of a case where RESTRICT should make a difference is
where you have a foreign key reference from another table, or
a view that uses the column you're trying to delete.

We can debate whether indexes ought to be AUTO dependencies or not.
It seems reasonable to me though.  Indexes aren't really independent
objects to my mind, only auxiliary thingummies...

>> AlterTableDropColumn neglects to heap_close the relation, but I'm
>> surprised that error isn't reported sooner.

> Fixed.  New diff attached - fixes regression tests as well, plus re-merged
> against HEAD.

Thanks, will work from this.

> Note that the check against the parent attribute when adding a foreign key
> probably should be improved.  ie. It relies on the fact that the parent
> column(s) should not have a unique index on them (thanks to dependencies),
> rather than actually checking the attisdropped attribute.

Uh ... maybe it's too late at night here, but I didn't follow.

            regards, tom lane

Re: [HACKERS] DROP COLUMN round 4

From
"Christopher Kings-Lynne"
Date:
> This happens because indexes are marked DEPENDENCY_AUTO on their
> columns.  The drop will cascade to the index even under RESTRICT;
> if you have message level set to DEBUG1 or higher you'll be told
> about it, but otherwise the behavior is to zap the index quietly.

Ah doh.  I knew that as well.  I'll try a view or something then...

> > Note that the check against the parent attribute when adding a
> foreign key
> > probably should be improved.  ie. It relies on the fact that the parent
> > column(s) should not have a unique index on them (thanks to
> dependencies),
> > rather than actually checking the attisdropped attribute.

OK, in this statement:

ALTER TABLE child ADD FOREIGN KEY (a) REFERENCES parent(b);

It does not check that column b is not dropped (it does check "a").  It just
relies on the UNIQUE constraint not being present on b.  This should
probably be fixed...

Chris


Re: [HACKERS] DROP COLUMN round 4

From
Tom Lane
Date:
"Christopher Kings-Lynne" <chriskl@familyhealth.com.au> writes:
> Fixed.  New diff attached - fixes regression tests as well, plus re-merged
> against HEAD.

I've applied this patch after some editorializing.  Notably, I went
ahead and created syscache lookup convenience routines

extern HeapTuple SearchSysCacheAttName(Oid relid, const char *attname);
extern HeapTuple SearchSysCacheCopyAttName(Oid relid, const char *attname);
extern bool SearchSysCacheExistsAttName(Oid relid, const char *attname);

These are equivalent to the corresponding basic syscache routines for
the ATTNAME cache, except that they will release the cache entry and
return NULL (or false, etc) if the entry exists but has attisdropped =
true.

Essentially all uses of the ATTNAME cache should now go through these
routines instead.  This cleans up a number of cases in which the patch
as-submitted produced rather bogus error messages.

I did not adopt the approach of inserting NULLs in eref lists, because
I'm afraid that will break code elsewhere that relies on eref lists.
Instead I added a post-facto check to scanRTEforColumn, which is simple
and reliable.

Also, I'm still unconvinced that there's any percentage in modifying the
name of a deleted column to avoid collisions, since it does nothing for
after-the-fact collisions; AFAICT the net result is just to *enlarge*
the set of column names that users have to avoid.  So I took that code
out.  A possible solution that would actually work is to replace
pg_attribute's unique index on (attrelid, attname) with one on
(attrelid, attname, attisdropped).  However, I doubt that the problem is
worth the overhead that that would add.  I'm inclined to leave the code
as it stands and just document that column names like
"........pg.dropped.N........" are best avoided.


There are still issues about functions that accept or return tuple
datatypes --- a DROP COLUMN is likely to break any functions that use
the table's tuple datatype.  Related problems occur already with ADD
COLUMN, though, so I did not think this was a reason to reject the
patch.

            regards, tom lane

Re: [HACKERS] DROP COLUMN round 4

From
Tom Lane
Date:
"Christopher Kings-Lynne" <chriskl@familyhealth.com.au> writes:
> OK, in this statement:

> ALTER TABLE child ADD FOREIGN KEY (a) REFERENCES parent(b);

> It does not check that column b is not dropped (it does check "a").  It just
> relies on the UNIQUE constraint not being present on b.  This should
> probably be fixed...

This is not really a case of it "relies on" that, it's just that the
check for a key is done before trying to resolve the column names to
numbers, so you get that error first.  I'm not sure it's worth trying to
rearrange the code in analyze.c to avoid that.  In the self-referential
case,

    create table foo (id int primary key,
              parent int references foo);

you more or less have to work with column names not numbers.

            regards, tom lane