Thread: Controlling the usage of a user-defined cast
Hi,
When a user-defined CAST is created, it has the ability to break behavior of built-in
casts that could be performed implicitly, i.e. without a cast defined in pg_cast.
Below is a simple example of a user-defined text to numeric cast that changes the behavior of
such a type conversion.
postgres=# create table test ( id text ); insert into test values ('1.09');
CREATE TABLE
INSERT 0 1
postgres=#
postgres=# select id::numeric from test ;
id
------
1.09
(1 row)
postgres=#
postgres=# CREATE OR REPLACE FUNCTION text_to_numeric(t text) RETURNS numeric AS $$
postgres$# BEGIN
postgres$# RETURN t::float::numeric(10, 0);
postgres$# END;
postgres$# $$ LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# create cast(text as numeric) with function text_to_numeric(text) AS IMPLICIT;
CREATE CAST
postgres=#
postgres=# select id::numeric from test ;
id
----
1
(1 row)
In the above example, PostgreSQL is able to perform a text to numeric cast without an
explicit cast in pg_cast. Because a cast does not exist in pg_cast, a user ( with ownership to the source or
target type ) is able to create a new cast that will alter the built-in behavior.
This cast is now scoped to the entire database and the behavior intended by the creator of
the cast may not be the behavior desired for all applications. Also, if the cast returns erroneous
results, the scope of the error is now for the entire database.
There is currently no way to prevent the usage of a user-defined cast. Should there be one?
One idea I have been thinking about is to control this behavior via a GUC, but there may be
other ways to explore to handle this.
Any thoughts?
Regards,
Sami Imseih
Amazon Web Services (AWS)
Sami Imseih <samimseih@gmail.com> writes: > When a user-defined CAST is created, it has the ability to break behavior of built-in > casts that could be performed implicitly, i.e. without a cast defined in pg_cast. The requirement for ownership of at least one type means that the example you give could only be done by a superuser. I think there could be an argument for requiring ownership of *both* types, but perhaps that would break some useful cases. > There is currently no way to prevent the usage of a user-defined cast. Should there be one? I don't think so, and I don't see any reasonable way to do it. You will get nowhere proposing a GUC that changes query semantics --- we learned that that was a bad idea decades ago. regards, tom lane
> The requirement for ownership of at least one type means that the > example you give could only be done by a superuser. That's correct; and superuser should be doing the right thing. > There is currently no way to prevent the usage of a user-defined cast. Should there be one? >> I don't think so, and I don't see any reasonable way to do it. >> You will get nowhere proposing a GUC that changes query semantics --- >> we learned that that was a bad idea decades ago. Point taken. Looking at [1] I wonder if there should be more emphasis on this point. The point being that a user-defined cast has the ability to override the behavior of a cast that can be performed implicitly. [1] https://www.postgresql.org/docs/current/sql-createcast.html Regards, Sami Amazon Web Services (AWS)