mirror of https://github.com/citusdata/citus.git
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
parent
30ac6f0fe9
commit
1b26d57288
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue