Adds tests for suppressed constants in postgres_fdw queries (#6370)

PG15 has suppressed some casts on constants when querying foreign
tables.
For example, we can use text to represent a type that's an enum on the
remote side.
A comparison on such a column will get shipped as "var = 'foo'::text".
But there's no enum = text operator on the remote side.
If we leave off the explicit cast, the comparison will work.

Test we behave in the same way with a Citus foreign table
Reminder: foreign tables cannot be distributed/reference, can only be
Citus local

Relevant PG commit:
f8abb0f5e1
pull/6376/head
Naisila Puka 2022-09-27 13:40:48 +03:00 committed by GitHub
parent 30ac6f0fe9
commit 1b26d57288
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 181 additions and 0 deletions

View File

@ -1249,12 +1249,128 @@ CREATE TABLE set_on_default_test_referencing(
ON DELETE SET DEFAULT (col_3)
);
ERROR: cannot create foreign key constraint since Citus does not support ON DELETE / UPDATE SET DEFAULT actions on the columns that default to sequences
--
-- PG15 has suppressed some casts on constants when querying foreign tables
-- For example, we can use text to represent a type that's an enum on the remote side
-- A comparison on such a column will get shipped as "var = 'foo'::text"
-- But there's no enum = text operator on the remote side
-- If we leave off the explicit cast, the comparison will work
-- Test we behave in the same way with a Citus foreign table
-- Reminder: foreign tables cannot be distributed/reference, can only be Citus local
-- Relevant PG commit:
-- f8abb0f5e114d8c309239f0faa277b97f696d829
--
\set VERBOSITY terse
SET citus.next_shard_id TO 960200;
SET citus.enable_local_execution TO ON;
-- add the foreign table to metadata with the guc
SET citus.use_citus_managed_tables TO ON;
CREATE TYPE user_enum AS ENUM ('foo', 'bar', 'buz');
CREATE TABLE foreign_table_test (c0 integer NOT NULL, c1 user_enum);
INSERT INTO foreign_table_test VALUES (1, 'foo');
CREATE EXTENSION postgres_fdw;
CREATE SERVER foreign_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'localhost', port :'master_port', dbname 'regression');
CREATE USER MAPPING FOR CURRENT_USER
SERVER foreign_server
OPTIONS (user 'postgres');
CREATE FOREIGN TABLE foreign_table (
c0 integer NOT NULL,
c1 text
)
SERVER foreign_server
OPTIONS (schema_name 'pg15', table_name 'foreign_table_test');
-- check that the foreign table is a citus local table
SELECT partmethod, repmodel FROM pg_dist_partition WHERE logicalrelid = 'foreign_table'::regclass ORDER BY logicalrelid;
partmethod | repmodel
---------------------------------------------------------------------
n | s
(1 row)
-- same tests as in the relevant PG commit
-- Check that Remote SQL in the EXPLAIN doesn't contain casting
EXPLAIN (VERBOSE, COSTS OFF)
SELECT * FROM foreign_table WHERE c1 = 'foo' LIMIT 1;
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Output: remote_scan.c0, remote_scan.c1
Task Count: 1
Tasks Shown: All
-> Task
Query: SELECT c0, c1 FROM pg15.foreign_table_960201 foreign_table WHERE (c1 OPERATOR(pg_catalog.=) 'foo'::text) LIMIT 1
Node: host=localhost port=xxxxx dbname=regression
-> Foreign Scan on pg15.foreign_table_960201 foreign_table
Output: c0, c1
Remote SQL: SELECT c0, c1 FROM pg15.foreign_table_test WHERE ((c1 = 'foo')) LIMIT 1::bigint
(10 rows)
SELECT * FROM foreign_table WHERE c1 = 'foo' LIMIT 1;
c0 | c1
---------------------------------------------------------------------
1 | foo
(1 row)
-- Check that Remote SQL in the EXPLAIN doesn't contain casting
EXPLAIN (VERBOSE, COSTS OFF)
SELECT * FROM foreign_table WHERE 'foo' = c1 LIMIT 1;
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Output: remote_scan.c0, remote_scan.c1
Task Count: 1
Tasks Shown: All
-> Task
Query: SELECT c0, c1 FROM pg15.foreign_table_960201 foreign_table WHERE ('foo'::text OPERATOR(pg_catalog.=) c1) LIMIT 1
Node: host=localhost port=xxxxx dbname=regression
-> Foreign Scan on pg15.foreign_table_960201 foreign_table
Output: c0, c1
Remote SQL: SELECT c0, c1 FROM pg15.foreign_table_test WHERE (('foo' = c1)) LIMIT 1::bigint
(10 rows)
SELECT * FROM foreign_table WHERE 'foo' = c1 LIMIT 1;
c0 | c1
---------------------------------------------------------------------
1 | foo
(1 row)
-- we declared c1 to be text locally, but it's still the same type on
-- the remote which will balk if we try to do anything incompatible
-- with that remote type
SELECT * FROM foreign_table WHERE c1 LIKE 'foo' LIMIT 1; -- ERROR
ERROR: operator does not exist: pg15.user_enum ~~ unknown
SELECT * FROM foreign_table WHERE c1::text LIKE 'foo' LIMIT 1; -- ERROR; cast not pushed down
ERROR: operator does not exist: pg15.user_enum ~~ unknown
-- Clean up foreign table test
RESET citus.use_citus_managed_tables;
SELECT undistribute_table('foreign_table');
NOTICE: creating a new table for pg15.foreign_table
NOTICE: dropping the old pg15.foreign_table
NOTICE: renaming the new table to pg15.foreign_table
undistribute_table
---------------------------------------------------------------------
(1 row)
SELECT undistribute_table('foreign_table_test');
NOTICE: creating a new table for pg15.foreign_table_test
NOTICE: moving the data of pg15.foreign_table_test
NOTICE: dropping the old pg15.foreign_table_test
NOTICE: renaming the new table to pg15.foreign_table_test
undistribute_table
---------------------------------------------------------------------
(1 row)
SELECT 1 FROM citus_remove_node('localhost', :master_port);
?column?
---------------------------------------------------------------------
1
(1 row)
DROP SERVER foreign_server CASCADE;
NOTICE: drop cascades to 2 other objects
-- Clean up
\set VERBOSITY terse
SET client_min_messages TO ERROR;

View File

@ -806,7 +806,72 @@ CREATE TABLE set_on_default_test_referencing(
ON DELETE SET DEFAULT (col_3)
);
--
-- PG15 has suppressed some casts on constants when querying foreign tables
-- For example, we can use text to represent a type that's an enum on the remote side
-- A comparison on such a column will get shipped as "var = 'foo'::text"
-- But there's no enum = text operator on the remote side
-- If we leave off the explicit cast, the comparison will work
-- Test we behave in the same way with a Citus foreign table
-- Reminder: foreign tables cannot be distributed/reference, can only be Citus local
-- Relevant PG commit:
-- f8abb0f5e114d8c309239f0faa277b97f696d829
--
\set VERBOSITY terse
SET citus.next_shard_id TO 960200;
SET citus.enable_local_execution TO ON;
-- add the foreign table to metadata with the guc
SET citus.use_citus_managed_tables TO ON;
CREATE TYPE user_enum AS ENUM ('foo', 'bar', 'buz');
CREATE TABLE foreign_table_test (c0 integer NOT NULL, c1 user_enum);
INSERT INTO foreign_table_test VALUES (1, 'foo');
CREATE EXTENSION postgres_fdw;
CREATE SERVER foreign_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'localhost', port :'master_port', dbname 'regression');
CREATE USER MAPPING FOR CURRENT_USER
SERVER foreign_server
OPTIONS (user 'postgres');
CREATE FOREIGN TABLE foreign_table (
c0 integer NOT NULL,
c1 text
)
SERVER foreign_server
OPTIONS (schema_name 'pg15', table_name 'foreign_table_test');
-- check that the foreign table is a citus local table
SELECT partmethod, repmodel FROM pg_dist_partition WHERE logicalrelid = 'foreign_table'::regclass ORDER BY logicalrelid;
-- same tests as in the relevant PG commit
-- Check that Remote SQL in the EXPLAIN doesn't contain casting
EXPLAIN (VERBOSE, COSTS OFF)
SELECT * FROM foreign_table WHERE c1 = 'foo' LIMIT 1;
SELECT * FROM foreign_table WHERE c1 = 'foo' LIMIT 1;
-- Check that Remote SQL in the EXPLAIN doesn't contain casting
EXPLAIN (VERBOSE, COSTS OFF)
SELECT * FROM foreign_table WHERE 'foo' = c1 LIMIT 1;
SELECT * FROM foreign_table WHERE 'foo' = c1 LIMIT 1;
-- we declared c1 to be text locally, but it's still the same type on
-- the remote which will balk if we try to do anything incompatible
-- with that remote type
SELECT * FROM foreign_table WHERE c1 LIKE 'foo' LIMIT 1; -- ERROR
SELECT * FROM foreign_table WHERE c1::text LIKE 'foo' LIMIT 1; -- ERROR; cast not pushed down
-- Clean up foreign table test
RESET citus.use_citus_managed_tables;
SELECT undistribute_table('foreign_table');
SELECT undistribute_table('foreign_table_test');
SELECT 1 FROM citus_remove_node('localhost', :master_port);
DROP SERVER foreign_server CASCADE;
-- Clean up
\set VERBOSITY terse