diff --git a/createas.c b/createas.c index 5b50293..756c4b2 100644 --- a/createas.c +++ b/createas.c @@ -66,7 +66,8 @@ typedef struct { bool has_agg; bool has_subquery; - bool in_exists_subquery; /* true, if it is in a exists subquery */ + bool in_exists_subquery; /* true, if it is in a exists subquery */ + bool in_jointree; /* true, if it is in a join tree */ List *exists_qual_vars; int sublevels_up; } check_ivm_restriction_context; @@ -746,7 +747,7 @@ CreateIvmTrigger(Oid relOid, Oid viewOid, int16 type, int16 timing, bool ex_lock static void check_ivm_restriction(Node *node) { - check_ivm_restriction_context context = {false, false, false, NIL, 0}; + check_ivm_restriction_context context = {false, false, false, false, NIL, 0}; check_ivm_restriction_walker(node, &context); } @@ -968,11 +969,6 @@ check_ivm_restriction_walker(Node *node, check_ivm_restriction_context *context) case T_TargetEntry: { TargetEntry *tle = (TargetEntry *)node; - if (IsA(tle->expr, SubLink)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("this query is not allowed on incrementally maintainable materialized view"), - errhint("sublink only supports subquery with EXISTS clause in WHERE clause"))); if (isIvmName(tle->resname)) ereport(ERROR, @@ -986,6 +982,16 @@ check_ivm_restriction_walker(Node *node, check_ivm_restriction_context *context) expression_tree_walker(node, check_ivm_restriction_walker, (void *) context); break; } + case T_FromExpr: + { + FromExpr *from = (FromExpr *) node; + + check_ivm_restriction_walker((Node *)from->fromlist, context); + context->in_jointree = true; + check_ivm_restriction_walker(from->quals, context); + context->in_jointree = false; + break; + } case T_JoinExpr: { JoinExpr *joinexpr = (JoinExpr *)node; @@ -1043,7 +1049,7 @@ check_ivm_restriction_walker(Node *node, check_ivm_restriction_context *context) /* Currently, EXISTS clause is supported only */ Query *subselect; SubLink *sublink = (SubLink *) node; - if (sublink->subLinkType != EXISTS_SUBLINK) + if (!context->in_jointree || sublink->subLinkType != EXISTS_SUBLINK) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("this query is not allowed on incrementally maintainable materialized view"), diff --git a/expected/pg_ivm.out b/expected/pg_ivm.out index b7990a4..7a5e9fd 100644 --- a/expected/pg_ivm.out +++ b/expected/pg_ivm.out @@ -848,6 +848,12 @@ ERROR: nested sublink is not supported on incrementally maintainable materializ SELECT create_immv('mv_ivm_subquery', 'SELECT EXISTS(SELECT 1 from mv_base_b) FROM mv_base_a a'); ERROR: this query is not allowed on incrementally maintainable materialized view HINT: sublink only supports subquery with EXISTS clause in WHERE clause +SELECT create_immv('mv_ivm_subquery', 'SELECT false OR EXISTS(SELECT 1 FROM mv_base_a) FROM mv_base_b'); +ERROR: this query is not allowed on incrementally maintainable materialized view +HINT: sublink only supports subquery with EXISTS clause in WHERE clause +SELECT create_immv('mv_ivm_subquery', 'SELECT * FROM generate_series(1, CASE EXISTS(SELECT 1 FROM mv_base_a) WHEN true THEN 100 ELSE 10 END), mv_base_b'); +ERROR: this query is not allowed on incrementally maintainable materialized view +HINT: sublink only supports subquery with EXISTS clause in WHERE clause -- 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/sql/pg_ivm.sql b/sql/pg_ivm.sql index 80f0c88..1caa3bf 100644 --- a/sql/pg_ivm.sql +++ b/sql/pg_ivm.sql @@ -272,6 +272,8 @@ SELECT create_immv('mv_ivm_subquery', 'SELECT a.j FROM mv_base_a a WHERE EXISTS( 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))'); SELECT create_immv('mv_ivm_subquery', 'SELECT EXISTS(SELECT 1 from mv_base_b) FROM mv_base_a a'); +SELECT create_immv('mv_ivm_subquery', 'SELECT false OR EXISTS(SELECT 1 FROM mv_base_a) FROM mv_base_b'); +SELECT create_immv('mv_ivm_subquery', 'SELECT * FROM generate_series(1, CASE EXISTS(SELECT 1 FROM mv_base_a) WHEN true THEN 100 ELSE 10 END), mv_base_b'); -- support join subquery in FROM clause BEGIN;