Re: SQL:2011 application time
Paul A Jungwirth <pj@illuminatedcomputing.com>
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Rename gist stratnum support function
- 32edf732e8dc 18.0 landed
-
Remove support for temporal RESTRICT foreign keys
- b83e8a2ca2eb 18.0 landed
-
Cache NO ACTION foreign keys separately from RESTRICT foreign keys
- 9926f854d077 18.0 landed
-
Fix NO ACTION temporal foreign keys when the referenced endpoints change
- 1772d554b089 18.0 landed
-
Improve whitespace in without_overlaps test
- 888d4523f0c2 18.0 landed
-
Tests for logical replication with temporal keys
- 939b0908c87a 18.0 landed
-
Support for GiST in get_equal_strategy_number()
- 74edabce7a33 18.0 landed
-
Make the conditions in IsIndexUsableForReplicaIdentityFull() more explicit
- 13544e790ef8 18.0 landed
-
Replace get_equal_strategy_number_for_am() by get_equal_strategy_number()
- a2a475b011cf 18.0 landed
-
Improve internal logical replication error for missing equality strategy
- 321c287351f7 18.0 landed
-
Simplify IsIndexUsableForReplicaIdentityFull()
- 7727049e8f66 18.0 landed
-
Fix ALTER TABLE / REPLICA IDENTITY for temporal tables
- 79b575d3bc09 18.0 landed
-
doc: Update pg_constraint.conexclop docs for WITHOUT OVERLAPS
- f683ba0867da 18.0 landed
-
doc: Add PERIOD to ALTER TABLE reference docs
- d56af4c882e2 18.0 landed
-
doc: Add WITHOUT OVERLAPS to ALTER TABLE reference docs
- bf621059500b 18.0 landed
-
Add temporal FOREIGN KEY contraints
- 89f908a6d0ac 18.0 landed
- 34768ee36165 17.0 landed
-
Add temporal PRIMARY KEY and UNIQUE constraints
- fc0438b4e805 18.0 landed
- 46a0cd4cefb4 17.0 landed
-
Add stratnum GiST support function
- 7406ab623fee 18.0 landed
- 6db4598fcb82 17.0 landed
-
Avoid crashing when a JIT-inlined backend function throws an error.
- 5d6c64d29097 17.0 cited
-
Revert temporal primary keys and foreign keys
- 8aee330af55d 17.0 landed
-
Fix ON CONFLICT DO NOTHING/UPDATE for temporal indexes
- 144c2ce0cc75 17.0 landed
-
Add test for REPLICA IDENTITY with a temporal key
- 482e108cd38d 17.0 landed
-
Use half-open interval notation in without_overlaps tests
- 5577a71fb0cc 17.0 landed
-
Use daterange and YMD in without_overlaps tests instead of tsrange.
- a88c800deb6f 17.0 landed
-
Rename pg_constraint.conwithoutoverlaps to conperiod
- 030e10ff1a36 17.0 landed
-
Fix comment on gist_stratnum_btree
- 86232a49a437 17.0 landed
-
Add missing TAP test name
- 1ab763fc22ad 16.0 cited
-
Improve error handling of HMAC computations
- 5513dc6a304d 15.0 cited
-
Rename functions to avoid future conflicts
- ee419607381d 15.0 landed
Thank you for the review! I think we covered everything here at the
PgConf.dev Advanced Patch Feedback session, but for the sake of the
list I'll reply to the specifics. I'll send a longer email summarizing
more from that session later, probably in a few days.
On Fri, May 9, 2025 at 2:50 PM Robert Haas <robertmhaas@gmail.com> wrote:
> I think these patches would benefit from some work to make them more
> understandable for people who don't already know what they're intended
> to accomplish.
I'll improve the commit messages in the next version of the patches. I
agree they have been pretty brief. Also we agreed that there should be
a separate documentation chapter/section introducing the concepts
behind temporal tables and application time. That will help in
general, plus it will give the existing doc changes a place to
reference for new terms.
> The rest of the
> commit message for v51-0001 reads like this:
>
> The procs return SETOF their input type and work like minus but don't
> fail on splits. The results never contain empty elements.
>
> For someone familiar with this work, this probably makes sense, but
> I'm not and it doesn't. I don't even understand to what "work like
> minus but don't fail on splits" is intended to refer. I mean, is there
> some existing minus thing? I don't see it among the GIST_*_PROC
> symbols, and I don't know where else I'd go looking.
Yes, I think I will rename these functions to
{,multi}range_minus_multi. I'm trying to say that they work like
range_minus (typically used via the minus operator). But range_minus
raises an exception if you subtract from the middle of its first
parameter/operand, because the result would yield two separate ranges.
range_minus_multi is a set-returning function to avoid that.
You can't return an array of ranges, because where our polymorphic
type system sees an input parameter of anyrange with a return type of
anyarray, it treats them as range<T> -> array<T>, not range<T> ->
array<range<T>>.
I don't want to return a multirange here either because that design
locks us in to range types, and I'd rather leave the door open to
support arbitrary user-defined types. A SRF means the type can bring
its own function to generate as many "leftovers" as it needs.
Also it sounds like an opclass support proc is not needed here at all.
There is no index involved (or there could be several). Perhaps a type
support proc. But for now we can support just range & multirange with
neither.
> As I read through the documentation changes, I find that you use terms
> like "leftovers" or "leftover row" in various parts of the
> documentation that are quite far away from and not obviously linked to
> the documentation of FOR PORTION OF. I think that's going to be very
> confusing. In other places where we used specialized terms like this,
> we often using <xref> or <link> to reference the place where the term
> is defined. You don't really quite have a place where that happens,
> though, although maybe linking to the documentation of FOR PORTION OF
> would be good enough.
Okay, see above. We also discussed using a term that better signals
its context, like "temporal range leftovers". I think I like just
"temporal leftovers" better, or maybe "temporal update leftovers" or
"temporal delete leftovers", depending on the operation.
> The documentation of FOR PORTION OF makes more sense to me for range
> types than for multirange types.
Okay, this is good feedback. I'll work on it!
> I gather that if I have a range like
> [1,10] and I deleted from 3 to 6, I'm going to end up with two ranges.
> I'm not sure whether 3 or 6 are inclusive or exclusive bounds, so I
> don't know if I should expect to end up with [1,3) and (6,10] or [1,3]
> and [6,10], and I kind of wonder if I should get to say which one I
> want, but anyway now I have two records, my original one having been
> split. But if [1,10] is a multirange, it's unnecessary to split the
> record in two in order to accommodate a deletion: i can just include
> both sub-ranges in the original value. But the documentation doesn't
> seem to mention this one way or the other: will I still (needlessly?)
> create two records, or will I just update the one record I already and
> split the range? Since the documentation is already talking about a
> feature specific to range and multirange types, it seems like this
> kind of stuff should be mentioned.
A multirange always returns just 0 or 1 result from without_portion
aka multirange_minus_multi. As you say, 2 results are unneeded.
> Hmm. I guess this implies that we never do an update -- it's always a
> DELETE followed by zero, one, or two INSERTs. That seems like it's
> leaving quite a bit of efficiency on the table, because updating an
> existing row in place could potentially be a HOT update.
>
> Is this feature as per the SQL standard? And, assuming yes, does the
> SQL standard specify that permission checks should work as you
> describe here, or is that something we decided?
This is not quite right. We never delete then insert the existing row
(except in the usual MVCC sense). The standard is very clear here: a
temporal update always updates the existing row (and automatically
changes its start/end time to not extend beyond the targeted range),
and a temporal delete always deletes the existing row. But if the
row's start/end times extended beyond just the targeted range, there
is still history your update/delete wasn't supposed to touch. So the
update/delete should be followed by 0, 1, or 2 inserts to preserve the
row's original values for those portions of history. I'll include this
in the docs I write.
Where the standard is not very clear is how to fire triggers for the
inserts. I'll leave those details for the next email.
The standard doesn't say anything about permissions either. Personally
I feel that since the inserts aren't adding any history that wasn't
there already, we shouldn't require insert permission. Also if we did
require insert permission, there would be no way to grant someone
access to correct existing history without adding new history. But I
don't have a strong opinion here. As my comment mentioned, perhaps
there is a security flaw, since skipping the insert permission check
means insert triggers fire for unauthorized users. Whatever we decide,
permissions and triggers should ideally cooperate to yield a
consistent mental model.
For that next email I'll start a separate thread, since this one has
gotten so long. Also I think this project is overdue for a wiki page.
Yours,
--
Paul ~{:-)
pj@illuminatedcomputing.co