mirror of https://github.com/citusdata/citus.git
Merge branch 'main' into view-citus-nodes
commit
54c4de845b
|
|
@ -84,7 +84,6 @@ int ValuesMaterializationThreshold = 100;
|
|||
/* Local functions forward declarations */
|
||||
static bool JoinTreeContainsSubqueryWalker(Node *joinTreeNode, void *context);
|
||||
static bool IsFunctionOrValuesRTE(Node *node);
|
||||
static bool IsOuterJoinExpr(Node *node);
|
||||
static bool WindowPartitionOnDistributionColumn(Query *query);
|
||||
static DeferredErrorMessage * DeferErrorIfFromClauseRecurs(Query *queryTree);
|
||||
static RecurringTuplesType FromClauseRecurringTupleType(Query *queryTree);
|
||||
|
|
@ -394,7 +393,7 @@ IsNodeSubquery(Node *node)
|
|||
/*
|
||||
* IsOuterJoinExpr returns whether the given node is an outer join expression.
|
||||
*/
|
||||
static bool
|
||||
bool
|
||||
IsOuterJoinExpr(Node *node)
|
||||
{
|
||||
bool isOuterJoin = false;
|
||||
|
|
|
|||
|
|
@ -137,7 +137,8 @@ static bool ShouldRecursivelyPlanNonColocatedSubqueries(Query *subquery,
|
|||
RecursivePlanningContext *
|
||||
context);
|
||||
static bool ContainsSubquery(Query *query);
|
||||
static bool ShouldRecursivelyPlanOuterJoins(RecursivePlanningContext *context);
|
||||
static bool ShouldRecursivelyPlanOuterJoins(Query *query,
|
||||
RecursivePlanningContext *context);
|
||||
static void RecursivelyPlanNonColocatedSubqueries(Query *subquery,
|
||||
RecursivePlanningContext *context);
|
||||
static void RecursivelyPlanNonColocatedJoinWalker(Node *joinNode,
|
||||
|
|
@ -192,6 +193,10 @@ static Query * CreateOuterSubquery(RangeTblEntry *rangeTableEntry,
|
|||
List *outerSubqueryTargetList);
|
||||
static List * GenerateRequiredColNamesFromTargetList(List *targetList);
|
||||
static char * GetRelationNameAndAliasName(RangeTblEntry *rangeTablentry);
|
||||
#if PG_VERSION_NUM < PG_VERSION_17
|
||||
static bool hasPseudoconstantQuals(
|
||||
RelationRestrictionContext *relationRestrictionContext);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GenerateSubplansForSubqueriesAndCTEs is a wrapper around RecursivelyPlanSubqueriesAndCTEs.
|
||||
|
|
@ -355,7 +360,7 @@ RecursivelyPlanSubqueriesAndCTEs(Query *query, RecursivePlanningContext *context
|
|||
* result and logical planner can handle the new query since it's of the from
|
||||
* "<recurring> LEFT JOIN <recurring>".
|
||||
*/
|
||||
if (ShouldRecursivelyPlanOuterJoins(context))
|
||||
if (ShouldRecursivelyPlanOuterJoins(query, context))
|
||||
{
|
||||
RecursivelyPlanRecurringTupleOuterJoinWalker((Node *) query->jointree,
|
||||
query, context);
|
||||
|
|
@ -468,7 +473,7 @@ ContainsSubquery(Query *query)
|
|||
* join(s) that might need to be recursively planned.
|
||||
*/
|
||||
static bool
|
||||
ShouldRecursivelyPlanOuterJoins(RecursivePlanningContext *context)
|
||||
ShouldRecursivelyPlanOuterJoins(Query *query, RecursivePlanningContext *context)
|
||||
{
|
||||
if (!context || !context->plannerRestrictionContext ||
|
||||
!context->plannerRestrictionContext->joinRestrictionContext)
|
||||
|
|
@ -477,7 +482,37 @@ ShouldRecursivelyPlanOuterJoins(RecursivePlanningContext *context)
|
|||
"planning context")));
|
||||
}
|
||||
|
||||
return context->plannerRestrictionContext->joinRestrictionContext->hasOuterJoin;
|
||||
bool hasOuterJoin =
|
||||
context->plannerRestrictionContext->joinRestrictionContext->hasOuterJoin;
|
||||
#if PG_VERSION_NUM < PG_VERSION_17
|
||||
if (!hasOuterJoin)
|
||||
{
|
||||
/*
|
||||
* PG15 commit d1ef5631e620f9a5b6480a32bb70124c857af4f1
|
||||
* PG16 commit 695f5deb7902865901eb2d50a70523af655c3a00
|
||||
* disallows replacing joins with scans in queries with pseudoconstant quals.
|
||||
* This commit prevents the set_join_pathlist_hook from being called
|
||||
* if any of the join restrictions is a pseudo-constant.
|
||||
* So in these cases, citus has no info on the join, never sees that the query
|
||||
* has an outer join, and ends up producing an incorrect plan.
|
||||
* PG17 fixes this by commit 9e9931d2bf40e2fea447d779c2e133c2c1256ef3
|
||||
* Therefore, we take this extra measure here for PG versions less than 17.
|
||||
* hasOuterJoin can never be true when set_join_pathlist_hook is absent.
|
||||
*/
|
||||
if (hasPseudoconstantQuals(
|
||||
context->plannerRestrictionContext->relationRestrictionContext) &&
|
||||
FindNodeMatchingCheckFunction((Node *) query->jointree, IsOuterJoinExpr))
|
||||
{
|
||||
ereport(ERROR, (errmsg("Distributed queries with outer joins and "
|
||||
"pseudoconstant quals are not supported in PG15 and PG16."),
|
||||
errdetail(
|
||||
"PG15 and PG16 disallow replacing joins with scans when the"
|
||||
" query has pseudoconstant quals"),
|
||||
errhint("Consider upgrading your PG version to PG17+")));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return hasOuterJoin;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2109,7 +2144,6 @@ TransformFunctionRTE(RangeTblEntry *rangeTblEntry)
|
|||
subquery->targetList = lappend(subquery->targetList, targetEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If tupleDesc is NULL we have 2 different cases:
|
||||
*
|
||||
|
|
@ -2159,7 +2193,6 @@ TransformFunctionRTE(RangeTblEntry *rangeTblEntry)
|
|||
columnType = list_nth_oid(rangeTblFunction->funccoltypes,
|
||||
targetColumnIndex);
|
||||
}
|
||||
|
||||
/* use the types in the function definition otherwise */
|
||||
else
|
||||
{
|
||||
|
|
@ -2583,3 +2616,29 @@ GeneratingSubplans(void)
|
|||
{
|
||||
return recursivePlanningDepth > 0;
|
||||
}
|
||||
|
||||
|
||||
#if PG_VERSION_NUM < PG_VERSION_17
|
||||
|
||||
/*
|
||||
* hasPseudoconstantQuals returns true if any of the planner infos in the
|
||||
* relation restriction list of the input relation restriction context
|
||||
* has a pseudoconstant qual
|
||||
*/
|
||||
static bool
|
||||
hasPseudoconstantQuals(RelationRestrictionContext *relationRestrictionContext)
|
||||
{
|
||||
ListCell *objectCell = NULL;
|
||||
foreach(objectCell, relationRestrictionContext->relationRestrictionList)
|
||||
{
|
||||
if (((RelationRestriction *) lfirst(
|
||||
objectCell))->plannerInfo->hasPseudoConstantQuals)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ extern DeferredErrorMessage * DeferErrorIfCannotPushdownSubquery(Query *subquery
|
|||
outerMostQueryHasLimit);
|
||||
extern DeferredErrorMessage * DeferErrorIfUnsupportedUnionQuery(Query *queryTree);
|
||||
extern bool IsJsonTableRTE(RangeTblEntry *rte);
|
||||
extern bool IsOuterJoinExpr(Node *node);
|
||||
|
||||
|
||||
#endif /* QUERY_PUSHDOWN_PLANNING_H */
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ DEPS = {
|
|||
],
|
||||
repeatable=False,
|
||||
),
|
||||
"pg17": TestDeps("minimal_schedule", ["multi_behavioral_analytics_create_table"]),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -343,6 +343,165 @@ NOTICE: drop cascades to 3 other objects
|
|||
DETAIL: drop cascades to table pg17_corr_subq_folding.test
|
||||
drop cascades to table pg17_corr_subq_folding.users
|
||||
drop cascades to table pg17_corr_subq_folding.events
|
||||
-- Queries with outer joins with pseudoconstant quals work only in PG17
|
||||
-- Relevant PG17 commit:
|
||||
-- https://github.com/postgres/postgres/commit/9e9931d2b
|
||||
CREATE SCHEMA pg17_outerjoin;
|
||||
SET search_path to pg17_outerjoin, public;
|
||||
SET citus.next_shard_id TO 20250321;
|
||||
-- issue https://github.com/citusdata/citus/issues/7697
|
||||
create table t0 (vkey int4 , c3 timestamp);
|
||||
create table t3 ( vkey int4 ,c26 timestamp);
|
||||
create table t4 ( vkey int4 );
|
||||
insert into t0 (vkey, c3) values (13,make_timestamp(2019, 10, 23, 15, 34, 50));
|
||||
insert into t3 (vkey,c26) values (1, make_timestamp(2024, 3, 26, 17, 36, 53));
|
||||
insert into t4 (vkey) values (1);
|
||||
select * from
|
||||
(t0 full outer join t3
|
||||
on (t0.c3 = t3.c26 ))
|
||||
where (exists (select * from t4)) order by 1, 2, 3;
|
||||
vkey | c3 | vkey | c26
|
||||
---------------------------------------------------------------------
|
||||
13 | Wed Oct 23 15:34:50 2019 | |
|
||||
| | 1 | Tue Mar 26 17:36:53 2024
|
||||
(2 rows)
|
||||
|
||||
SELECT create_distributed_table('t0', 'vkey');
|
||||
NOTICE: Copying data from local table...
|
||||
NOTICE: copying the data has completed
|
||||
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$pg17_outerjoin.t0$$)
|
||||
create_distributed_table
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
select * from
|
||||
(t0 full outer join t3
|
||||
on (t0.c3 = t3.c26 ))
|
||||
where (exists (select * from t4)) order by 1, 2, 3;
|
||||
vkey | c3 | vkey | c26
|
||||
---------------------------------------------------------------------
|
||||
13 | Wed Oct 23 15:34:50 2019 | |
|
||||
| | 1 | Tue Mar 26 17:36:53 2024
|
||||
(2 rows)
|
||||
|
||||
-- issue https://github.com/citusdata/citus/issues/7696
|
||||
create table t1 ( vkey int4 );
|
||||
create table t2 ( vkey int4 );
|
||||
insert into t2 (vkey) values (5);
|
||||
select * from (t2 full outer join t1 on(t2.vkey = t1.vkey ))
|
||||
where not((85) in (select 1 from t2));
|
||||
vkey | vkey
|
||||
---------------------------------------------------------------------
|
||||
5 |
|
||||
(1 row)
|
||||
|
||||
SELECT create_distributed_table('t1', 'vkey');
|
||||
create_distributed_table
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT create_reference_table('t2');
|
||||
NOTICE: Copying data from local table...
|
||||
NOTICE: copying the data has completed
|
||||
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$pg17_outerjoin.t2$$)
|
||||
create_reference_table
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
select * from (t2 full outer join t1 on(t2.vkey = t1.vkey ))
|
||||
where not((85) in (select 1 from t2));
|
||||
vkey | vkey
|
||||
---------------------------------------------------------------------
|
||||
5 |
|
||||
(1 row)
|
||||
|
||||
-- issue https://github.com/citusdata/citus/issues/7698
|
||||
create table t5 ( vkey int4, c10 int4 );
|
||||
create table t6 ( vkey int4 );
|
||||
insert into t5 (vkey,c10) values (4, -70);
|
||||
insert into t6 (vkey) values (1);
|
||||
select t6.vkey
|
||||
from (t5 right outer join t6
|
||||
on (t5.c10 = t6.vkey))
|
||||
where exists (select * from t6);
|
||||
vkey
|
||||
---------------------------------------------------------------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT create_distributed_table('t5', 'vkey');
|
||||
NOTICE: Copying data from local table...
|
||||
NOTICE: copying the data has completed
|
||||
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$pg17_outerjoin.t5$$)
|
||||
create_distributed_table
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
select t6.vkey
|
||||
from (t5 right outer join t6
|
||||
on (t5.c10 = t6.vkey))
|
||||
where exists (select * from t6);
|
||||
vkey
|
||||
---------------------------------------------------------------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
-- issue https://github.com/citusdata/citus/issues/7119
|
||||
-- this test was removed in
|
||||
-- https://github.com/citusdata/citus/commit/a5ce601c0
|
||||
-- Citus doesn't support it in PG15 and PG16, but supports it in PG17
|
||||
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||
CREATE TABLE events_table_local AS SELECT * FROM events_table;
|
||||
SET client_min_messages TO DEBUG1;
|
||||
-- subquery in FROM -> FROM -> WHERE -> WHERE should be replaced if
|
||||
-- it contains onle local tables
|
||||
-- Later the upper level query is also recursively planned due to LIMIT
|
||||
SELECT user_id, array_length(events_table, 1)
|
||||
FROM (
|
||||
SELECT user_id, array_agg(event ORDER BY time) AS events_table
|
||||
FROM (
|
||||
SELECT
|
||||
u.user_id, e.event_type::text AS event, e.time
|
||||
FROM
|
||||
users_table AS u,
|
||||
events_table AS e
|
||||
WHERE u.user_id = e.user_id AND
|
||||
u.user_id IN
|
||||
(
|
||||
SELECT
|
||||
user_id
|
||||
FROM
|
||||
users_table
|
||||
WHERE value_2 >= 5
|
||||
AND EXISTS (SELECT user_id FROM events_table_local WHERE event_type > 1 AND event_type <= 3 AND value_3 > 1)
|
||||
AND NOT EXISTS (SELECT user_id FROM events_table WHERE event_type > 3 AND event_type <= 4 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||
LIMIT 5
|
||||
)
|
||||
) t
|
||||
GROUP BY user_id
|
||||
) q
|
||||
ORDER BY 2 DESC, 1;
|
||||
DEBUG: generating subplan XXX_1 for subquery SELECT user_id FROM pg17_outerjoin.events_table_local WHERE ((event_type OPERATOR(pg_catalog.>) 1) AND (event_type OPERATOR(pg_catalog.<=) 3) AND (value_3 OPERATOR(pg_catalog.>) (1)::double precision))
|
||||
DEBUG: push down of limit count: 5
|
||||
DEBUG: generating subplan XXX_2 for subquery SELECT user_id FROM public.users_table WHERE ((value_2 OPERATOR(pg_catalog.>=) 5) AND (EXISTS (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) AND (NOT (EXISTS (SELECT events_table.user_id FROM public.events_table WHERE ((events_table.event_type OPERATOR(pg_catalog.>) 3) AND (events_table.event_type OPERATOR(pg_catalog.<=) 4) AND (events_table.value_3 OPERATOR(pg_catalog.>) (1)::double precision) AND (events_table.user_id OPERATOR(pg_catalog.=) users_table.user_id)))))) LIMIT 5
|
||||
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT user_id, array_length(events_table, 1) AS array_length FROM (SELECT t.user_id, array_agg(t.event ORDER BY t."time") AS events_table FROM (SELECT u.user_id, (e.event_type)::text AS event, e."time" FROM public.users_table u, public.events_table e WHERE ((u.user_id OPERATOR(pg_catalog.=) e.user_id) AND (u.user_id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))))) t GROUP BY t.user_id) q ORDER BY (array_length(events_table, 1)) DESC, user_id
|
||||
user_id | array_length
|
||||
---------------------------------------------------------------------
|
||||
5 | 364
|
||||
(1 row)
|
||||
|
||||
RESET search_path;
|
||||
SET citus.next_shard_id TO 20240023;
|
||||
SET client_min_messages TO ERROR;
|
||||
DROP SCHEMA pg17_outerjoin CASCADE;
|
||||
RESET client_min_messages;
|
||||
\if :server_version_ge_17
|
||||
\else
|
||||
\q
|
||||
|
|
|
|||
|
|
@ -287,6 +287,151 @@ NOTICE: drop cascades to 3 other objects
|
|||
DETAIL: drop cascades to table pg17_corr_subq_folding.test
|
||||
drop cascades to table pg17_corr_subq_folding.users
|
||||
drop cascades to table pg17_corr_subq_folding.events
|
||||
-- Queries with outer joins with pseudoconstant quals work only in PG17
|
||||
-- Relevant PG17 commit:
|
||||
-- https://github.com/postgres/postgres/commit/9e9931d2b
|
||||
CREATE SCHEMA pg17_outerjoin;
|
||||
SET search_path to pg17_outerjoin, public;
|
||||
SET citus.next_shard_id TO 20250321;
|
||||
-- issue https://github.com/citusdata/citus/issues/7697
|
||||
create table t0 (vkey int4 , c3 timestamp);
|
||||
create table t3 ( vkey int4 ,c26 timestamp);
|
||||
create table t4 ( vkey int4 );
|
||||
insert into t0 (vkey, c3) values (13,make_timestamp(2019, 10, 23, 15, 34, 50));
|
||||
insert into t3 (vkey,c26) values (1, make_timestamp(2024, 3, 26, 17, 36, 53));
|
||||
insert into t4 (vkey) values (1);
|
||||
select * from
|
||||
(t0 full outer join t3
|
||||
on (t0.c3 = t3.c26 ))
|
||||
where (exists (select * from t4)) order by 1, 2, 3;
|
||||
vkey | c3 | vkey | c26
|
||||
---------------------------------------------------------------------
|
||||
13 | Wed Oct 23 15:34:50 2019 | |
|
||||
| | 1 | Tue Mar 26 17:36:53 2024
|
||||
(2 rows)
|
||||
|
||||
SELECT create_distributed_table('t0', 'vkey');
|
||||
NOTICE: Copying data from local table...
|
||||
NOTICE: copying the data has completed
|
||||
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$pg17_outerjoin.t0$$)
|
||||
create_distributed_table
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
select * from
|
||||
(t0 full outer join t3
|
||||
on (t0.c3 = t3.c26 ))
|
||||
where (exists (select * from t4)) order by 1, 2, 3;
|
||||
ERROR: Distributed queries with outer joins and pseudoconstant quals are not supported in PG15 and PG16.
|
||||
DETAIL: PG15 and PG16 disallow replacing joins with scans when the query has pseudoconstant quals
|
||||
HINT: Consider upgrading your PG version to PG17+
|
||||
-- issue https://github.com/citusdata/citus/issues/7696
|
||||
create table t1 ( vkey int4 );
|
||||
create table t2 ( vkey int4 );
|
||||
insert into t2 (vkey) values (5);
|
||||
select * from (t2 full outer join t1 on(t2.vkey = t1.vkey ))
|
||||
where not((85) in (select 1 from t2));
|
||||
vkey | vkey
|
||||
---------------------------------------------------------------------
|
||||
5 |
|
||||
(1 row)
|
||||
|
||||
SELECT create_distributed_table('t1', 'vkey');
|
||||
create_distributed_table
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT create_reference_table('t2');
|
||||
NOTICE: Copying data from local table...
|
||||
NOTICE: copying the data has completed
|
||||
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$pg17_outerjoin.t2$$)
|
||||
create_reference_table
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
select * from (t2 full outer join t1 on(t2.vkey = t1.vkey ))
|
||||
where not((85) in (select 1 from t2));
|
||||
ERROR: Distributed queries with outer joins and pseudoconstant quals are not supported in PG15 and PG16.
|
||||
DETAIL: PG15 and PG16 disallow replacing joins with scans when the query has pseudoconstant quals
|
||||
HINT: Consider upgrading your PG version to PG17+
|
||||
-- issue https://github.com/citusdata/citus/issues/7698
|
||||
create table t5 ( vkey int4, c10 int4 );
|
||||
create table t6 ( vkey int4 );
|
||||
insert into t5 (vkey,c10) values (4, -70);
|
||||
insert into t6 (vkey) values (1);
|
||||
select t6.vkey
|
||||
from (t5 right outer join t6
|
||||
on (t5.c10 = t6.vkey))
|
||||
where exists (select * from t6);
|
||||
vkey
|
||||
---------------------------------------------------------------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT create_distributed_table('t5', 'vkey');
|
||||
NOTICE: Copying data from local table...
|
||||
NOTICE: copying the data has completed
|
||||
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$pg17_outerjoin.t5$$)
|
||||
create_distributed_table
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
select t6.vkey
|
||||
from (t5 right outer join t6
|
||||
on (t5.c10 = t6.vkey))
|
||||
where exists (select * from t6);
|
||||
ERROR: Distributed queries with outer joins and pseudoconstant quals are not supported in PG15 and PG16.
|
||||
DETAIL: PG15 and PG16 disallow replacing joins with scans when the query has pseudoconstant quals
|
||||
HINT: Consider upgrading your PG version to PG17+
|
||||
-- issue https://github.com/citusdata/citus/issues/7119
|
||||
-- this test was removed in
|
||||
-- https://github.com/citusdata/citus/commit/a5ce601c0
|
||||
-- Citus doesn't support it in PG15 and PG16, but supports it in PG17
|
||||
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||
CREATE TABLE events_table_local AS SELECT * FROM events_table;
|
||||
SET client_min_messages TO DEBUG1;
|
||||
-- subquery in FROM -> FROM -> WHERE -> WHERE should be replaced if
|
||||
-- it contains onle local tables
|
||||
-- Later the upper level query is also recursively planned due to LIMIT
|
||||
SELECT user_id, array_length(events_table, 1)
|
||||
FROM (
|
||||
SELECT user_id, array_agg(event ORDER BY time) AS events_table
|
||||
FROM (
|
||||
SELECT
|
||||
u.user_id, e.event_type::text AS event, e.time
|
||||
FROM
|
||||
users_table AS u,
|
||||
events_table AS e
|
||||
WHERE u.user_id = e.user_id AND
|
||||
u.user_id IN
|
||||
(
|
||||
SELECT
|
||||
user_id
|
||||
FROM
|
||||
users_table
|
||||
WHERE value_2 >= 5
|
||||
AND EXISTS (SELECT user_id FROM events_table_local WHERE event_type > 1 AND event_type <= 3 AND value_3 > 1)
|
||||
AND NOT EXISTS (SELECT user_id FROM events_table WHERE event_type > 3 AND event_type <= 4 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||
LIMIT 5
|
||||
)
|
||||
) t
|
||||
GROUP BY user_id
|
||||
) q
|
||||
ORDER BY 2 DESC, 1;
|
||||
DEBUG: generating subplan XXX_1 for subquery SELECT user_id FROM pg17_outerjoin.events_table_local WHERE ((event_type OPERATOR(pg_catalog.>) 1) AND (event_type OPERATOR(pg_catalog.<=) 3) AND (value_3 OPERATOR(pg_catalog.>) (1)::double precision))
|
||||
ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns
|
||||
RESET search_path;
|
||||
SET citus.next_shard_id TO 20240023;
|
||||
SET client_min_messages TO ERROR;
|
||||
DROP SCHEMA pg17_outerjoin CASCADE;
|
||||
RESET client_min_messages;
|
||||
\if :server_version_ge_17
|
||||
\else
|
||||
\q
|
||||
|
|
|
|||
|
|
@ -170,6 +170,109 @@ RESET client_min_messages;
|
|||
RESET search_path;
|
||||
DROP SCHEMA pg17_corr_subq_folding CASCADE;
|
||||
|
||||
-- Queries with outer joins with pseudoconstant quals work only in PG17
|
||||
-- Relevant PG17 commit:
|
||||
-- https://github.com/postgres/postgres/commit/9e9931d2b
|
||||
|
||||
CREATE SCHEMA pg17_outerjoin;
|
||||
SET search_path to pg17_outerjoin, public;
|
||||
SET citus.next_shard_id TO 20250321;
|
||||
|
||||
-- issue https://github.com/citusdata/citus/issues/7697
|
||||
create table t0 (vkey int4 , c3 timestamp);
|
||||
create table t3 ( vkey int4 ,c26 timestamp);
|
||||
create table t4 ( vkey int4 );
|
||||
insert into t0 (vkey, c3) values (13,make_timestamp(2019, 10, 23, 15, 34, 50));
|
||||
insert into t3 (vkey,c26) values (1, make_timestamp(2024, 3, 26, 17, 36, 53));
|
||||
insert into t4 (vkey) values (1);
|
||||
|
||||
select * from
|
||||
(t0 full outer join t3
|
||||
on (t0.c3 = t3.c26 ))
|
||||
where (exists (select * from t4)) order by 1, 2, 3;
|
||||
|
||||
SELECT create_distributed_table('t0', 'vkey');
|
||||
|
||||
select * from
|
||||
(t0 full outer join t3
|
||||
on (t0.c3 = t3.c26 ))
|
||||
where (exists (select * from t4)) order by 1, 2, 3;
|
||||
|
||||
-- issue https://github.com/citusdata/citus/issues/7696
|
||||
create table t1 ( vkey int4 );
|
||||
create table t2 ( vkey int4 );
|
||||
insert into t2 (vkey) values (5);
|
||||
|
||||
select * from (t2 full outer join t1 on(t2.vkey = t1.vkey ))
|
||||
where not((85) in (select 1 from t2));
|
||||
|
||||
SELECT create_distributed_table('t1', 'vkey');
|
||||
SELECT create_reference_table('t2');
|
||||
|
||||
select * from (t2 full outer join t1 on(t2.vkey = t1.vkey ))
|
||||
where not((85) in (select 1 from t2));
|
||||
|
||||
-- issue https://github.com/citusdata/citus/issues/7698
|
||||
create table t5 ( vkey int4, c10 int4 );
|
||||
create table t6 ( vkey int4 );
|
||||
insert into t5 (vkey,c10) values (4, -70);
|
||||
insert into t6 (vkey) values (1);
|
||||
|
||||
select t6.vkey
|
||||
from (t5 right outer join t6
|
||||
on (t5.c10 = t6.vkey))
|
||||
where exists (select * from t6);
|
||||
|
||||
SELECT create_distributed_table('t5', 'vkey');
|
||||
|
||||
select t6.vkey
|
||||
from (t5 right outer join t6
|
||||
on (t5.c10 = t6.vkey))
|
||||
where exists (select * from t6);
|
||||
|
||||
-- issue https://github.com/citusdata/citus/issues/7119
|
||||
-- this test was removed in
|
||||
-- https://github.com/citusdata/citus/commit/a5ce601c0
|
||||
-- Citus doesn't support it in PG15 and PG16, but supports it in PG17
|
||||
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||
CREATE TABLE events_table_local AS SELECT * FROM events_table;
|
||||
|
||||
SET client_min_messages TO DEBUG1;
|
||||
-- subquery in FROM -> FROM -> WHERE -> WHERE should be replaced if
|
||||
-- it contains onle local tables
|
||||
-- Later the upper level query is also recursively planned due to LIMIT
|
||||
SELECT user_id, array_length(events_table, 1)
|
||||
FROM (
|
||||
SELECT user_id, array_agg(event ORDER BY time) AS events_table
|
||||
FROM (
|
||||
SELECT
|
||||
u.user_id, e.event_type::text AS event, e.time
|
||||
FROM
|
||||
users_table AS u,
|
||||
events_table AS e
|
||||
WHERE u.user_id = e.user_id AND
|
||||
u.user_id IN
|
||||
(
|
||||
SELECT
|
||||
user_id
|
||||
FROM
|
||||
users_table
|
||||
WHERE value_2 >= 5
|
||||
AND EXISTS (SELECT user_id FROM events_table_local WHERE event_type > 1 AND event_type <= 3 AND value_3 > 1)
|
||||
AND NOT EXISTS (SELECT user_id FROM events_table WHERE event_type > 3 AND event_type <= 4 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||
LIMIT 5
|
||||
)
|
||||
) t
|
||||
GROUP BY user_id
|
||||
) q
|
||||
ORDER BY 2 DESC, 1;
|
||||
|
||||
RESET search_path;
|
||||
SET citus.next_shard_id TO 20240023;
|
||||
SET client_min_messages TO ERROR;
|
||||
DROP SCHEMA pg17_outerjoin CASCADE;
|
||||
RESET client_min_messages;
|
||||
|
||||
\if :server_version_ge_17
|
||||
\else
|
||||
\q
|
||||
|
|
|
|||
Loading…
Reference in New Issue