mirror of https://github.com/citusdata/citus.git
Errors for CTEs with search clause
Relevant PG commit: 3696a600e2292d43c00949ddf0352e4ebb487e5bpull/5234/head
parent
b3f1a94688
commit
19af1cef2f
|
@ -158,6 +158,10 @@ static List * ExtractInsertValuesList(Query *query, Var *partitionColumn);
|
||||||
static DeferredErrorMessage * DeferErrorIfUnsupportedRouterPlannableSelectQuery(
|
static DeferredErrorMessage * DeferErrorIfUnsupportedRouterPlannableSelectQuery(
|
||||||
Query *query);
|
Query *query);
|
||||||
static DeferredErrorMessage * ErrorIfQueryHasUnroutableModifyingCTE(Query *queryTree);
|
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 bool SelectsFromDistributedTable(List *rangeTableList, Query *query);
|
||||||
static ShardPlacement * CreateDummyPlacement(bool hasLocalRelation);
|
static ShardPlacement * CreateDummyPlacement(bool hasLocalRelation);
|
||||||
static ShardPlacement * CreateLocalDummyPlacement();
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3623,6 +3636,15 @@ DeferErrorIfUnsupportedRouterPlannableSelectQuery(Query *query)
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_14
|
||||||
|
DeferredErrorMessage *CTEWithSearchClauseError =
|
||||||
|
ErrorIfQueryHasCTEWithSearchClause(query);
|
||||||
|
if (CTEWithSearchClauseError != NULL)
|
||||||
|
{
|
||||||
|
return CTEWithSearchClauseError;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return ErrorIfQueryHasUnroutableModifyingCTE(query);
|
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
|
* get_all_actual_clauses
|
||||||
*
|
*
|
||||||
|
|
|
@ -644,5 +644,74 @@ REINDEX TABLE dist_part_table;
|
||||||
ERROR: REINDEX TABLE queries on distributed partitioned tables are not supported
|
ERROR: REINDEX TABLE queries on distributed partitioned tables are not supported
|
||||||
-- but we support REINDEXing partitions
|
-- but we support REINDEXing partitions
|
||||||
REINDEX TABLE dist_part_table_1;
|
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;
|
set client_min_messages to error;
|
||||||
drop schema pg14 cascade;
|
drop schema pg14 cascade;
|
||||||
|
|
|
@ -272,5 +272,70 @@ REINDEX TABLE dist_part_table;
|
||||||
-- but we support REINDEXing partitions
|
-- but we support REINDEXing partitions
|
||||||
REINDEX TABLE dist_part_table_1;
|
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;
|
set client_min_messages to error;
|
||||||
drop schema pg14 cascade;
|
drop schema pg14 cascade;
|
||||||
|
|
Loading…
Reference in New Issue