Обсуждение: Why cannot alter column type when a view depends on it?

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

Why cannot alter column type when a view depends on it?

От
Chao Li
Дата:
Hi Hacker,

We have received a complain many times from our customers, especially those switched to PG from Oracle, that when they need to alter a column’s type, if there are views depend on the column, then users have to drop the view first and recreate the view after altering the column type.

This is quite easy to reproduce:

```
evantest=# create table t (c char(20));
CREATE TABLE
evantest=# create view v_t as select * from t;
CREATE VIEW

evantest=# alter table t alter column c type char(25);
ERROR:  cannot alter type of a column used by a view or rule
DETAIL:  rule _RETURN on view v_t depends on column "c"
```

I tried to understand why this restriction is set, then I found that, when a function uses a view, the view can actually be dropped, only when the function is executed, it will raise an error saying the view doesn’t exist. From this perspective, I think we should allow alter column type when a view depends on the column.

But I also realized the subtle complexities involved. For example, If a view is defined with a where clause, for example:

```
# create view v_t2 as select * from t where c = ‘xx’;
```

Then if you alter type of c from char(20) to int, that will cause the select statement invalid. However, alter table itself will block this type change, because it cannot cast char(20) to int automatically unless “using” is specified. So, at least for the following two cases:

* a view is defined with select only without where
* alter column type without using (the complexity is that even if “using” is specified, it might still be safe)

“Alter column” can be safely done without checking if a view depends on it.

The checking comes from RemeberAllDependentForRebuilding(), and I see a code comment:

case RewriteRelationId:

/*
* View/rule bodies have pretty much the same issues as
* function bodies. FIXME someday.
*/
if (subtype == AT_AlterColumnType)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot alter type of a column used by a view or rule"),
errdetail("%s depends on column \"%s\"",
getObjectDescription(&foundObject, false),
colName)));
break;

From this comment, I guess PG actually wants to remove the restriction.

In summary, this email is just raising the issue rather than proposing a solution. I want to hear feedbacks from the community. If people are interested in a solution to remove the restriction, then I can spend time on it.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/




Re: Why cannot alter column type when a view depends on it?

От
jian he
Дата:
On Sun, Sep 28, 2025 at 4:19 PM Chao Li <li.evan.chao@gmail.com> wrote:
>
> ```
> evantest=# create table t (c char(20));
> CREATE TABLE
> evantest=# create view v_t as select * from t;
> CREATE VIEW
>
> evantest=# alter table t alter column c type char(25);
> ERROR:  cannot alter type of a column used by a view or rule
> DETAIL:  rule _RETURN on view v_t depends on column "c"
> ```
>
> I tried to understand why this restriction is set, then I found that, when a function uses a view, the view can
actuallybe dropped, only when the function is executed, it will raise an error saying the view doesn’t exist. From this
perspective,I think we should allow alter column type when a view depends on the column. 
>

hi.

the simple case you mentioned above, it's definitely doable.
however say we have
create view v_t1 as select * from v_t;

RememberAllDependentForRebuilding can not cope with the dependency
between t and v_t1.
ATPostAlterTypeCleanup, we use DROP_RESTRICT in
performMultipleDeletions(objects, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);

That means
``alter table t alter column c type char(25);``
can not drop and recreate view v_t1,
it will error out within performMultipleDeletions while trying to drop view v_t.



Re: Why cannot alter column type when a view depends on it?

От
"David G. Johnston"
Дата:
On Sunday, September 28, 2025, Chao Li <li.evan.chao@gmail.com> wrote:

I tried to understand why this restriction is set, then I found that, when a function uses a view, the view can actually be dropped, only when the function is executed, it will raise an error saying the view doesn’t exist.

I’m doubting this applies to SQL-standard body functions where dependencies are actually tracked on the objects the function references.
 

In summary, this email is just raising the issue rather than proposing a solution. I want to hear feedbacks from the community. If people are interested in a solution to remove the restriction, then I can spend time on it.

I’d rather spend the effort providing something in pg_dump where you can give it a object_id and pg_dump will produce the DDL needed to recreate all of the views/etc in the correct order and the drop commands as well.  Making the alter table  “just work” seems just too problematic and limited to justify spending time on IMO.

David J.

Re: Why cannot alter column type when a view depends on it?

От
Chao Li
Дата:


On Sep 28, 2025, at 21:18, David G. Johnston <david.g.johnston@gmail.com> wrote:

On Sunday, September 28, 2025, Chao Li <li.evan.chao@gmail.com> wrote:

I tried to understand why this restriction is set, then I found that, when a function uses a view, the view can actually be dropped, only when the function is executed, it will raise an error saying the view doesn’t exist.

I’m doubting this applies to SQL-standard body functions where dependencies are actually tracked on the objects the function references.
 

In summary, this email is just raising the issue rather than proposing a solution. I want to hear feedbacks from the community. If people are interested in a solution to remove the restriction, then I can spend time on it.

I’d rather spend the effort providing something in pg_dump where you can give it a object_id and pg_dump will produce the DDL needed to recreate all of the views/etc in the correct order and the drop commands as well.  Making the alter table  “just work” seems just too problematic and limited to justify spending time on IMO.


I agree doing limited checks and making it “just work” isn’t the right direction to go.

After researching, I think we can take the similar way against constant and index for view. After altering a column’s type, related constrains and indexes will be rebuilt. Column type change may also break constraints or indexes. For example, if an int typed column has a constraints of “check (a>0)”, then if you change the column type from int to text, the constraints will become invalid, so that rebuilding the constant will fail, as a result, alter column type will fail as well.

So, while altering a column type, we can also rebuild depended views. If rebuilding views succeeds, then alter column type also succeeds. This should be a reliable solution.

I am going to work on PoC with this approach.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/




Re: Why cannot alter column type when a view depends on it?

От
Tom Lane
Дата:
Chao Li <li.evan.chao@gmail.com> writes:
> After researching, I think we can take the similar way against constant and index for view. After altering a column’s
type,related constrains and indexes will be rebuilt. Column type change may also break constraints or indexes. For
example,if an int typed column has a constraints of “check (a>0)”, then if you change the column type from int to text,
theconstraints will become invalid, so that rebuilding the constant will fail, as a result, alter column type will fail
aswell. 

> So, while altering a column type, we can also rebuild depended views. If rebuilding views succeeds, then alter column
typealso succeeds. This should be a reliable solution. 

I'm pretty uncomfortable with this proposal, because "this should be
a reliable solution" seems like very naive optimism.  ALTER COLUMN
TYPE's ability to rebuild indexes and constraints has never been more
than an 80% kind of feature: there is a nontrivial risk of its doing
the wrong thing.  Now, failing is not the wrong thing, but installing
a new object that doesn't act like the old object is.  We are making
all kinds of assumptions when we do those rebuilds, such as that the
same function or operator name means the same thing for the new data
type.

We've accepted that hazard for indexes and constraints because
the downside risk seems limited.  For instance, if we install an
expression index that isn't really what it should have been, the
worst case is that it won't match queries and hence won't be useful.
A bad constraint might prevent you from inserting valid data, but
when you notice that you can fix it.

However, I'm not convinced that the same argument applies to views.
People will be trying to use the rebuilt view, and if it doesn't do
what it should do, a real mess could ensue, such as silently-wrong
query results or table updates.

On top of that, rebuilding indexes and constraints is a one-level
problem: we might get them right or not, but nothing else depends on
it.  With views, after you've rebuilt them (and potentially changed
their output data types), you then have to consider rebuilding views
that depend on the changed one, and so on for perhaps many levels.
Each level increases the risk of a bad deduction about what should
happen, which would then cascade to all subsequently-modified views.

So on the whole I think this would be an anti-feature.  Given the
limited field demand for it, I'm not convinced we should put time
into it.

If we did want to pursue this further, I'd like to start by trying
to make the existing expression-rebuilding technology less of a
cross-your-fingers-and-pray matter.  I'm not very sure what that
should look like, except that I'd like something better than
"operators with the same name probably do the same thing".
We invented the notions of operator classes and families so that
we could formalize reasoning of that sort for index-associated
operators.  I wonder if some similar constructs could help?

            regards, tom lane