Re: postgres_fdw could deparse ArrayCoerceExpr - Mailing list pgsql-hackers

From Alexander Pyhalov
Subject Re: postgres_fdw could deparse ArrayCoerceExpr
Date
Msg-id 0be55d1548c3b1bc29b8ae23f6db24e3@postgrespro.ru
Whole thread Raw
Responses Re: postgres_fdw could deparse ArrayCoerceExpr
List pgsql-hackers
Maxim Orlov писал(а) 2025-01-24 18:09:
> Look like an overlook for me. Apparently no one has encountered this
> use case before.
> 
> Patch seems good to me with no visible defects. Deparse support was
> also added. As well as a
> test case. But do we really need copy/paste code for a
> T_ArrayCoerceExpr case? To be more specific,
> can we "reuse" T_RelabelType case, as it made for T_OpExpr and
> T_DistinctExpr?
> 
> --
> 

Unfortunately, it's not so simple. We can't just ship type casts to 
remote server if we are not sure that local and remote types match. For 
example,

CREATE TYPE enum_of_int_like AS enum('1', '2', '3', '4');
CREATE TABLE conversions(id int, d enum_of_int_like);
CREATE FOREIGN TABLE ft_conversions (id int, d char(1))
SERVER loopback options (table_name 'conversions');
INSERT INTO ft_conversions VALUES (1, '1'), (2, '2'), (3, '3'), (4, 
'4');

Patched version gives error:

-- Test array type conversion pushdown
SET plan_cache_mode = force_generic_plan;
PREPARE s(varchar[]) AS SELECT count(*) FROM ft_conversions WHERE d = 
ANY ($1);
EXPLAIN (VERBOSE, COSTS OFF)
EXECUTE s(ARRAY['1','2']);
                                             QUERY PLAN
---------------------------------------------------------------------------------------------------
  Foreign Scan
    Output: (count(*))
    Relations: Aggregate on (public.ft_conversions)
    Remote SQL: SELECT count(*) FROM public.conversions WHERE ((d = ANY 
($1::character varying[])))
(4 rows)

EXECUTE s(ARRAY['1','2']);
ERROR:  operator does not exist: public.enum_of_int_like = character 
varying
HINT:  No operator matches the given name and argument types. You might 
need to add explicit type casts.
CONTEXT:  remote SQL command: SELECT count(*) FROM public.conversions 
WHERE ((d = ANY ($1::character varying[])))

Original one does successful local filtering:

PREPARE s(varchar[]) AS SELECT count(*) FROM ft_conversions WHERE d = 
ANY ($1);
EXPLAIN (VERBOSE, COSTS OFF)
EXECUTE s(ARRAY['1','2']);
                         QUERY PLAN
-----------------------------------------------------------
  Aggregate
    Output: count(*)
    ->  Foreign Scan on public.ft_conversions
          Output: id, d
          Filter: (ft_conversions.d = ANY (($1)::bpchar[]))
          Remote SQL: SELECT d FROM public.conversions
(6 rows)

EXECUTE s(ARRAY['1','2']);
  count
-------
      2

-- 
Best regards,
Alexander Pyhalov,
Postgres Professional



pgsql-hackers by date:

Previous
From: Amit Kapila
Date:
Subject: Re: Skip collecting decoded changes of already-aborted transactions
Next
From: Bertrand Drouvot
Date:
Subject: Re: BF member drongo doesn't like 035_standby_logical_decoding.pl