Merge branch 'main' into view-citus-nodes

pull/7968/head
Alper Kocatas 2025-05-12 14:32:56 +03:00 committed by GitHub
commit 54c4de845b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 475 additions and 8 deletions

View File

@ -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;

View File

@ -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

View File

@ -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 */

View File

@ -224,6 +224,7 @@ DEPS = {
], ],
repeatable=False, repeatable=False,
), ),
"pg17": TestDeps("minimal_schedule", ["multi_behavioral_analytics_create_table"]),
} }

View File

@ -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

View File

@ -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

View File

@ -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