Обсуждение: Re: [HACKERS] [GENERAL] Column rename in an extension update script

Поиск
Список
Период
Сортировка

Re: [HACKERS] [GENERAL] Column rename in an extension update script

От
Julien Rouhaud
Дата:
moving this thread to -hackers, since this looks like a bug.

On 01/05/2017 08:54, Philippe BEAUDOIN wrote:
> Hi all,
> 
> I am coding an update script for an extension. And I am in trouble when
> trying to rename a column of an existing table.
> 
> Just after the ALTER TABLE statement, I want to access this table. But
> at this time, the altered column is not visible with its new name.
> 

I can reproduce this issue.

It looks like this is due to missing cache invalidation between the
ALTER TABLE execution and next query planning (failure happens during
pg_analyze_and_rewrite()).

AFAICT, CommandCounterIncrement() is responsible for handling
invalidation messages, but in execute_sql_string() this function is
called before executing a Stmt instead of after.  Moving the
CommandCounterIncrement() just before the PopActiveSnapshot() call (and
removing the final one) fixes this issue for me, but I have no idea if
this is the right fix.

-- 
Julien Rouhaud
http://dalibo.com - http://dalibo.org



Re: [HACKERS] [GENERAL] Column rename in an extension update script

От
Tom Lane
Дата:
Julien Rouhaud <julien.rouhaud@dalibo.com> writes:
> moving this thread to -hackers, since this looks like a bug.
> On 01/05/2017 08:54, Philippe BEAUDOIN wrote:
>> I am coding an update script for an extension. And I am in trouble when
>> trying to rename a column of an existing table.
>> 
>> Just after the ALTER TABLE statement, I want to access this table. But
>> at this time, the altered column is not visible with its new name.

> I can reproduce this issue.

> It looks like this is due to missing cache invalidation between the
> ALTER TABLE execution and next query planning (failure happens during
> pg_analyze_and_rewrite()).

Yes.  Kind of surprising nobody noticed this before --- you'd certainly
think that extension scripts would have lots of cases of statements
depending on DDL done just before them.  I think it must have been masked
by the fact that many DDL commands *end* with CommandCounterIncrement,
or at least have one pretty close to the end.  But not renameatt().

> AFAICT, CommandCounterIncrement() is responsible for handling
> invalidation messages, but in execute_sql_string() this function is
> called before executing a Stmt instead of after.  Moving the
> CommandCounterIncrement() just before the PopActiveSnapshot() call (and
> removing the final one) fixes this issue for me, but I have no idea if
> this is the right fix.

I'm inclined to add one before the parse step, rather than removing any.
The sequence of bump-the-command-counter-then-capture-a-snapshot is
pretty well established in places like spi.c, so I don't want to change
that usage.  Also, I think part of the point here was to ensure that
any DDL done *before* reaching execute_sql_string() is visible to the
first command.  Also note the assumption in ApplyExtensionUpdates that
execute_sql_string will do at least one CommandCounterIncrement, even
if the script is empty.  A CCI that has nothing to do is quite cheap,
and we're not that worried about performance here anyway IMO, so I'd
just as soon err on the side of having more than enough CCIs.
        regards, tom lane