Re: inconsistent tableoid handling in COPY WHERE clause - Mailing list pgsql-hackers

From Kirill Reshke
Subject Re: inconsistent tableoid handling in COPY WHERE clause
Date
Msg-id CALdSSPh_V_pF92yC4hmb3hH4Zv0hOZ1JWp5A839aGHF1rgMKOw@mail.gmail.com
Whole thread Raw
In response to inconsistent tableoid handling in COPY WHERE clause  (Peter Eisentraut <peter@eisentraut.org>)
Responses Re: inconsistent tableoid handling in COPY WHERE clause
List pgsql-hackers
On Wed, 5 Nov 2025 at 16:06, Peter Eisentraut <peter@eisentraut.org> wrote:
>
> I think the COPY FROM WHERE clause is handling the tableoid column in a
> way that is inconsistent with its usual definition.
>
> Consider a partitioning hierarchy like
>
> DROP TABLE IF EXISTS xp;
>
> CREATE TABLE xp (a int, b int) PARTITION BY LIST (a);
> CREATE TABLE xp1 PARTITION OF xp FOR VALUES IN (1);
> CREATE TABLE xp2 PARTITION OF xp FOR VALUES IN (2);
> CREATE TABLE xp3 PARTITION OF xp FOR VALUES IN (3);
>
> Then you can use tableoid in a trigger to reveal the actual partition
> that an inserted row ended up in:
>
> CREATE OR REPLACE FUNCTION tf() RETURNS TRIGGER LANGUAGE plpgsql
> AS
> $$
> BEGIN
>    RAISE NOTICE 'new.tableoid = %', NEW.tableoid;
>    RETURN NEW;
> END
> $$;
>
> CREATE TRIGGER tg1 AFTER INSERT ON xp FOR EACH ROW EXECUTE FUNCTION tf();
>
> INSERT INTO xp VALUES (1, 11), (2, 22);
>
> You can also write a check constraint that references tableoid to check
> what partition a row ends up in:
>
> ALTER TABLE xp ADD CONSTRAINT xpc
>    CHECK (tableoid IN ('xp1'::regclass, 'xp2'::regclass));
>
> INSERT INTO xp VALUES (3, 33);  -- error: violates check constraint
>
> So far so good.
>
> You can also refer to tableoid in the WHERE clause of a COPY command,
> but that doesn't work correctly:
>
> COPY xp FROM STDIN WHERE tableoid = 'xp2'::regclass;
> 1       111
> 2       222
> \.
>
> I would have expected that to copy only rows that are targeted for the
> xp2 partition, but in fact it does not copy anything.
>
> This works:
>
> COPY xp FROM STDIN WHERE tableoid = 'xp'::regclass;
> 1       111
> 2       222
> \.
>
> because tableoid in fact refers to the table named in the command, not
> the actual target partition.
>
> That seems incorrect to me.
>
> I don't see this documented one way or another, but there is a code
> comment in copyfrom.c at least mentioning tableoid in the context of the
> COPY WHERE clause:
>
>      /*
>       * Constraints and where clause might reference the tableoid column,
>       * so (re-)initialize tts_tableOid before evaluating them.
>       */
>      myslot->tts_tableOid =
> RelationGetRelid(target_resultRelInfo->ri_RelationDesc);
>
> This comment appeared in a not-quite-related refactoring (commit
> 86b85044e82), it only said "Constraints might ..." beforehand.
>
> Even the "Constraints might ..." variant of this is dubious, since as
> shown above, check constraints do have partition awareness, and there
> are places in nodeModifyTable.c that initialize tts_tableOid for that
> purpose.  Are there other constraints where tableoid can be used (and
> where this way of initializing it doesn't result in wrong behavior)?
>
> I suggest that we should prohibit using tableoid in COPY WHERE clauses
> for the time being.  I don't know if there would be a way to make them
> work correctly at all, but most likely not in a backpatchable way anyway.
>
> I also suggest that the above piece of code assigning tts_tableOid
> should be changed somehow.  Maybe just delete it, or set it to
> InvalidOid, because as it is it's misleading and probably wrong.
>
>
>

Hi!
Looks like this issue is currently discussed at [0]. Should we
continue here or there?



[0] https://www.postgresql.org/message-id/CACJufxHGGc25a2m%2B3Dezfctuykn51n5k3FJK6w3KSqfSFc5gvQ%40mail.gmail.com

-- 
Best regards,
Kirill Reshke



pgsql-hackers by date:

Previous
From: Peter Eisentraut
Date:
Subject: inconsistent tableoid handling in COPY WHERE clause
Next
From: Peter Eisentraut
Date:
Subject: Re: inconsistent tableoid handling in COPY WHERE clause