summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/pg_inherits.c26
-rw-r--r--src/backend/rewrite/rewriteDefine.c19
-rw-r--r--src/include/catalog/pg_inherits_fn.h1
-rw-r--r--src/test/regress/expected/rules.out11
-rw-r--r--src/test/regress/sql/rules.sql11
5 files changed, 62 insertions, 6 deletions
diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c
index 04687c1a3e1..d0fd1a4170d 100644
--- a/src/backend/catalog/pg_inherits.c
+++ b/src/backend/catalog/pg_inherits.c
@@ -254,6 +254,32 @@ has_subclass(Oid relationId)
return result;
}
+/*
+ * has_superclass - does this relation inherit from another?
+ *
+ * Unlike has_subclass, this can be relied on to give an accurate answer.
+ * However, the caller must hold a lock on the given relation so that it
+ * can't be concurrently added to or removed from an inheritance hierarchy.
+ */
+bool
+has_superclass(Oid relationId)
+{
+ Relation catalog;
+ SysScanDesc scan;
+ ScanKeyData skey;
+ bool result;
+
+ catalog = heap_open(InheritsRelationId, AccessShareLock);
+ ScanKeyInit(&skey, Anum_pg_inherits_inhrelid, BTEqualStrategyNumber,
+ F_OIDEQ, ObjectIdGetDatum(relationId));
+ scan = systable_beginscan(catalog, InheritsRelidSeqnoIndexId, true,
+ NULL, 1, &skey);
+ result = HeapTupleIsValid(systable_getnext(scan));
+ systable_endscan(scan);
+ heap_close(catalog, AccessShareLock);
+
+ return result;
+}
/*
* Given two type OIDs, determine whether the first is a complex type
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 357847f1f01..d2dea4e696b 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -25,6 +25,7 @@
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
+#include "catalog/pg_inherits_fn.h"
#include "catalog/pg_rewrite.h"
#include "catalog/storage.h"
#include "commands/policy.h"
@@ -411,12 +412,12 @@ DefineQueryRewrite(char *rulename,
*
* If so, check that the relation is empty because the storage for the
* relation is going to be deleted. Also insist that the rel not have
- * any triggers, indexes, child tables, policies, or RLS enabled.
- * (Note: these tests are too strict, because they will reject
- * relations that once had such but don't anymore. But we don't
- * really care, because this whole business of converting relations
- * to views is just a kluge to allow dump/reload of views that
- * participate in circular dependencies.)
+ * any triggers, indexes, child or parent tables, RLS policies, or RLS
+ * enabled. (Note: some of these tests are too strict, because they
+ * will reject relations that once had such but don't anymore. But we
+ * don't really care, because this whole business of converting
+ * relations to views is just a kluge to allow dump/reload of views
+ * that participate in circular dependencies.)
*/
if (event_relation->rd_rel->relkind != RELKIND_VIEW &&
event_relation->rd_rel->relkind != RELKIND_MATVIEW)
@@ -453,6 +454,12 @@ DefineQueryRewrite(char *rulename,
errmsg("could not convert table \"%s\" to a view because it has child tables",
RelationGetRelationName(event_relation))));
+ if (has_superclass(RelationGetRelid(event_relation)))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("could not convert table \"%s\" to a view because it has parent tables",
+ RelationGetRelationName(event_relation))));
+
if (event_relation->rd_rel->relrowsecurity)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
diff --git a/src/include/catalog/pg_inherits_fn.h b/src/include/catalog/pg_inherits_fn.h
index 3ff1947f3e2..2a8ced5f67d 100644
--- a/src/include/catalog/pg_inherits_fn.h
+++ b/src/include/catalog/pg_inherits_fn.h
@@ -21,6 +21,7 @@ extern List *find_inheritance_children(Oid parentrelId, LOCKMODE lockmode);
extern List *find_all_inheritors(Oid parentrelId, LOCKMODE lockmode,
List **parents);
extern bool has_subclass(Oid relationId);
+extern bool has_superclass(Oid relationId);
extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);
#endif /* PG_INHERITS_FN_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 615e14fbe48..1d094b995ae 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2457,6 +2457,17 @@ select reltoastrelid, relkind, relfrozenxid
(1 row)
drop view fooview;
+-- cannot convert an inheritance parent or child to a view, though
+create table fooview (x int, y text);
+create table fooview_child () inherits (fooview);
+create rule "_RETURN" as on select to fooview do instead
+ select 1 as x, 'aaa'::text as y;
+ERROR: could not convert table "fooview" to a view because it has child tables
+create rule "_RETURN" as on select to fooview_child do instead
+ select 1 as x, 'aaa'::text as y;
+ERROR: could not convert table "fooview_child" to a view because it has parent tables
+drop table fooview cascade;
+NOTICE: drop cascades to table fooview_child
--
-- check for planner problems with complex inherited UPDATES
--
diff --git a/src/test/regress/sql/rules.sql b/src/test/regress/sql/rules.sql
index 12cd4a012bc..347545063f0 100644
--- a/src/test/regress/sql/rules.sql
+++ b/src/test/regress/sql/rules.sql
@@ -898,6 +898,17 @@ select reltoastrelid, relkind, relfrozenxid
drop view fooview;
+-- cannot convert an inheritance parent or child to a view, though
+create table fooview (x int, y text);
+create table fooview_child () inherits (fooview);
+
+create rule "_RETURN" as on select to fooview do instead
+ select 1 as x, 'aaa'::text as y;
+create rule "_RETURN" as on select to fooview_child do instead
+ select 1 as x, 'aaa'::text as y;
+
+drop table fooview cascade;
+
--
-- check for planner problems with complex inherited UPDATES
--