From 01bc0111f73b2ef75ef6d0a97f2f440c91c3f1fa Mon Sep 17 00:00:00 2001 From: hoshiai Date: Wed, 26 Jul 2023 06:57:15 +0900 Subject: [PATCH] Fix some comments and error messages --- createas.c | 14 ++++++++------ expected/pg_ivm.out | 10 ++++++---- matview.c | 20 +++++++++++++++----- sql/pg_ivm.sql | 2 ++ 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/createas.c b/createas.c index 622e566..4617d56 100644 --- a/createas.c +++ b/createas.c @@ -895,8 +895,9 @@ check_ivm_restriction_walker(Node *node, check_ivm_restriction_context *context) /* * additional restriction checks for exists subquery * - * When contain EXISTS clauses, and it has a column refernces - * a table outside, its column must be included by target list. + * If the query has any EXISTS clauses and columns in them refer to + * columns in tables in the output query, those columns must be + * included in the target list. */ if (context->exists_qual_vars != NIL && context->sublevels_up == 0) { @@ -1019,7 +1020,8 @@ check_ivm_restriction_walker(Node *node, check_ivm_restriction_context *context) case T_Var: { Var *variable = (Var *) node; - /* Currently, only EXISTS clause is allowed here. + /* + * Currently, only EXISTS clause is allowed here. * If EXISTS subquery refers to vars of the upper query, collect these vars. */ if (variable->varlevelsup > 0 && context->in_exists_subquery) @@ -1028,18 +1030,18 @@ check_ivm_restriction_walker(Node *node, check_ivm_restriction_context *context) } case T_SubLink: { - /* Now, EXISTS clause is supported only */ + /* Currently, EXISTS clause is supported only */ Query *subselect; SubLink *sublink = (SubLink *) node; if (sublink->subLinkType != EXISTS_SUBLINK) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("this query is not allowed on incrementally maintainable materialized view"), - errhint("subquery in WHERE clause only supports subquery with EXISTS clause"))); + errhint("sublink only supports subquery with EXISTS clause in WHERE clause"))); if (context->sublevels_up > 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("nested subquery is not supported on incrementally maintainable materialized view"))); + errmsg("nested sublink is not supported on incrementally maintainable materialized view"))); subselect = (Query *)sublink->subselect; /* raise ERROR if the sublink has CTE */ diff --git a/expected/pg_ivm.out b/expected/pg_ivm.out index 9288d2d..8936b7f 100644 --- a/expected/pg_ivm.out +++ b/expected/pg_ivm.out @@ -827,22 +827,24 @@ SELECT create_immv('mv_ivm_subquery', 'SELECT a.i,a.j FROM mv_base_a a, (SELECT ERROR: DISTINCT clause in nested query are not supported on incrementally maintainable materialized view SELECT create_immv('mv_ivm_subquery', 'SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 )'); ERROR: this query is not allowed on incrementally maintainable materialized view -HINT: subquery in WHERE clause only supports subquery with EXISTS clause +HINT: sublink only supports subquery with EXISTS clause in WHERE clause SELECT create_immv('mv_ivm_subquery', 'SELECT i,j, (SELECT k FROM mv_base_b LIMIT 1) FROM mv_base_a a'); ERROR: this query is not allowed on incrementally maintainable materialized view -HINT: subquery in WHERE clause only supports subquery with EXISTS clause +HINT: sublink only supports subquery with EXISTS clause in WHERE clause SELECT create_immv('mv_ivm_subquery', 'SELECT i,j, (SELECT k FROM mv_base_b LIMIT 1) + 1 FROM mv_base_a a'); ERROR: this query is not allowed on incrementally maintainable materialized view -HINT: subquery in WHERE clause only supports subquery with EXISTS clause +HINT: sublink only supports subquery with EXISTS clause in WHERE clause SELECT create_immv('mv_ivm_subquery', 'SELECT * FROM generate_series(1, (SELECT k FROM mv_base_b LIMIT 1)) AS v'); ERROR: this query is not allowed on incrementally maintainable materialized view -HINT: subquery in WHERE clause only supports subquery with EXISTS clause +HINT: sublink only supports subquery with EXISTS clause in WHERE clause SELECT create_immv('mv_ivm_subquery', 'SELECT a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i)'); ERROR: this query is not allowed on incrementally maintainable materialized view HINT: targetlist must contain vars that are referred to in EXISTS subquery SELECT create_immv('mv_ivm_subquery', 'SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 2'); ERROR: this query is not allowed on incrementally maintainable materialized view HINT: OR or NOT conditions and EXISTS condition are not used together +SELECT create_immv('mv_ivm_subquery', 'SELECT a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_a a2 WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a2.i = b.i))'); +ERROR: nested sublink is not supported on incrementally maintainable materialized view -- support join subquery in FROM clause BEGIN; SELECT create_immv('mv_ivm_join_subquery', 'SELECT i, j, k FROM ( SELECT i, a.j, b.k FROM mv_base_b b INNER JOIN mv_base_a a USING(i)) tmp'); diff --git a/matview.c b/matview.c index d8837fa..4e90b00 100644 --- a/matview.c +++ b/matview.c @@ -1587,11 +1587,6 @@ rewrite_query_for_distinct_and_aggregates(Query *query, ParseState *pstate) return query; } -/* - * rewrite_query_for_exists_subquery - * - * Rewrite EXISTS sublink in WHERE to LATERAL subquery - */ static Query * rewrite_exists_subquery_walker(Query *query, Node *node, int *count) { @@ -1725,6 +1720,21 @@ rewrite_exists_subquery_walker(Query *query, Node *node, int *count) return query; } +/* + * rewrite_query_for_exists_subquery + * + * Rewrite EXISTS sublink in WHERE to LATERAL subquery + * For example, rewrite + * SELECT t1.* FROM t1 + * WHERE EXISTS(SELECT 1 FROM t2 WHERE t1.key = t2.key) + * to + * SELECT t1.*, ex.__ivm_exists_count_0__ + * FROM t1, LATERAL( + * SELECT 1, COUNT(*) AS __ivm_exists_count_0__ + * FROM t2 + * WHERE t1.key = t2.key + * HAVING __ivm_exists_count_0__ > 0) AS ex + */ Query * rewrite_query_for_exists_subquery(Query *query) { diff --git a/sql/pg_ivm.sql b/sql/pg_ivm.sql index ddc2053..186efb3 100644 --- a/sql/pg_ivm.sql +++ b/sql/pg_ivm.sql @@ -270,6 +270,7 @@ SELECT create_immv('mv_ivm_subquery', 'SELECT i,j, (SELECT k FROM mv_base_b LIMI SELECT create_immv('mv_ivm_subquery', 'SELECT * FROM generate_series(1, (SELECT k FROM mv_base_b LIMIT 1)) AS v'); SELECT create_immv('mv_ivm_subquery', 'SELECT a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i)'); SELECT create_immv('mv_ivm_subquery', 'SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 2'); +SELECT create_immv('mv_ivm_subquery', 'SELECT a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_a a2 WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a2.i = b.i))'); -- support join subquery in FROM clause BEGIN; @@ -379,6 +380,7 @@ ROLLBACK; --- disallow not-simple CTE SELECT create_immv('mv_cte_fail', 'WITH b AS (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i'); SELECT create_immv('mv_cte_fail', 'WITH b AS (SELECT DISTINCT i FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i'); +SELECT create_immv('mv_cte_fail', 'WITH a AS (SELECT i, j FROM mv_base_a) SELECT a.i,a.j FROM a WHERE EXISTS(WITH b AS (SELECT i FROM mv_base_b) SELECT 1 FROM b WHERE a.i = b.i)'); -- unreferenced CTE SELECT create_immv('mv_cte_fail', 'WITH b AS (SELECT * FROM mv_base_b) SELECT * FROM mv_base_a a');