Good enough ten-second sum types for Postgres
10 points by silby
10 points by silby
What’s the point of the epoch column over only having the timestamp column with the old records being null?
I want the timestamp to be NOT NULL
on all new records without fussing with it on old ones. One could add a constraint CHECK (filled_at IS NOT NULL) NOT VALID
and it’d be comparable, but I can’t tell you the physical difference between that and a NOT NULL
column. Maybe there is none, in which case doing that would be less complicated than what I posted about, in this instance.
I’ve used check constraints with disjunctions of conditions before without a tag column, for cases where a record should have exactly one of three foreign keys not null. (There’s probably a more Codd-ian solution to that one too.)
There’s probably more compelling ways to use the same hack than my example, and there’s probably better ways of modeling the situation in a database too.
I understood the motivation. But you set the default on the new column already, so that should cover it. I’m not clear what’s gained by the extra field.
I like the idea for sum types like this, I just don’t see the appeal in the example ;)
I want the timestamp to be NOT NULL on all new records without fussing with it on old ones.
The thing here is, your enum doesn’t prevent this either, you can still insert things without a timestamp
Yeah totally, it relies on me never inserting a non-default epoch. I hate making promises instead of receiving guarantees but in context it’s a relatively easy promise to keep.
Occasionally I see people making SQL pre-processors to add features to the language; what I’d really love is a preprocessor that turns something like:
CREATE ENUM shape (
square(side NUMBER),
circle(radius NUMBER),
);
…and generates a table with all the fields and CHECKs implied:
CREATE TABLE shape (
_tag TEXT NOT NULL CHECK (_tag = 'square' OR _tag = 'circle'),
side NUMBER,
radius NUMBER,
CHECK (
(_tag = 'square' AND side IS NOT NULL AND radius IS NULL) OR
(_tag = 'circle' AND side IS NULL AND radius IS NOT NULL)
)
)
I just want a database with proper sum types.
Same. This feels like one of those things where the people who defend the status quo at all costs will rail against it until eventually it is manifest and then everyone will abruptly stop talking about it because it will seem so obvious and natural.
I think you would really need to support foreign key references (with referential integrity checks) to be truly useful. Without support for references, sum types are not very useful.
It’s hard to put my finger on it but sum types don’t feel quite right in a relational model. If I had records that could be in different “varieties“ with extra columns, I would probably model that as multiple tables. One for all of the records, and then a table each for the variations. Of course, then you cannot make them mutually exclusive, unless you had something like an anti-foreign key constraint?
I don’t think I agree. I don’t think there’s anything really special about the relational model that makes sum types particularly difficult–it would be a pretty natural extension of the existing model, specifically you just need to be able to express that a value can be one of several types, including a foreign key into another table (with the requisite constraints to ensure referential integrity). If that’s not already possible today, I think it would be a pretty simple extension, although in any case it would benefit considerably from syntax sugar so it’s as easy as INTEGER | TEXT | REFERENCES foos(foo_id)
or whathaveyou.
Yeah it’s definitely a weird fit, which is why I deemed it “probably illegal.” The relational model definitely wants you to have more than one table. A view would let me union these two tables when necessary. Though in my actual application I’d then have complicated foreign key problems as you note, especially bc the main foreign key on responses
is unique.
I’ve probably stared at Pg’s docs for table inheritance a dozen or so times in my life trying to decide if they were what I wanted for something. It never seemed like it.
I don’t do enough DB wrangling to comment, but I like how straightforward and to-the-point this post is. (Even if the red-on-green hurts my eyes for whatever reason.)
Interested in other ways people handle this, even if they require more than ten seconds to think about.
How about a default of -infinity
, to convert them to an unknown before value: https://www.postgresql.org/docs/current/datatype-datetime.html
That’s probably better! I either didn’t know or forgot -infinity
timestamps were a thing. They’d probably suit my purposes here.
a nullable column, backfilling the data, and making it non nullable
table inheritance and adding the new column there, so you have one table with everything (no timestamps) and one table with (only timestamps)
If table inheritance is the best option here for the first time in my life I’ll be delighted. I’ll probably try it out.