Re: Is there a good way to handle sum types (or tagged unions) in PostgreSQL?

Поиск
Список
Период
Сортировка
От Peter J. Holzer
Тема Re: Is there a good way to handle sum types (or tagged unions) in PostgreSQL?
Дата
Msg-id 20230519195204.h2gjmzevimmjp6sx@hjp.at
обсуждение исходный текст
Ответ на Re: Is there a good way to handle sum types (or tagged unions) in PostgreSQL?  (Victor Nordam Suadicani <v.n.suadicani@gmail.com>)
Список pgsql-general
On 2023-05-19 16:55:00 +0200, Victor Nordam Suadicani wrote:
> Thanks for the perspective :)
>
> > If you need SQL, you need to design for SQL for the get go. Not shoehorn your
> >  Rust data model into SQL.
>
> Sometimes the data in the domain really does fit a sum type and then a sum type
> is the right tool to use (whether you use Rust or Haskell or whatever
> language). Trying to shoehorn your domain data model into a data format that
> doesn't fit isn't the way to go either. I feel like it's a deficiency in SQL
> that there is no support for sum types. I would guess this is influenced by the
> fact that SQL was developed in a time when there were no major programming
> languages with sum type support either.

That may have been a reason. It is worth noting, however that (at least
some versions of) entity-relationship diagrams do have graphical
symbols for "exactly/at most one of these attributes must be set". This
is very similar to the example you gave, where each of the three
variants had a name (and very different to e.g. TypeScript, where you
can just define a variable to be of type «string | number | Date»)

The way this is implemented is quite straightforward, as Dominique
wrote: You have several nullable columns and a constraint which ensures
that only one is not null.

For example

    create table alternatetest (
        id serial primary key,
        name text,
        i int, f float, t text, -- these three form a union/sum type
        check (
            (i is not null)::int + (f is not null)::int + (t is not null)::int = 1
        )
    );

The space overhead is very small (in PostgreSQL it's a single bit per
nullable column).

An ORM for Rust should be able to read the three columns and stuff them
into a single variable of sum type. I don't know Rust well enough if the
other direction is possible automatically (does the compiler and/or the
run-time system keep track which variant is currently valid?), but even
if it isn't, surely the application must have that information and be
able to pass it into the ORM.

If you aren't using an ORM but using SQL directly (as I prefer to do as
I find that ORMs are just another leaky abstraction layer which makes
stuff harder instead of easier) then you have to code that yourself, but
you can probably centralize that somewhere and the rest of your code
will be blissfully unaware.

(Of course you can stuff those values in a single column of JSONB type.
But I don't think this is better.)

        hp

--
   _  | Peter J. Holzer    | Story must make more sense than reality.
|_|_) |                    |
| |   | hjp@hjp.at         |    -- Charles Stross, "Creative writing
__/   | http://www.hjp.at/ |       challenge!"

Вложения

В списке pgsql-general по дате отправления:

Предыдущее
От: Mike Lissner
Дата:
Сообщение: Re: Trying to understand a failed upgrade in AWS RDS
Следующее
От: "Peter J. Holzer"
Дата:
Сообщение: Re: Modeling combinations (options and dependencies)