diff --git a/README.md b/README.md index 850e9ac..ca4e6b9 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,10 @@ Currently, IMMV's view definition can contain inner joins, DISTINCT clause, some The base tables must be simple tables. Views, materialized views, inheritance parent tables, partitioned tables, partitions, and foreign tables can not be used. -The targetlist cannot contain system columns, columns whose name starts with `__ivm_`. +Any system column cannot be included in the view definition query. +The target list cannot columns whose name starts with `__ivm_`. + +Data type used in the target list in the view must have default operator class for access method btree. For example, `json`, `xml`, or `point` type cannot be in the target list. Logical replication is not supported, that is, even when a base table at a publisher node is modified, IMMVs at subscriber nodes defined on these base tables are not updated. diff --git a/createas.c b/createas.c index acf518e..8129415 100644 --- a/createas.c +++ b/createas.c @@ -17,6 +17,7 @@ #include "catalog/dependency.h" #include "catalog/index.h" #include "catalog/indexing.h" +#include "catalog/pg_am.h" #include "catalog/pg_constraint.h" #include "catalog/pg_inherits.h" #include "catalog/pg_trigger_d.h" @@ -828,6 +829,26 @@ check_ivm_restriction_walker(Node *node, check_ivm_restriction_context *context) errmsg("system column is not supported on incrementally maintainable materialized view"))); } } + + /* check if type in the top target list had an equality operator */ + if (context->sublevels_up == 0) + { + foreach(lc, qry->targetList) + { + TargetEntry *tle = (TargetEntry *) lfirst(lc); + Oid atttype = exprType((Node *) tle->expr); + Oid opclass; + + + opclass = GetDefaultOpClass(atttype, BTREE_AM_OID); + if (!OidIsValid(opclass)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("data type %s has no default operator class for access method \"%s\"", + format_type_be(atttype), "btree"))); + } + } + /* subquery restrictions */ if (context->sublevels_up > 0 && qry->distinctClause != NIL) ereport(ERROR, diff --git a/expected/pg_ivm.out b/expected/pg_ivm.out index a6c1fd2..bf559d3 100644 --- a/expected/pg_ivm.out +++ b/expected/pg_ivm.out @@ -1635,6 +1635,12 @@ NOTICE: created index "mv_idx6_index" on immv "mv_idx6" 0 (1 row) +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +SELECT create_immv('mv_json', 'SELECT * from table_json'); +ERROR: data type json has no default operator class for access method "btree" ROLLBACK; -- prevent IMMV chanages INSERT INTO mv_ivm_1 VALUES(1,1,1); diff --git a/sql/pg_ivm.sql b/sql/pg_ivm.sql index a366d7a..f99224c 100644 --- a/sql/pg_ivm.sql +++ b/sql/pg_ivm.sql @@ -658,6 +658,12 @@ SELECT create_immv('mv_idx5', 'SELECT a.i, b.j FROM base_a a, base_b b'); SELECT create_immv('mv_idx6(i_a, i_b)', 'SELECT a.i, b.i FROM (SELECT * FROM base_a) a, (SELECT * FROM base_b) b'); ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +SELECT create_immv('mv_json', 'SELECT * from table_json'); +ROLLBACK; + -- prevent IMMV chanages INSERT INTO mv_ivm_1 VALUES(1,1,1); UPDATE mv_ivm_1 SET k = 1 WHERE i = 1;