Re: BUG #18097: Immutable expression not allowed in generated at
Tom Lane <tgl@sss.pgh.pa.us>
From: Tom Lane <tgl@sss.pgh.pa.us>
To: pgsql-hackers@lists.postgresql.org
Cc: James Keener <jim@jimkeener.com>
Date: 2023-09-09T19:18:07Z
Lists: pgsql-bugs, pgsql-hackers
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Ensure we preprocess expressions before checking their volatility.
- f07a3039c72b 16.2 landed
- abd1b1325d60 12.18 landed
- 9bd0f74eac19 14.11 landed
- 9057ddbefe7e 15.6 landed
- 743ddafc7124 17.0 landed
- 5c11104c7d20 13.14 landed
Attachments
- v1-0001-Refactor-to-add-wrappers-for-contain_mutable-vola.patch (text/x-diff) patch v1-0001
- v1-0002-Preprocess-column-GENERATED-expressions-before-ch.patch (text/x-diff) patch v1-0002
- v1-0003-Preprocess-column-DEFAULT-expressions-before-chec.patch (text/x-diff) patch v1-0003
[ moving to pgsql-hackers ] I wrote: > Applying expression_planner() solves the problem because it inlines > anytextcat(anynonarray,text), resolving that the required cast is > numeric->text which is immutable. The code for generated expressions > omits that step and arrives at the less desirable answer. I wonder > where else we have the same issue. After digging around, I could only find one other place where outside-the-planner code was doing this wrong: AddRelationNewConstraints can come to the wrong conclusion about whether it's safe to use missingMode. So here's a patch series to resolve this. I split it into three parts mostly because 0002 will only go back to v12 where we added GENERATED, but the missingMode bug exists in v11. There are a couple of points worth bikeshedding perhaps. I didn't spend much thought on the wrapper functions' names, but it's surely true that the semantic difference between contain_mutable_functions and ContainMutableFunctions is quite un-apparent from those names. Anybody got a better idea? It also seemed about fifty-fifty whether to make the wrappers' argument types be Node * or Expr *. I stuck with Expr * because that's what the predecessor code CheckMutability() used, but that's not a very strong argument. BTW, the test function in 0003 might look funny: CREATE FUNCTION foolme(timestamptz DEFAULT clock_timestamp()) RETURNS timestamptz IMMUTABLE AS 'select $1' LANGUAGE sql; but AFAICS it's perfectly legit. The function itself is indeed immutable, since it's only "select $1"; it's the default argument that's volatile. I'll add this to the open CF 2023-11, but we really ought to get it committed before that so we can ship these bug fixes in November's releases. regards, tom lane