I looked into bug#14397. The submitter was discourteous enough not to
provide an in-line example, but here it is:
CREATE TABLE IF NOT EXISTS TEST_1 (
ID SERIAL PRIMARY KEY,
C1 BYTEA,
C2 TEXT NOT NULL,
C3 BOOLEAN NOT NULL DEFAULT FALSE,
CONSTRAINT TEST_1_unique_idx UNIQUE(C1, C2)
create or replace view test as select * from test_1 with cascaded check option;
insert into test (c1, c2, c3) values (decode('MTIzAAE=', 'base64'),
'text', true) on conflict (c1, c2) do update set c3=excluded.c3;
ERROR: ON CONFLICT is not supported on table "test" used as a catalog table
LINE 1: ...lues (decode('MTIzAAE=', 'base64'), 'text', true) on conflic...
^
The reason for the error is that transformOnConflictArbiter applies
RelationIsUsedAsCatalogTable() to something that it doesn't know to
be a plain relation --- it's a view in this case. And that macro
blindly assumes that relation->rd_options is a StdRdOptions struct,
when in this case it's actually a ViewOptions struct.
Now that I've seen this I wonder which other uses of rd_options are
potentially broken. RelationIsUsedAsCatalogTable() is hardly the
only macro that is assuming with little justification that it's
applied to the right kind of reloptions.
We could band-aid this by having the RelationIsUsedAsCatalogTable()
macro check relation->relkind, but I'm inclined to think that the
right fix going forward is to insist that StdRdOptions, ViewOptions,
and the other in-memory representations of reloptions ought to be
self-identifying somehow. We could add a field to them similar to
nodeTag, but one of the things that was envisioned to begin with
is relation types that have StdRdOptions as the first part of a
larger struct. I'm not sure how to make that work with a tag.
Thoughts?
regards, tom lane