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 */
|
/* Local functions forward declarations */
|
||||||
static bool JoinTreeContainsSubqueryWalker(Node *joinTreeNode, void *context);
|
static bool JoinTreeContainsSubqueryWalker(Node *joinTreeNode, void *context);
|
||||||
static bool IsFunctionOrValuesRTE(Node *node);
|
static bool IsFunctionOrValuesRTE(Node *node);
|
||||||
static bool IsOuterJoinExpr(Node *node);
|
|
||||||
static bool WindowPartitionOnDistributionColumn(Query *query);
|
static bool WindowPartitionOnDistributionColumn(Query *query);
|
||||||
static DeferredErrorMessage * DeferErrorIfFromClauseRecurs(Query *queryTree);
|
static DeferredErrorMessage * DeferErrorIfFromClauseRecurs(Query *queryTree);
|
||||||
static RecurringTuplesType FromClauseRecurringTupleType(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.
|
* IsOuterJoinExpr returns whether the given node is an outer join expression.
|
||||||
*/
|
*/
|
||||||
static bool
|
bool
|
||||||
IsOuterJoinExpr(Node *node)
|
IsOuterJoinExpr(Node *node)
|
||||||
{
|
{
|
||||||
bool isOuterJoin = false;
|
bool isOuterJoin = false;
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,8 @@ static bool ShouldRecursivelyPlanNonColocatedSubqueries(Query *subquery,
|
||||||
RecursivePlanningContext *
|
RecursivePlanningContext *
|
||||||
context);
|
context);
|
||||||
static bool ContainsSubquery(Query *query);
|
static bool ContainsSubquery(Query *query);
|
||||||
static bool ShouldRecursivelyPlanOuterJoins(RecursivePlanningContext *context);
|
static bool ShouldRecursivelyPlanOuterJoins(Query *query,
|
||||||
|
RecursivePlanningContext *context);
|
||||||
static void RecursivelyPlanNonColocatedSubqueries(Query *subquery,
|
static void RecursivelyPlanNonColocatedSubqueries(Query *subquery,
|
||||||
RecursivePlanningContext *context);
|
RecursivePlanningContext *context);
|
||||||
static void RecursivelyPlanNonColocatedJoinWalker(Node *joinNode,
|
static void RecursivelyPlanNonColocatedJoinWalker(Node *joinNode,
|
||||||
|
|
@ -192,6 +193,10 @@ static Query * CreateOuterSubquery(RangeTblEntry *rangeTableEntry,
|
||||||
List *outerSubqueryTargetList);
|
List *outerSubqueryTargetList);
|
||||||
static List * GenerateRequiredColNamesFromTargetList(List *targetList);
|
static List * GenerateRequiredColNamesFromTargetList(List *targetList);
|
||||||
static char * GetRelationNameAndAliasName(RangeTblEntry *rangeTablentry);
|
static char * GetRelationNameAndAliasName(RangeTblEntry *rangeTablentry);
|
||||||
|
#if PG_VERSION_NUM < PG_VERSION_17
|
||||||
|
static bool hasPseudoconstantQuals(
|
||||||
|
RelationRestrictionContext *relationRestrictionContext);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GenerateSubplansForSubqueriesAndCTEs is a wrapper around RecursivelyPlanSubqueriesAndCTEs.
|
* 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
|
* result and logical planner can handle the new query since it's of the from
|
||||||
* "<recurring> LEFT JOIN <recurring>".
|
* "<recurring> LEFT JOIN <recurring>".
|
||||||
*/
|
*/
|
||||||
if (ShouldRecursivelyPlanOuterJoins(context))
|
if (ShouldRecursivelyPlanOuterJoins(query, context))
|
||||||
{
|
{
|
||||||
RecursivelyPlanRecurringTupleOuterJoinWalker((Node *) query->jointree,
|
RecursivelyPlanRecurringTupleOuterJoinWalker((Node *) query->jointree,
|
||||||
query, context);
|
query, context);
|
||||||
|
|
@ -468,7 +473,7 @@ ContainsSubquery(Query *query)
|
||||||
* join(s) that might need to be recursively planned.
|
* join(s) that might need to be recursively planned.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
ShouldRecursivelyPlanOuterJoins(RecursivePlanningContext *context)
|
ShouldRecursivelyPlanOuterJoins(Query *query, RecursivePlanningContext *context)
|
||||||
{
|
{
|
||||||
if (!context || !context->plannerRestrictionContext ||
|
if (!context || !context->plannerRestrictionContext ||
|
||||||
!context->plannerRestrictionContext->joinRestrictionContext)
|
!context->plannerRestrictionContext->joinRestrictionContext)
|
||||||
|
|
@ -477,7 +482,37 @@ ShouldRecursivelyPlanOuterJoins(RecursivePlanningContext *context)
|
||||||
"planning 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);
|
subquery->targetList = lappend(subquery->targetList, targetEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If tupleDesc is NULL we have 2 different cases:
|
* If tupleDesc is NULL we have 2 different cases:
|
||||||
*
|
*
|
||||||
|
|
@ -2159,7 +2193,6 @@ TransformFunctionRTE(RangeTblEntry *rangeTblEntry)
|
||||||
columnType = list_nth_oid(rangeTblFunction->funccoltypes,
|
columnType = list_nth_oid(rangeTblFunction->funccoltypes,
|
||||||
targetColumnIndex);
|
targetColumnIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use the types in the function definition otherwise */
|
/* use the types in the function definition otherwise */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2583,3 +2616,29 @@ GeneratingSubplans(void)
|
||||||
{
|
{
|
||||||
return recursivePlanningDepth > 0;
|
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);
|
outerMostQueryHasLimit);
|
||||||
extern DeferredErrorMessage * DeferErrorIfUnsupportedUnionQuery(Query *queryTree);
|
extern DeferredErrorMessage * DeferErrorIfUnsupportedUnionQuery(Query *queryTree);
|
||||||
extern bool IsJsonTableRTE(RangeTblEntry *rte);
|
extern bool IsJsonTableRTE(RangeTblEntry *rte);
|
||||||
|
extern bool IsOuterJoinExpr(Node *node);
|
||||||
|
|
||||||
|
|
||||||
#endif /* QUERY_PUSHDOWN_PLANNING_H */
|
#endif /* QUERY_PUSHDOWN_PLANNING_H */
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,7 @@ DEPS = {
|
||||||
],
|
],
|
||||||
repeatable=False,
|
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
|
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.users
|
||||||
drop cascades to table pg17_corr_subq_folding.events
|
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
|
\if :server_version_ge_17
|
||||||
\else
|
\else
|
||||||
\q
|
\q
|
||||||
|
|
|
||||||
|
|
@ -287,6 +287,151 @@ NOTICE: drop cascades to 3 other objects
|
||||||
DETAIL: drop cascades to table pg17_corr_subq_folding.test
|
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.users
|
||||||
drop cascades to table pg17_corr_subq_folding.events
|
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
|
\if :server_version_ge_17
|
||||||
\else
|
\else
|
||||||
\q
|
\q
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,109 @@ RESET client_min_messages;
|
||||||
RESET search_path;
|
RESET search_path;
|
||||||
DROP SCHEMA pg17_corr_subq_folding CASCADE;
|
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
|
\if :server_version_ge_17
|
||||||
\else
|
\else
|
||||||
\q
|
\q
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue