diff --git a/createas.c b/createas.c index 8129415..7ebe0da 100644 --- a/createas.c +++ b/createas.c @@ -66,6 +66,7 @@ typedef struct typedef struct { bool has_agg; + bool has_sublinks; bool has_subquery; bool in_exists_subquery; /* true, if it is in a exists subquery */ bool in_jointree; /* true, if it is in a join tree */ @@ -748,7 +749,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, false, NIL, 0}; + check_ivm_restriction_context context = {false, false, false, false, false, NIL, 0}; check_ivm_restriction_walker(node, &context); } @@ -815,6 +816,8 @@ check_ivm_restriction_walker(Node *node, check_ivm_restriction_context *context) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("recursive query is not supported on incrementally maintainable materialized view"))); + context->has_sublinks |= qry->hasSubLinks; + /* system column restrictions */ vars = pull_vars_of_level((Node *) qry, 0); foreach(lc, vars) @@ -1008,10 +1011,23 @@ check_ivm_restriction_walker(Node *node, check_ivm_restriction_context *context) FromExpr *from = (FromExpr *) node; check_ivm_restriction_walker((Node *)from->fromlist, context); + /* + * check the sublink restrictions. + * Currently, EXISTS subqueries with condition other than 'AND' is not supported. + */ + if (from->quals == NULL) + break; + if (context->has_sublinks && !context->in_exists_subquery && + !IsA(from->quals, SubLink) && !IsA(from->quals, BoolExpr)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("this query is not allowed on incrementally maintainable materialized view"), + errhint("sublink only supports simple conditions with EXISTS clause in WHERE clause"))); + context->in_jointree = true; check_ivm_restriction_walker(from->quals, context); context->in_jointree = false; - break; + break; } case T_JoinExpr: { diff --git a/expected/pg_ivm.out b/expected/pg_ivm.out index bf559d3..990ef62 100644 --- a/expected/pg_ivm.out +++ b/expected/pg_ivm.out @@ -888,6 +888,9 @@ 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 +SELECT create_immv('mv_ivm_subquery', 'SELECT * FROM mv_base_a a WHERE CASE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) WHEN true THEN false ELSE true END'); +ERROR: this query is not allowed on incrementally maintainable materialized view +HINT: sublink only supports simple conditions 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 f99224c..017c26c 100644 --- a/sql/pg_ivm.sql +++ b/sql/pg_ivm.sql @@ -292,6 +292,7 @@ SELECT create_immv('mv_ivm_subquery', 'SELECT a.j FROM mv_base_a a WHERE EXISTS( 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'); +SELECT create_immv('mv_ivm_subquery', 'SELECT * FROM mv_base_a a WHERE CASE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) WHEN true THEN false ELSE true END'); -- support join subquery in FROM clause BEGIN;