Errors for CTEs with search clause

Relevant PG commit:
3696a600e2292d43c00949ddf0352e4ebb487e5b
pull/5234/head
Halil Ozan Akgul 2021-09-02 12:58:47 +03:00
parent b3f1a94688
commit 19af1cef2f
3 changed files with 207 additions and 0 deletions

View File

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

View File

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

View File

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