Re: AW: AW: Cast INTEGER to BIT confusion - Mailing list pgsql-general

From Erik Wienhold
Subject Re: AW: AW: Cast INTEGER to BIT confusion
Date
Msg-id 347149651.358104.1692279104782@office.mailbox.org
Whole thread Raw
In response to AW: AW: Cast INTEGER to BIT confusion  ("[Quipsy] Markus Karg" <karg@quipsy.de>)
List pgsql-general
> On 17/08/2023 09:31 CEST [Quipsy] Markus Karg <karg@quipsy.de> wrote:
>
> I am giving up. While even `SELECT current_schemas(true)` correctly prints
> `xxx, pg_catalog` it still uses the original bit type. This is completely
> NOT as described in the documentation, where it is clearly told that
> pg_catalog only is searched immediately if NOT found in the search path.
> It seems it is simply impossible to run this application on PostgreSQL, and
> we have to stick with a different RDBMS. Very sad.
>
> -----Ursprüngliche Nachricht-----
> Von: Erik Wienhold <ewie@ewie.name>
> Gesendet: Dienstag, 15. August 2023 16:28
> An: [Quipsy] Markus Karg <karg@quipsy.de>; pgsql-general@lists.postgresql.org
> Betreff: Re: AW: Cast INTEGER to BIT confusion
>
> > On 15/08/2023 14:02 CEST [Quipsy] Markus Karg <karg@quipsy.de> wrote:
> >
> > I just tried out your proposal on PostgreSQL 15.3 and this is the result:
> >
> > ERROR:  column "c" is of type bit but expression is of type integer
> > LINE 5:   INSERT INTO t VALUES (1);
> >                                 ^
> > HINT:  You will need to rewrite or cast the expression.
> >
> > Apparently the search path is ignored?!
> >
> > -----Ursprüngliche Nachricht-----
> > Von: Erik Wienhold <ewie@ewie.name>
> > Gesendet: Dienstag, 15. August 2023 13:48
> > An: [Quipsy] Markus Karg <karg@quipsy.de>;
> > pgsql-general@lists.postgresql.org
> > Betreff: Re: Cast INTEGER to BIT confusion
> >
> > You could create a custom domain if you're only interested in values 0
> > and 1 and don't use bit string functions.  The search path must be
> > changed so that domain bit overrides pg_catalog.bit:
> >
> >     =# CREATE SCHEMA xxx;
> >     =# CREATE DOMAIN xxx.bit AS int;
> >     =# SET search_path = xxx, pg_catalog;
> >     =# CREATE TABLE t (c bit);
> >     =# INSERT INTO t VALUES (1);
> >     INSERT 0 1
> >
> > But I would do that only if the third-party code cannot be tweaked
> > because the custom domain could be confusing.  It's also prone to
> > errors as it relies on a specific search path order.  Also make sure
> > that regular users cannot create objects in schema xxx that would override objects in pg_catalog.
>
> Hmm, I thought that Postgres resolves all types through the search path, but apparently that is not the case for
built-intypes.  I never used this to override built-in types so this is a surprise to me.  (And obviously I haven't
testedthe search path feature before posting.) 
>
> Neither [1] or [2] mention that special (?) case or if there's a distinction between built-in types and user-defined
types. The USAGE privilege is required according to [2] but I was testing as superuser anyway. 
>
> [1] https://www.postgresql.org/docs/15/ddl-schemas.html
> [2] https://www.postgresql.org/docs/15/runtime-config-client.html#GUC-SEARCH-PATH

It looks like Postgres resolves standard SQL types without considering the
search path.  This could be a feature (perhaps mandated by the SQL standard?)
and not a bug if the rationale here is to avoid shadowing of standard types
with custom types so that type bit, for example, always behaves as the standard
bit type.

In the following script I create several domains in schema xxx: bit and float
match standard SQL type names, domain foo does not conflict with any built-in
type name, and inet is a built-in type but not a standard type.

    BEGIN;

    CREATE SCHEMA xxx;
    GRANT USAGE ON SCHEMA xxx TO current_user;

    CREATE DOMAIN xxx.bit AS int;
    CREATE DOMAIN xxx.float AS int;
    CREATE DOMAIN xxx.foo AS int;
    CREATE DOMAIN xxx.inet AS int;
    CREATE DOMAIN pg_catalog.foo AS int;
    \dD *.(bit|float|foo|inet)

    SET LOCAL search_path = xxx, pg_catalog;
    SELECT current_schemas(true);

    CREATE TABLE public.t (f1 bit, f2 float, f3 inet, f4 foo);

    SET LOCAL search_path = '';
    \d public.t

    ROLLBACK;

We see that table t is created with the standard SQL types instead of our
custom domains.  Only xxx.inet and xxx.foo are resolved according to the search
path.

    BEGIN
    CREATE SCHEMA
    GRANT
    CREATE DOMAIN
    CREATE DOMAIN
    CREATE DOMAIN
    CREATE DOMAIN
    CREATE DOMAIN
                                List of domains
       Schema   | Name  |  Type   | Collation | Nullable | Default | Check
    ------------+-------+---------+-----------+----------+---------+-------
     pg_catalog | foo   | integer |           |          |         |
     xxx        | bit   | integer |           |          |         |
     xxx        | float | integer |           |          |         |
     xxx        | foo   | integer |           |          |         |
     xxx        | inet  | integer |           |          |         |
    (4 rows)

    SET
     current_schemas
    ------------------
     {xxx,pg_catalog}
    (1 row)

    CREATE TABLE
    SET
                          Table "public.t"
     Column |       Type       | Collation | Nullable | Default
    --------+------------------+-----------+----------+---------
     f1     | bit(1)           |           |          |
     f2     | double precision |           |          |
     f3     | xxx.inet         |           |          |
     f4     | xxx.foo          |           |          |

    ROLLBACK

--
Erik



pgsql-general by date:

Previous
From: "David G. Johnston"
Date:
Subject: Re: Cast INTEGER to BIT confusion
Next
From: Sai Teja
Date:
Subject: Re: Fatal Error : Invalid Memory alloc request size 1236252631