Detect vars referencing outer queries in local-dist table

We were checking just range table list to detect local-dist table joins
but there can be vars referencing to outer queries which belong to a
distributed table.

The current logic is we keep track of rtable list when we are descending
in the query tree. At any level, we find the range table entries that
are references by the vars of the current subquery. Then we use this to
determine if we should convert local-distributed tables to a subquery.
pull/4470/head
Sait Talha Nisanci 2020-12-29 13:54:07 +03:00
parent 75c533ca02
commit 69f4b0f297
10 changed files with 581 additions and 29 deletions

View File

@ -355,27 +355,6 @@ AllRangeTableEntriesHaveUniqueIndex(List *rangeTableEntryDetailsList)
} }
/*
* ShouldConvertLocalTableJoinsToSubqueries returns true if we should
* convert local-dist table joins to subqueries.
*/
bool
ShouldConvertLocalTableJoinsToSubqueries(List *rangeTableList)
{
if (LocalTableJoinPolicy == LOCAL_JOIN_POLICY_NEVER)
{
/* user doesn't want Citus to enable local table joins */
return false;
}
if (!ContainsLocalTableDistributedTableJoin(rangeTableList))
{
return false;
}
return true;
}
/* /*
* HasConstantFilterOnUniqueColumn returns true if the given rangeTableEntry has a constant * HasConstantFilterOnUniqueColumn returns true if the given rangeTableEntry has a constant
* filter on a unique column. * filter on a unique column.

View File

@ -920,7 +920,7 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
ExtractRangeTableEntryWalker((Node *) originalQuery, &rangeTableList); ExtractRangeTableEntryWalker((Node *) originalQuery, &rangeTableList);
} }
bool containsLocalTableDistributedTableJoin = bool containsLocalTableDistributedTableJoin =
ContainsLocalTableDistributedTableJoin(queryTree->rtable); ContainsLocalTableDistributedTableJoin(queryTree->rtable, NULL, NULL);
RangeTblEntry *rangeTableEntry = NULL; RangeTblEntry *rangeTableEntry = NULL;
foreach_ptr(rangeTableEntry, rangeTableList) foreach_ptr(rangeTableEntry, rangeTableList)

View File

@ -74,6 +74,7 @@
#include "distributed/relation_restriction_equivalence.h" #include "distributed/relation_restriction_equivalence.h"
#include "distributed/log_utils.h" #include "distributed/log_utils.h"
#include "distributed/shard_pruning.h" #include "distributed/shard_pruning.h"
#include "distributed/var_utils.h"
#include "distributed/version_compat.h" #include "distributed/version_compat.h"
#include "lib/stringinfo.h" #include "lib/stringinfo.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
@ -111,6 +112,7 @@ struct RecursivePlanningContextInternal
uint64 planId; uint64 planId;
bool allDistributionKeysInQueryAreEqual; /* used for some optimizations */ bool allDistributionKeysInQueryAreEqual; /* used for some optimizations */
List *subPlanList; List *subPlanList;
List *rtableList; /* list of rtables */
PlannerRestrictionContext *plannerRestrictionContext; PlannerRestrictionContext *plannerRestrictionContext;
}; };
@ -144,6 +146,9 @@ static DeferredErrorMessage * RecursivelyPlanSubqueriesAndCTEs(Query *query,
static bool ShouldRecursivelyPlanNonColocatedSubqueries(Query *subquery, static bool ShouldRecursivelyPlanNonColocatedSubqueries(Query *subquery,
RecursivePlanningContext * RecursivePlanningContext *
context); context);
static bool ShouldConvertLocalTableJoinsToSubqueries(List *rangeTableList,
List *tableList, List *rtableList);
static bool ContainsSubquery(Query *query); static bool ContainsSubquery(Query *query);
static void RecursivelyPlanNonColocatedSubqueries(Query *subquery, static void RecursivelyPlanNonColocatedSubqueries(Query *subquery,
RecursivePlanningContext *context); RecursivePlanningContext *context);
@ -195,6 +200,9 @@ 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);
static void ContainsLocalTableDistributedTableVars(List *tableList, List *rtableList,
bool *containsLocalTable,
bool *containsDistributedTable);
/* /*
* GenerateSubplansForSubqueriesAndCTEs is a wrapper around RecursivelyPlanSubqueriesAndCTEs. * GenerateSubplansForSubqueriesAndCTEs is a wrapper around RecursivelyPlanSubqueriesAndCTEs.
@ -219,6 +227,7 @@ GenerateSubplansForSubqueriesAndCTEs(uint64 planId, Query *originalQuery,
context.planId = planId; context.planId = planId;
context.subPlanList = NIL; context.subPlanList = NIL;
context.plannerRestrictionContext = plannerRestrictionContext; context.plannerRestrictionContext = plannerRestrictionContext;
context.rtableList = NIL;
/* /*
* Calculating the distribution key equality upfront is a trade-off for us. * Calculating the distribution key equality upfront is a trade-off for us.
@ -276,6 +285,8 @@ GenerateSubplansForSubqueriesAndCTEs(uint64 planId, Query *originalQuery,
static DeferredErrorMessage * static DeferredErrorMessage *
RecursivelyPlanSubqueriesAndCTEs(Query *query, RecursivePlanningContext *context) RecursivelyPlanSubqueriesAndCTEs(Query *query, RecursivePlanningContext *context)
{ {
context->rtableList = lcons(query->rtable, context->rtableList);
DeferredErrorMessage *error = RecursivelyPlanCTEs(query, context); DeferredErrorMessage *error = RecursivelyPlanCTEs(query, context);
if (error != NULL) if (error != NULL)
{ {
@ -350,8 +361,9 @@ RecursivelyPlanSubqueriesAndCTEs(Query *query, RecursivePlanningContext *context
RecursivelyPlanNonColocatedSubqueries(query, context); RecursivelyPlanNonColocatedSubqueries(query, context);
} }
List *tableList = PullAllRangeTablesEntries(query, context->rtableList);
if (ShouldConvertLocalTableJoinsToSubqueries(query->rtable)) if (ShouldConvertLocalTableJoinsToSubqueries(query->rtable, tableList,
context->rtableList))
{ {
/* /*
* Logical planner cannot handle "local_table" [OUTER] JOIN "dist_table", or * Logical planner cannot handle "local_table" [OUTER] JOIN "dist_table", or
@ -361,11 +373,64 @@ RecursivelyPlanSubqueriesAndCTEs(Query *query, RecursivePlanningContext *context
RecursivelyPlanLocalTableJoins(query, context); RecursivelyPlanLocalTableJoins(query, context);
} }
context->rtableList = list_delete_first(context->rtableList);
return NULL; return NULL;
} }
/*
* ShouldConvertLocalTableJoinsToSubqueries returns true if we should
* convert local-dist table joins to subqueries.
*/
static bool
ShouldConvertLocalTableJoinsToSubqueries(List *rangeTableList, List *tableList,
List *rtableList)
{
if (LocalTableJoinPolicy == LOCAL_JOIN_POLICY_NEVER)
{
/* user doesn't want Citus to enable local table joins */
return false;
}
bool containsDistributedTable = false;
bool containsLocalTable = false;
if (ContainsLocalTableDistributedTableJoin(rangeTableList, &containsLocalTable,
&containsDistributedTable))
{
return true;
}
/* if we have vars that references local or distributed tables, it means we need to do subquery-conversion */
ContainsLocalTableDistributedTableVars(tableList, rtableList, &containsLocalTable,
&containsDistributedTable);
return containsDistributedTable && containsLocalTable;
}
static void
ContainsLocalTableDistributedTableVars(List *tableList, List *rtableList,
bool *containsLocalTable,
bool *containsDistributedTable)
{
RangeTblEntry *rte = NULL;
foreach_ptr(rte, tableList)
{
if (IsDistributedOrReferenceTableRTE((Node *) rte))
{
*containsDistributedTable = true;
}
else if (IsRecursivelyPlannableRelation(rte) &&
IsLocalTableRteOrMatView((Node *) rte))
{
/* we consider citus local tables as local table */
*containsLocalTable = true;
}
}
}
/* /*
* GetPlannerRestrictionContext returns the planner restriction context * GetPlannerRestrictionContext returns the planner restriction context
* from the given context. * from the given context.
@ -1576,7 +1641,8 @@ IsRecursivelyPlannableRelation(RangeTblEntry *rangeTableEntry)
* or reference table. * or reference table.
*/ */
bool bool
ContainsLocalTableDistributedTableJoin(List *rangeTableList) ContainsLocalTableDistributedTableJoin(List *rangeTableList, bool *containsLocalTableOut,
bool *containsDistributedTableOut)
{ {
bool containsLocalTable = false; bool containsLocalTable = false;
bool containsDistributedTable = false; bool containsDistributedTable = false;
@ -1596,7 +1662,14 @@ ContainsLocalTableDistributedTableJoin(List *rangeTableList)
containsLocalTable = true; containsLocalTable = true;
} }
} }
if (containsLocalTableOut)
{
*containsLocalTableOut = containsLocalTable;
}
if (containsDistributedTableOut)
{
*containsDistributedTableOut = containsDistributedTable;
}
return containsLocalTable && containsDistributedTable; return containsLocalTable && containsDistributedTable;
} }

View File

@ -0,0 +1,112 @@
/*-------------------------------------------------------------------------
*
* var_utils.c
* Utilities regarding vars
*
* Copyright (c) Citus Data, Inc.
*-------------------------------------------------------------------------
*/
#include "distributed/pg_version_constants.h"
#include "postgres.h"
#include "distributed/var_utils.h"
#include "parser/parsetree.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "nodes/nodes.h"
#include "nodes/nodeFuncs.h"
#include "nodes/pg_list.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "nodes/primnodes.h"
#if PG_VERSION_NUM >= PG_VERSION_12
#include "nodes/pathnodes.h"
#else
#include "nodes/relation.h"
#endif
typedef struct PullTableContext
{
List *rteList;
List *rtableList;
}PullTableContext;
static bool PullAllRangeTablesEntriesWalker(Node *node,
PullTableContext *pullTableContext);
/*
* PullAllRangeTablesEntries collects all the range table entries that are referenced
* in the given query. The range table entry could be outside of the given query but a var
* could exist that points to it.
* rtableList should contain list of rtables up to this query from the top query.
*/
List *
PullAllRangeTablesEntries(Query *query, List *rtableList)
{
PullTableContext p;
p.rtableList = rtableList;
p.rteList = NIL;
query_or_expression_tree_walker((Node *) query,
PullAllRangeTablesEntriesWalker,
(void *) &p,
0);
return p.rteList;
}
/*
* PullAllRangeTablesEntriesWalker descends into the given node and collects
* all range table entries that are referenced by a Var.
*/
static bool
PullAllRangeTablesEntriesWalker(Node *node, PullTableContext *pullTableContext)
{
if (node == NULL)
{
return false;
}
if (IsA(node, Var))
{
Var *var = (Var *) node;
List *rtableList = pullTableContext->rtableList;
int index = var->varlevelsup;
if (index >= list_length(rtableList) || index < 0)
{
ereport(ERROR, (errmsg("unexpected state: %d is not between 0-%d", index,
list_length(rtableList))));
}
List *rtable = (List *) list_nth(rtableList, index);
RangeTblEntry *rte = (RangeTblEntry *) list_nth(rtable, var->varno - 1);
pullTableContext->rteList = lappend(pullTableContext->rteList, rte);
return false;
}
if (IsA(node, PlaceHolderVar))
{
/* PlaceHolderVar *phv = (PlaceHolderVar *) node; */
/* we don't want to look into the contained expression */
return false;
}
if (IsA(node, Query))
{
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
Query *query = (Query *) node;
pullTableContext->rtableList = lcons(query->rtable, pullTableContext->rtableList);
bool result = query_tree_walker(query, PullAllRangeTablesEntriesWalker,
(void *) pullTableContext, 0);
pullTableContext->rtableList = list_delete_first(pullTableContext->rtableList);
return result;
}
return expression_tree_walker(node, PullAllRangeTablesEntriesWalker,
(void *) pullTableContext);
}

View File

@ -27,7 +27,6 @@ typedef enum
extern int LocalTableJoinPolicy; extern int LocalTableJoinPolicy;
extern bool ShouldConvertLocalTableJoinsToSubqueries(List *rangeTableList);
extern void RecursivelyPlanLocalTableJoins(Query *query, extern void RecursivelyPlanLocalTableJoins(Query *query,
RecursivePlanningContext *context); RecursivePlanningContext *context);

View File

@ -43,7 +43,9 @@ extern Query * BuildReadIntermediateResultsArrayQuery(List *targetEntryList,
List *resultIdList, List *resultIdList,
bool useBinaryCopyFormat); bool useBinaryCopyFormat);
extern bool GeneratingSubplans(void); extern bool GeneratingSubplans(void);
extern bool ContainsLocalTableDistributedTableJoin(List *rangeTableList); extern bool ContainsLocalTableDistributedTableJoin(List *rangeTableList,
bool *containsLocalTableOut,
bool *containsDistributedTableOut);
extern void ReplaceRTERelationWithRteSubquery(RangeTblEntry *rangeTableEntry, extern void ReplaceRTERelationWithRteSubquery(RangeTblEntry *rangeTableEntry,
List *requiredAttrNumbers, List *requiredAttrNumbers,
RecursivePlanningContext *context); RecursivePlanningContext *context);

View File

@ -0,0 +1,17 @@
/*-------------------------------------------------------------------------
*
* var_utils.h
* Utilities regarding vars
*
* Copyright (c) Citus Data, Inc.
*-------------------------------------------------------------------------
*/
#ifndef VAR_UTILS
#define VAR_UTILS
#include "nodes/pg_list.h"
#include "nodes/parsenodes.h"
List * PullAllRangeTablesEntries(Query *query, List *rtableList);
#endif

View File

@ -0,0 +1,285 @@
CREATE SCHEMA local_table_join_vars;
SET search_path TO local_table_join_vars;
SET client_min_messages to ERROR;
SELECT master_add_node('localhost', :master_port, groupId => 0) AS coordinator_nodeid \gset
SET client_min_messages TO DEBUG1;
CREATE TABLE postgres_table (key int, value text, value_2 jsonb);
CREATE TABLE reference_table (key int, value text, value_2 jsonb);
SELECT create_reference_table('reference_table');
create_reference_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE distributed_table (key int, value text, value_2 jsonb);
SELECT create_distributed_table('distributed_table', 'key');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE distributed_table_pkey (key int primary key, value text, value_2 jsonb);
DEBUG: CREATE TABLE / PRIMARY KEY will create implicit index "distributed_table_pkey_pkey" for table "distributed_table_pkey"
SELECT create_distributed_table('distributed_table_pkey', 'key');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE distributed_table_windex (key int primary key, value text, value_2 jsonb);
DEBUG: CREATE TABLE / PRIMARY KEY will create implicit index "distributed_table_windex_pkey" for table "distributed_table_windex"
SELECT create_distributed_table('distributed_table_windex', 'key');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE UNIQUE INDEX key_index ON distributed_table_windex (key);
CREATE TABLE citus_local(key int, value text);
SELECT create_citus_local_table('citus_local');
create_citus_local_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE distributed_partitioned_table(key int, value text) PARTITION BY RANGE (key);
CREATE TABLE distributed_partitioned_table_1 PARTITION OF distributed_partitioned_table FOR VALUES FROM (0) TO (50);
CREATE TABLE distributed_partitioned_table_2 PARTITION OF distributed_partitioned_table FOR VALUES FROM (50) TO (200);
SELECT create_distributed_table('distributed_partitioned_table', 'key');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE local_partitioned_table(key int, value text) PARTITION BY RANGE (key);
CREATE TABLE local_partitioned_table_1 PARTITION OF local_partitioned_table FOR VALUES FROM (0) TO (50);
CREATE TABLE local_partitioned_table_2 PARTITION OF local_partitioned_table FOR VALUES FROM (50) TO (200);
CREATE TABLE distributed_table_composite (key int, value text, value_2 jsonb, primary key (key, value));
DEBUG: CREATE TABLE / PRIMARY KEY will create implicit index "distributed_table_composite_pkey" for table "distributed_table_composite"
SELECT create_distributed_table('distributed_table_composite', 'key');
create_distributed_table
---------------------------------------------------------------------
(1 row)
INSERT INTO postgres_table SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
INSERT INTO reference_table SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
DEBUG: distributed INSERT ... SELECT can only select from distributed tables
DEBUG: Collecting INSERT ... SELECT results on coordinator
INSERT INTO distributed_table_windex SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
DEBUG: distributed INSERT ... SELECT can only select from distributed tables
DEBUG: Collecting INSERT ... SELECT results on coordinator
INSERT INTO distributed_table SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
DEBUG: distributed INSERT ... SELECT can only select from distributed tables
DEBUG: Collecting INSERT ... SELECT results on coordinator
INSERT INTO distributed_table_pkey SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
DEBUG: distributed INSERT ... SELECT can only select from distributed tables
DEBUG: Collecting INSERT ... SELECT results on coordinator
INSERT INTO distributed_partitioned_table SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
DEBUG: distributed INSERT ... SELECT can only select from distributed tables
DEBUG: Collecting INSERT ... SELECT results on coordinator
INSERT INTO distributed_table_composite SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
DEBUG: distributed INSERT ... SELECT can only select from distributed tables
DEBUG: Collecting INSERT ... SELECT results on coordinator
INSERT INTO local_partitioned_table SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
-- vars referencing outer queries should work in SELECT
SELECT (SELECT COUNT(*) FROM postgres_table WHERE postgres_table.key = distributed_table.key) FROM distributed_table ORDER BY 1 LIMIT 1;
DEBUG: Wrapping relation "postgres_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.postgres_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (SELECT count(*) AS count FROM (SELECT postgres_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) postgres_table_1) postgres_table WHERE (postgres_table.key OPERATOR(pg_catalog.=) distributed_table.key)) AS count FROM local_table_join_vars.distributed_table ORDER BY (SELECT count(*) AS count FROM (SELECT postgres_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) postgres_table_1) postgres_table WHERE (postgres_table.key OPERATOR(pg_catalog.=) distributed_table.key)) LIMIT 1
DEBUG: push down of limit count: 1
count
---------------------------------------------------------------------
1
(1 row)
SELECT (SELECT COUNT(*) FROM postgres_table WHERE distributed_table.key = 5) FROM distributed_table ORDER BY 1 LIMIT 1;
DEBUG: Wrapping relation "postgres_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT NULL::integer AS "dummy-1" FROM local_table_join_vars.postgres_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (SELECT count(*) AS count FROM (SELECT NULL::integer AS key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) postgres_table_1) postgres_table WHERE (distributed_table.key OPERATOR(pg_catalog.=) 5)) AS count FROM local_table_join_vars.distributed_table ORDER BY (SELECT count(*) AS count FROM (SELECT NULL::integer AS key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) postgres_table_1) postgres_table WHERE (distributed_table.key OPERATOR(pg_catalog.=) 5)) LIMIT 1
DEBUG: push down of limit count: 1
count
---------------------------------------------------------------------
0
(1 row)
SELECT (SELECT COUNT(*) FROM distributed_table WHERE postgres_table.key = 5) FROM postgres_table ORDER BY 1 LIMIT 1;
DEBUG: Wrapping relation "distributed_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT NULL::integer AS "dummy-1" FROM local_table_join_vars.distributed_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (SELECT count(*) AS count FROM (SELECT NULL::integer AS key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) distributed_table_1) distributed_table WHERE (postgres_table.key OPERATOR(pg_catalog.=) 5)) AS count FROM local_table_join_vars.postgres_table ORDER BY (SELECT count(*) AS count FROM (SELECT NULL::integer AS key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) distributed_table_1) distributed_table WHERE (postgres_table.key OPERATOR(pg_catalog.=) 5)) LIMIT 1
count
---------------------------------------------------------------------
0
(1 row)
SELECT (SELECT COUNT(*) FROM distributed_table WHERE postgres_table.key = distributed_table.key) FROM postgres_table ORDER BY 1 LIMIT 1;
DEBUG: Wrapping relation "distributed_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.distributed_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (SELECT count(*) AS count FROM (SELECT distributed_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) distributed_table_1) distributed_table WHERE (postgres_table.key OPERATOR(pg_catalog.=) distributed_table.key)) AS count FROM local_table_join_vars.postgres_table ORDER BY (SELECT count(*) AS count FROM (SELECT distributed_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) distributed_table_1) distributed_table WHERE (postgres_table.key OPERATOR(pg_catalog.=) distributed_table.key)) LIMIT 1
count
---------------------------------------------------------------------
1
(1 row)
-- vars referencing outer queries should work in SELECT with citus local tables
SELECT (SELECT COUNT(*) FROM citus_local WHERE citus_local.key = distributed_table.key) FROM distributed_table ORDER BY 1 LIMIT 1;
DEBUG: Wrapping relation "citus_local" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.citus_local WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (SELECT count(*) AS count FROM (SELECT citus_local_1.key, NULL::text AS value FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) citus_local_1) citus_local WHERE (citus_local.key OPERATOR(pg_catalog.=) distributed_table.key)) AS count FROM local_table_join_vars.distributed_table ORDER BY (SELECT count(*) AS count FROM (SELECT citus_local_1.key, NULL::text AS value FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) citus_local_1) citus_local WHERE (citus_local.key OPERATOR(pg_catalog.=) distributed_table.key)) LIMIT 1
DEBUG: push down of limit count: 1
count
---------------------------------------------------------------------
0
(1 row)
SELECT (SELECT COUNT(*) FROM citus_local WHERE distributed_table.key = 5) FROM distributed_table ORDER BY 1 LIMIT 1;
DEBUG: Wrapping relation "citus_local" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT NULL::integer AS "dummy-1" FROM local_table_join_vars.citus_local WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (SELECT count(*) AS count FROM (SELECT NULL::integer AS key, NULL::text AS value FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) citus_local_1) citus_local WHERE (distributed_table.key OPERATOR(pg_catalog.=) 5)) AS count FROM local_table_join_vars.distributed_table ORDER BY (SELECT count(*) AS count FROM (SELECT NULL::integer AS key, NULL::text AS value FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) citus_local_1) citus_local WHERE (distributed_table.key OPERATOR(pg_catalog.=) 5)) LIMIT 1
DEBUG: push down of limit count: 1
count
---------------------------------------------------------------------
0
(1 row)
SELECT (SELECT COUNT(*) FROM distributed_table WHERE citus_local.key = 5) FROM citus_local ORDER BY 1 LIMIT 1;
DEBUG: Wrapping relation "distributed_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT NULL::integer AS "dummy-1" FROM local_table_join_vars.distributed_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (SELECT count(*) AS count FROM (SELECT NULL::integer AS key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) distributed_table_1) distributed_table WHERE (citus_local.key OPERATOR(pg_catalog.=) 5)) AS count FROM local_table_join_vars.citus_local ORDER BY (SELECT count(*) AS count FROM (SELECT NULL::integer AS key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) distributed_table_1) distributed_table WHERE (citus_local.key OPERATOR(pg_catalog.=) 5)) LIMIT 1
count
---------------------------------------------------------------------
(0 rows)
SELECT (SELECT COUNT(*) FROM distributed_table WHERE citus_local.key = distributed_table.key) FROM citus_local ORDER BY 1 LIMIT 1;
DEBUG: Wrapping relation "distributed_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.distributed_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (SELECT count(*) AS count FROM (SELECT distributed_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) distributed_table_1) distributed_table WHERE (citus_local.key OPERATOR(pg_catalog.=) distributed_table.key)) AS count FROM local_table_join_vars.citus_local ORDER BY (SELECT count(*) AS count FROM (SELECT distributed_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) distributed_table_1) distributed_table WHERE (citus_local.key OPERATOR(pg_catalog.=) distributed_table.key)) LIMIT 1
count
---------------------------------------------------------------------
(0 rows)
-- vars referencing outer queries should work in WHERE
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM postgres_table WHERE key > distributed_table.key);
DEBUG: Wrapping relation "postgres_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.postgres_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM local_table_join_vars.distributed_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT postgres_table.key FROM (SELECT postgres_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) postgres_table_1) postgres_table WHERE (postgres_table.key OPERATOR(pg_catalog.>) distributed_table.key)))
count
---------------------------------------------------------------------
0
(1 row)
SELECT COUNT(*) FROM postgres_table WHERE key in (SELECT key FROM distributed_table WHERE key > postgres_table.key);
DEBUG: Wrapping relation "distributed_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.distributed_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM local_table_join_vars.postgres_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT distributed_table.key FROM (SELECT distributed_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) distributed_table_1) distributed_table WHERE (distributed_table.key OPERATOR(pg_catalog.>) postgres_table.key)))
count
---------------------------------------------------------------------
0
(1 row)
SELECT COUNT(*) FROM postgres_table WHERE key in (SELECT key FROM distributed_table WHERE postgres_table.key > 5);
DEBUG: Wrapping relation "distributed_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.distributed_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM local_table_join_vars.postgres_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT distributed_table.key FROM (SELECT distributed_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) distributed_table_1) distributed_table WHERE (postgres_table.key OPERATOR(pg_catalog.>) 5)))
count
---------------------------------------------------------------------
95
(1 row)
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM postgres_table WHERE distributed_table.key > 5);
DEBUG: Wrapping relation "postgres_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.postgres_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM local_table_join_vars.distributed_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT postgres_table.key FROM (SELECT postgres_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) postgres_table_1) postgres_table WHERE (distributed_table.key OPERATOR(pg_catalog.>) 5)))
count
---------------------------------------------------------------------
95
(1 row)
-- vars referencing outer queries should work in WHERE with citus local tables
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM citus_local WHERE key > distributed_table.key);
DEBUG: Wrapping relation "citus_local" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.citus_local WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM local_table_join_vars.distributed_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT citus_local.key FROM (SELECT citus_local_1.key, NULL::text AS value FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) citus_local_1) citus_local WHERE (citus_local.key OPERATOR(pg_catalog.>) distributed_table.key)))
count
---------------------------------------------------------------------
0
(1 row)
SELECT COUNT(*) FROM citus_local WHERE key in (SELECT key FROM distributed_table WHERE key > citus_local.key);
DEBUG: Wrapping relation "distributed_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.distributed_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM local_table_join_vars.citus_local WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT distributed_table.key FROM (SELECT distributed_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) distributed_table_1) distributed_table WHERE (distributed_table.key OPERATOR(pg_catalog.>) citus_local.key)))
count
---------------------------------------------------------------------
0
(1 row)
SELECT COUNT(*) FROM citus_local WHERE key in (SELECT key FROM distributed_table WHERE citus_local.key > 5);
DEBUG: Wrapping relation "distributed_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.distributed_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM local_table_join_vars.citus_local WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT distributed_table.key FROM (SELECT distributed_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) distributed_table_1) distributed_table WHERE (citus_local.key OPERATOR(pg_catalog.>) 5)))
count
---------------------------------------------------------------------
0
(1 row)
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM citus_local WHERE distributed_table.key > 5);
DEBUG: Wrapping relation "citus_local" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.citus_local WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM local_table_join_vars.distributed_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT citus_local.key FROM (SELECT citus_local_1.key, NULL::text AS value FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) citus_local_1) citus_local WHERE (distributed_table.key OPERATOR(pg_catalog.>) 5)))
count
---------------------------------------------------------------------
0
(1 row)
-- citus-local, local and dist should work
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM citus_local JOIN postgres_table USING(key) WHERE key > distributed_table.key);
DEBUG: Wrapping relation "citus_local" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.citus_local WHERE true
DEBUG: Wrapping relation "postgres_table" to a subquery
DEBUG: generating subplan XXX_2 for subquery SELECT key FROM local_table_join_vars.postgres_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM local_table_join_vars.distributed_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT citus_local.key FROM ((SELECT citus_local_1.key, NULL::text AS value FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) citus_local_1) citus_local JOIN (SELECT postgres_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) postgres_table_1) postgres_table USING (key)) WHERE (citus_local.key OPERATOR(pg_catalog.>) distributed_table.key)))
count
---------------------------------------------------------------------
0
(1 row)
-- Will work when we fix "correlated subqueries are not supported when the FROM clause contains a CTE or subquery"
SELECT COUNT(*) FROM citus_local WHERE key in (SELECT key FROM distributed_table JOIN postgres_table USING(key) WHERE key > citus_local.key);
DEBUG: Wrapping relation "postgres_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.postgres_table WHERE true
DEBUG: Wrapping relation "citus_local" to a subquery
DEBUG: generating subplan XXX_2 for subquery SELECT key FROM local_table_join_vars.citus_local WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT citus_local_1.key, NULL::text AS value FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) citus_local_1) citus_local WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT distributed_table.key FROM (local_table_join_vars.distributed_table JOIN (SELECT postgres_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) postgres_table_1) postgres_table USING (key)) WHERE (distributed_table.key OPERATOR(pg_catalog.>) citus_local.key)))
ERROR: correlated subqueries are not supported when the FROM clause contains a CTE or subquery
-- Will work when we fix "correlated subqueries are not supported when the FROM clause contains a CTE or subquery"
SELECT COUNT(*) FROM citus_local WHERE key in (SELECT key FROM distributed_table JOIN postgres_table USING(key) WHERE citus_local.key > 5);
DEBUG: Wrapping relation "postgres_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.postgres_table WHERE true
DEBUG: Wrapping relation "citus_local" to a subquery
DEBUG: generating subplan XXX_2 for subquery SELECT key FROM local_table_join_vars.citus_local WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT citus_local_1.key, NULL::text AS value FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) citus_local_1) citus_local WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT distributed_table.key FROM (local_table_join_vars.distributed_table JOIN (SELECT postgres_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) postgres_table_1) postgres_table USING (key)) WHERE (citus_local.key OPERATOR(pg_catalog.>) 5)))
ERROR: correlated subqueries are not supported when the FROM clause contains a CTE or subquery
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM citus_local JOIN postgres_table USING(key) WHERE distributed_table.key > 5);
DEBUG: Wrapping relation "citus_local" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.citus_local WHERE true
DEBUG: Wrapping relation "postgres_table" to a subquery
DEBUG: generating subplan XXX_2 for subquery SELECT key FROM local_table_join_vars.postgres_table WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM local_table_join_vars.distributed_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT citus_local.key FROM ((SELECT citus_local_1.key, NULL::text AS value FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) citus_local_1) citus_local JOIN (SELECT postgres_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) postgres_table_1) postgres_table USING (key)) WHERE (distributed_table.key OPERATOR(pg_catalog.>) 5)))
count
---------------------------------------------------------------------
0
(1 row)
-- Will work when we fix "correlated subqueries are not supported when the FROM clause contains a CTE or subquery"
SELECT (SELECT (SELECT COUNT(*) FROM postgres_table WHERE postgres_table.key = distributed_table.key) FROM postgres_table p2) FROM distributed_table;
DEBUG: Wrapping relation "postgres_table" to a subquery
DEBUG: generating subplan XXX_1 for subquery SELECT key FROM local_table_join_vars.postgres_table WHERE true
DEBUG: Wrapping relation "postgres_table" "p2" to a subquery
DEBUG: generating subplan XXX_2 for subquery SELECT NULL::integer AS "dummy-1" FROM local_table_join_vars.postgres_table p2 WHERE true
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (SELECT (SELECT count(*) AS count FROM (SELECT postgres_table_1.key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result.key FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer)) postgres_table_1) postgres_table WHERE (postgres_table.key OPERATOR(pg_catalog.=) distributed_table.key)) AS count FROM (SELECT NULL::integer AS key, NULL::text AS value, NULL::jsonb AS value_2 FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) p2_1) p2) AS count FROM local_table_join_vars.distributed_table
ERROR: correlated subqueries are not supported when the FROM clause contains a CTE or subquery
RESET client_min_messages;
\set VERBOSITY terse
DROP SCHEMA local_table_join_vars CASCADE;
NOTICE: drop cascades to 11 other objects

View File

@ -231,6 +231,7 @@ test: local_dist_join_modifications
test: local_table_join test: local_table_join
test: local_dist_join_mixed test: local_dist_join_mixed
test: citus_local_dist_joins test: citus_local_dist_joins
test: local_table_join_vars
# --------- # ---------
# multi_copy creates hash and range-partitioned tables and performs COPY # multi_copy creates hash and range-partitioned tables and performs COPY

View File

@ -0,0 +1,84 @@
CREATE SCHEMA local_table_join_vars;
SET search_path TO local_table_join_vars;
SET client_min_messages to ERROR;
SELECT master_add_node('localhost', :master_port, groupId => 0) AS coordinator_nodeid \gset
SET client_min_messages TO DEBUG1;
CREATE TABLE postgres_table (key int, value text, value_2 jsonb);
CREATE TABLE reference_table (key int, value text, value_2 jsonb);
SELECT create_reference_table('reference_table');
CREATE TABLE distributed_table (key int, value text, value_2 jsonb);
SELECT create_distributed_table('distributed_table', 'key');
CREATE TABLE distributed_table_pkey (key int primary key, value text, value_2 jsonb);
SELECT create_distributed_table('distributed_table_pkey', 'key');
CREATE TABLE distributed_table_windex (key int primary key, value text, value_2 jsonb);
SELECT create_distributed_table('distributed_table_windex', 'key');
CREATE UNIQUE INDEX key_index ON distributed_table_windex (key);
CREATE TABLE citus_local(key int, value text);
SELECT create_citus_local_table('citus_local');
CREATE TABLE distributed_partitioned_table(key int, value text) PARTITION BY RANGE (key);
CREATE TABLE distributed_partitioned_table_1 PARTITION OF distributed_partitioned_table FOR VALUES FROM (0) TO (50);
CREATE TABLE distributed_partitioned_table_2 PARTITION OF distributed_partitioned_table FOR VALUES FROM (50) TO (200);
SELECT create_distributed_table('distributed_partitioned_table', 'key');
CREATE TABLE local_partitioned_table(key int, value text) PARTITION BY RANGE (key);
CREATE TABLE local_partitioned_table_1 PARTITION OF local_partitioned_table FOR VALUES FROM (0) TO (50);
CREATE TABLE local_partitioned_table_2 PARTITION OF local_partitioned_table FOR VALUES FROM (50) TO (200);
CREATE TABLE distributed_table_composite (key int, value text, value_2 jsonb, primary key (key, value));
SELECT create_distributed_table('distributed_table_composite', 'key');
INSERT INTO postgres_table SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
INSERT INTO reference_table SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
INSERT INTO distributed_table_windex SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
INSERT INTO distributed_table SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
INSERT INTO distributed_table_pkey SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
INSERT INTO distributed_partitioned_table SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
INSERT INTO distributed_table_composite SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
INSERT INTO local_partitioned_table SELECT i, i::varchar(256) FROM generate_series(1, 100) i;
-- vars referencing outer queries should work in SELECT
SELECT (SELECT COUNT(*) FROM postgres_table WHERE postgres_table.key = distributed_table.key) FROM distributed_table ORDER BY 1 LIMIT 1;
SELECT (SELECT COUNT(*) FROM postgres_table WHERE distributed_table.key = 5) FROM distributed_table ORDER BY 1 LIMIT 1;
SELECT (SELECT COUNT(*) FROM distributed_table WHERE postgres_table.key = 5) FROM postgres_table ORDER BY 1 LIMIT 1;
SELECT (SELECT COUNT(*) FROM distributed_table WHERE postgres_table.key = distributed_table.key) FROM postgres_table ORDER BY 1 LIMIT 1;
-- vars referencing outer queries should work in SELECT with citus local tables
SELECT (SELECT COUNT(*) FROM citus_local WHERE citus_local.key = distributed_table.key) FROM distributed_table ORDER BY 1 LIMIT 1;
SELECT (SELECT COUNT(*) FROM citus_local WHERE distributed_table.key = 5) FROM distributed_table ORDER BY 1 LIMIT 1;
SELECT (SELECT COUNT(*) FROM distributed_table WHERE citus_local.key = 5) FROM citus_local ORDER BY 1 LIMIT 1;
SELECT (SELECT COUNT(*) FROM distributed_table WHERE citus_local.key = distributed_table.key) FROM citus_local ORDER BY 1 LIMIT 1;
-- vars referencing outer queries should work in WHERE
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM postgres_table WHERE key > distributed_table.key);
SELECT COUNT(*) FROM postgres_table WHERE key in (SELECT key FROM distributed_table WHERE key > postgres_table.key);
SELECT COUNT(*) FROM postgres_table WHERE key in (SELECT key FROM distributed_table WHERE postgres_table.key > 5);
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM postgres_table WHERE distributed_table.key > 5);
-- vars referencing outer queries should work in WHERE with citus local tables
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM citus_local WHERE key > distributed_table.key);
SELECT COUNT(*) FROM citus_local WHERE key in (SELECT key FROM distributed_table WHERE key > citus_local.key);
SELECT COUNT(*) FROM citus_local WHERE key in (SELECT key FROM distributed_table WHERE citus_local.key > 5);
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM citus_local WHERE distributed_table.key > 5);
-- citus-local, local and dist should work
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM citus_local JOIN postgres_table USING(key) WHERE key > distributed_table.key);
-- Will work when we fix "correlated subqueries are not supported when the FROM clause contains a CTE or subquery"
SELECT COUNT(*) FROM citus_local WHERE key in (SELECT key FROM distributed_table JOIN postgres_table USING(key) WHERE key > citus_local.key);
-- Will work when we fix "correlated subqueries are not supported when the FROM clause contains a CTE or subquery"
SELECT COUNT(*) FROM citus_local WHERE key in (SELECT key FROM distributed_table JOIN postgres_table USING(key) WHERE citus_local.key > 5);
SELECT COUNT(*) FROM distributed_table WHERE key in (SELECT key FROM citus_local JOIN postgres_table USING(key) WHERE distributed_table.key > 5);
-- Will work when we fix "correlated subqueries are not supported when the FROM clause contains a CTE or subquery"
SELECT (SELECT (SELECT COUNT(*) FROM postgres_table WHERE postgres_table.key = distributed_table.key) FROM postgres_table p2) FROM distributed_table;
RESET client_min_messages;
\set VERBOSITY terse
DROP SCHEMA local_table_join_vars CASCADE;