mirror of https://github.com/citusdata/citus.git
Merge pull request #5234 from citusdata/cte_with_search_clause
Errors for CTEs with search clausepull/5262/head^2
commit
f4428412a0
|
@ -158,6 +158,10 @@ static List * ExtractInsertValuesList(Query *query, Var *partitionColumn);
|
|||
static DeferredErrorMessage * DeferErrorIfUnsupportedRouterPlannableSelectQuery(
|
||||
Query *query);
|
||||
static DeferredErrorMessage * ErrorIfQueryHasUnroutableModifyingCTE(Query *queryTree);
|
||||
#if PG_VERSION_NUM >= PG_VERSION_14
|
||||
static DeferredErrorMessage * ErrorIfQueryHasCTEWithSearchClause(Query *queryTree);
|
||||
static bool ContainsSearchClauseWalker(Node *node);
|
||||
#endif
|
||||
static bool SelectsFromDistributedTable(List *rangeTableList, Query *query);
|
||||
static ShardPlacement * CreateDummyPlacement(bool hasLocalRelation);
|
||||
static ShardPlacement * CreateLocalDummyPlacement();
|
||||
|
@ -1070,6 +1074,15 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
|
|||
}
|
||||
}
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_14
|
||||
DeferredErrorMessage *CTEWithSearchClauseError =
|
||||
ErrorIfQueryHasCTEWithSearchClause(originalQuery);
|
||||
if (CTEWithSearchClauseError != NULL)
|
||||
{
|
||||
return CTEWithSearchClauseError;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -3623,6 +3636,15 @@ DeferErrorIfUnsupportedRouterPlannableSelectQuery(Query *query)
|
|||
NULL, NULL);
|
||||
}
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_14
|
||||
DeferredErrorMessage *CTEWithSearchClauseError =
|
||||
ErrorIfQueryHasCTEWithSearchClause(query);
|
||||
if (CTEWithSearchClauseError != NULL)
|
||||
{
|
||||
return CTEWithSearchClauseError;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ErrorIfQueryHasUnroutableModifyingCTE(query);
|
||||
}
|
||||
|
||||
|
@ -3756,6 +3778,57 @@ ErrorIfQueryHasUnroutableModifyingCTE(Query *queryTree)
|
|||
}
|
||||
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_14
|
||||
|
||||
/*
|
||||
* ErrorIfQueryHasCTEWithSearchClause checks if the query contains any common table
|
||||
* expressions with search clause and errors out if it does.
|
||||
*/
|
||||
static DeferredErrorMessage *
|
||||
ErrorIfQueryHasCTEWithSearchClause(Query *queryTree)
|
||||
{
|
||||
if (ContainsSearchClauseWalker((Node *) queryTree))
|
||||
{
|
||||
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||
"CTEs with search clauses are not supported",
|
||||
NULL, NULL);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ContainsSearchClauseWalker walks over the node and finds if there are any
|
||||
* CommonTableExprs with search clause
|
||||
*/
|
||||
static bool
|
||||
ContainsSearchClauseWalker(Node *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsA(node, CommonTableExpr))
|
||||
{
|
||||
if (((CommonTableExpr *) node)->search_clause != NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsA(node, Query))
|
||||
{
|
||||
return query_tree_walker((Query *) node, ContainsSearchClauseWalker, NULL, 0);
|
||||
}
|
||||
|
||||
return expression_tree_walker(node, ContainsSearchClauseWalker, NULL);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* get_all_actual_clauses
|
||||
*
|
||||
|
|
|
@ -644,5 +644,74 @@ REINDEX TABLE dist_part_table;
|
|||
ERROR: REINDEX TABLE queries on distributed partitioned tables are not supported
|
||||
-- but we support REINDEXing partitions
|
||||
REINDEX TABLE dist_part_table_1;
|
||||
-- test if we error with CTEs with search clauses
|
||||
CREATE TABLE graph0(f INT, t INT, label TEXT);
|
||||
SELECT create_distributed_table('graph0', 'f');
|
||||
create_distributed_table
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
INSERT INTO graph0 VALUES (1, 2, 'arc 1 -> 2'),
|
||||
(1, 3, 'arc 1 -> 3'), (2, 3, 'arc 2 -> 3'),
|
||||
(1, 4, 'arc 1 -> 4'), (4, 5, 'arc 4 -> 5');
|
||||
WITH RECURSIVE search_graph(f, t, label) AS (
|
||||
SELECT * FROM graph0 g WHERE f = 1
|
||||
UNION ALL
|
||||
SELECT g.*
|
||||
FROM graph0 g, search_graph sg
|
||||
WHERE g.f = sg.t and g.f = 1
|
||||
) SEARCH DEPTH FIRST BY f, t SET seq
|
||||
SELECT * FROM search_graph ORDER BY seq;
|
||||
ERROR: recursive CTEs are not supported in distributed queries
|
||||
WITH RECURSIVE search_graph(f, t, label) AS (
|
||||
SELECT * FROM graph0 g WHERE f = 1
|
||||
UNION ALL
|
||||
SELECT g.*
|
||||
FROM graph0 g, search_graph sg
|
||||
WHERE g.f = sg.t and g.f = 1
|
||||
) SEARCH DEPTH FIRST BY f, t SET seq
|
||||
DELETE FROM graph0 WHERE t IN (SELECT t FROM search_graph ORDER BY seq);
|
||||
ERROR: recursive CTEs are not supported in distributed queries
|
||||
CREATE TABLE graph1(f INT, t INT, label TEXT);
|
||||
SELECT create_reference_table('graph1');
|
||||
create_reference_table
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
INSERT INTO graph1 VALUES (1, 2, 'arc 1 -> 2'),
|
||||
(1, 3, 'arc 1 -> 3'), (2, 3, 'arc 2 -> 3'),
|
||||
(1, 4, 'arc 1 -> 4'), (4, 5, 'arc 4 -> 5');
|
||||
WITH RECURSIVE search_graph(f, t, label) AS (
|
||||
SELECT * FROM graph1 g WHERE f = 1
|
||||
UNION ALL
|
||||
SELECT g.*
|
||||
FROM graph1 g, search_graph sg
|
||||
WHERE g.f = sg.t and g.f = 1
|
||||
) SEARCH DEPTH FIRST BY f, t SET seq
|
||||
SELECT * FROM search_graph ORDER BY seq;
|
||||
ERROR: recursive CTEs are not supported in distributed queries
|
||||
WITH RECURSIVE search_graph(f, t, label) AS (
|
||||
SELECT * FROM graph1 g WHERE f = 1
|
||||
UNION ALL
|
||||
SELECT g.*
|
||||
FROM graph1 g, search_graph sg
|
||||
WHERE g.f = sg.t and g.f = 1
|
||||
) SEARCH DEPTH FIRST BY f, t SET seq
|
||||
DELETE FROM graph1 WHERE t IN (SELECT t FROM search_graph ORDER BY seq);
|
||||
ERROR: recursive CTEs are not supported in distributed queries
|
||||
SELECT * FROM (
|
||||
WITH RECURSIVE search_graph(f, t, label) AS (
|
||||
SELECT *
|
||||
FROM graph0 g
|
||||
WHERE f = 1
|
||||
UNION ALL SELECT g.*
|
||||
FROM graph0 g, search_graph sg
|
||||
WHERE g.f = sg.t AND g.f = 1
|
||||
) SEARCH DEPTH FIRST BY f, t SET seq
|
||||
SELECT * FROM search_graph ORDER BY seq
|
||||
) as foo;
|
||||
ERROR: recursive CTEs are not supported in distributed queries
|
||||
set client_min_messages to error;
|
||||
drop schema pg14 cascade;
|
||||
|
|
|
@ -272,5 +272,70 @@ REINDEX TABLE dist_part_table;
|
|||
-- but we support REINDEXing partitions
|
||||
REINDEX TABLE dist_part_table_1;
|
||||
|
||||
|
||||
-- test if we error with CTEs with search clauses
|
||||
CREATE TABLE graph0(f INT, t INT, label TEXT);
|
||||
SELECT create_distributed_table('graph0', 'f');
|
||||
|
||||
INSERT INTO graph0 VALUES (1, 2, 'arc 1 -> 2'),
|
||||
(1, 3, 'arc 1 -> 3'), (2, 3, 'arc 2 -> 3'),
|
||||
(1, 4, 'arc 1 -> 4'), (4, 5, 'arc 4 -> 5');
|
||||
|
||||
WITH RECURSIVE search_graph(f, t, label) AS (
|
||||
SELECT * FROM graph0 g WHERE f = 1
|
||||
UNION ALL
|
||||
SELECT g.*
|
||||
FROM graph0 g, search_graph sg
|
||||
WHERE g.f = sg.t and g.f = 1
|
||||
) SEARCH DEPTH FIRST BY f, t SET seq
|
||||
SELECT * FROM search_graph ORDER BY seq;
|
||||
|
||||
WITH RECURSIVE search_graph(f, t, label) AS (
|
||||
SELECT * FROM graph0 g WHERE f = 1
|
||||
UNION ALL
|
||||
SELECT g.*
|
||||
FROM graph0 g, search_graph sg
|
||||
WHERE g.f = sg.t and g.f = 1
|
||||
) SEARCH DEPTH FIRST BY f, t SET seq
|
||||
DELETE FROM graph0 WHERE t IN (SELECT t FROM search_graph ORDER BY seq);
|
||||
|
||||
CREATE TABLE graph1(f INT, t INT, label TEXT);
|
||||
SELECT create_reference_table('graph1');
|
||||
|
||||
INSERT INTO graph1 VALUES (1, 2, 'arc 1 -> 2'),
|
||||
(1, 3, 'arc 1 -> 3'), (2, 3, 'arc 2 -> 3'),
|
||||
(1, 4, 'arc 1 -> 4'), (4, 5, 'arc 4 -> 5');
|
||||
|
||||
WITH RECURSIVE search_graph(f, t, label) AS (
|
||||
SELECT * FROM graph1 g WHERE f = 1
|
||||
UNION ALL
|
||||
SELECT g.*
|
||||
FROM graph1 g, search_graph sg
|
||||
WHERE g.f = sg.t and g.f = 1
|
||||
) SEARCH DEPTH FIRST BY f, t SET seq
|
||||
SELECT * FROM search_graph ORDER BY seq;
|
||||
|
||||
WITH RECURSIVE search_graph(f, t, label) AS (
|
||||
SELECT * FROM graph1 g WHERE f = 1
|
||||
UNION ALL
|
||||
SELECT g.*
|
||||
FROM graph1 g, search_graph sg
|
||||
WHERE g.f = sg.t and g.f = 1
|
||||
) SEARCH DEPTH FIRST BY f, t SET seq
|
||||
DELETE FROM graph1 WHERE t IN (SELECT t FROM search_graph ORDER BY seq);
|
||||
|
||||
|
||||
SELECT * FROM (
|
||||
WITH RECURSIVE search_graph(f, t, label) AS (
|
||||
SELECT *
|
||||
FROM graph0 g
|
||||
WHERE f = 1
|
||||
UNION ALL SELECT g.*
|
||||
FROM graph0 g, search_graph sg
|
||||
WHERE g.f = sg.t AND g.f = 1
|
||||
) SEARCH DEPTH FIRST BY f, t SET seq
|
||||
SELECT * FROM search_graph ORDER BY seq
|
||||
) as foo;
|
||||
|
||||
set client_min_messages to error;
|
||||
drop schema pg14 cascade;
|
||||
|
|
Loading…
Reference in New Issue