Just stumbled across the same issues while upgrading one of my cluster to Pg 10 with pg_upgrade. Finished the upgrade by fixing the old database(s) and re-running pg_upgrade.
2017-08-04 23:06 GMT+07:00 Michael Paquier <michael.paqu...@gmail.com>: > > On Fri, Aug 4, 2017 at 5:50 PM, Tom Lane <t...@sss.pgh.pa.us> wrote: > > Michael Paquier <michael.paqu...@gmail.com> writes: > >> So I think that the attached patch is able to do the legwork. > > > > I've pushed this into HEAD. It seems like enough of a behavioral > > change that we wouldn't want to back-patch, but IMO it's not too late > > to be making this type of change in v10. If we wait for the next CF > > then it will take another year for the fix to reach the field. > > Thanks for applying the fix. My intention when adding that in a CF is > not to see things lost. Thans for the fix. Just found some issues: 1. My old database schema becomes like that by accidental modification on the child table, and on HEAD, it still works: # create table parent (id serial PRIMARY KEY, name VARCHAR(52) NOT NULL); CREATE TABLE # create table child () inherits (parent); CREATE TABLE # alter table child alter column name drop not null; ALTER TABLE # \d parent Table "public.parent" Column | Type | Collation | Nullable | Default --------+-----------------------+-----------+----------+------------------------------------ id | integer | | not null | nextval('parent_id_seq'::regclass) name | character varying(52) | | not null | Indexes: "parent_pkey" PRIMARY KEY, btree (id) Number of child tables: 1 (Use \d+ to list them.) # \d child Table "public.child" Column | Type | Collation | Nullable | Default --------+-----------------------+-----------+----------+------------------------------------ id | integer | | not null | nextval('parent_id_seq'::regclass) name | character varying(52) | | | Inherits: parent 2. If we execute pg_dump manually, it silently corrects the schema: ..... (cut) -- -- Name: parent; Type: TABLE; Schema: public; Owner: - -- CREATE TABLE parent ( id integer NOT NULL, name character varying(52) NOT NULL ); -- -- Name: child; Type: TABLE; Schema: public; Owner: - -- CREATE TABLE child ( ) INHERITS (parent); ...... (cut) There is't any DROP NOT NULL there. For me, it's better to prevent that from happening. So, attempts to DROP NOT NULL on the child must be rejected. The attached patch does that. Unfortunately, pg_class has no "has_parent" attribute, so in this patch, it hits pg_inherits everytime DROP NOT NULL is attempted. Notes: - It looks like we could remove the parent partition checking above? Because the new check already covers what it does - If this patch will be applied, i will work on pg_upgrade to check for this problem before attempting to dump schema. In my case, because the cluster has many databases, the error arise much late in the process, it will be much better if pg_upgrade complains while performing pre-checks. Best Regards, Ali Akbar
[1mdiff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c[m [1mindex 1bd8a58b7f..74903a8f24 100644[m [1m--- a/src/backend/catalog/pg_inherits.c[m [1m+++ b/src/backend/catalog/pg_inherits.c[m [36m@@ -242,6 +242,40 @@[m [mfind_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)[m }[m [m [m [32m+[m[32m/*[m [32m+[m[32m * get_superclasses -[m [32m+[m[32m * Returns a list of relation OIDs of direct parents[m [32m+[m[32m */[m [32m+[m[32mList *[m [32m+[m[32mget_superclasses(Oid relationId)[m [32m+[m[32m{[m [32m+[m [32mList *list = NIL;[m [32m+[m [32mRelation catalog;[m [32m+[m [32mSysScanDesc scan;[m [32m+[m [32mScanKeyData skey;[m [32m+[m [32mHeapTuple inheritsTuple;[m [32m+[m [32mOid inhparent;[m [32m+[m [32m+[m [32mcatalog = heap_open(InheritsRelationId, AccessShareLock);[m [32m+[m [32mScanKeyInit(&skey, Anum_pg_inherits_inhrelid, BTEqualStrategyNumber,[m [32m+[m [32mF_OIDEQ, ObjectIdGetDatum(relationId));[m [32m+[m [32mscan = systable_beginscan(catalog, InheritsRelidSeqnoIndexId, true,[m [32m+[m [32m NULL, 1, &skey);[m [32m+[m [32m+[m [32mwhile ((inheritsTuple = systable_getnext(scan)) != NULL)[m [32m+[m [32m{[m [32m+[m [32minhparent = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhparent;[m [32m+[m [32mlist = lappend_oid(list, inhparent);[m [32m+[m [32m}[m [32m+[m [32m+[m [32msystable_endscan(scan);[m [32m+[m [32m+[m [32mheap_close(catalog, AccessShareLock);[m [32m+[m [32m+[m [32mreturn list;[m [32m+[m[32m}[m [32m+[m [32m+[m /*[m * has_subclass - does this relation have any children?[m *[m [1mdiff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c[m [1mindex d979ce266d..c76fc3715d 100644[m [1m--- a/src/backend/commands/tablecmds.c[m [1m+++ b/src/backend/commands/tablecmds.c[m [36m@@ -5683,6 +5683,8 @@[m [mATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)[m Relation attr_rel;[m List *indexoidlist;[m ListCell *indexoidscan;[m [32m+[m [32mList *parentlist;[m [32m+[m [32mListCell *parentscan;[m ObjectAddress address;[m [m /*[m [36m@@ -5773,6 +5775,24 @@[m [mATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)[m heap_close(parent, AccessShareLock);[m }[m [m [32m+[m [32m/* If rel has parents, shoudn't drop NOT NULL if parent has the same */[m [32m+[m [32mparentlist = get_superclasses(RelationGetRelid(rel));[m [32m+[m [32mforeach(parentscan, parentlist) {[m [32m+[m [32mOid parentId = lfirst_oid(parentscan);[m [32m+[m [32mRelation parent = heap_open(parentId, AccessShareLock);[m [32m+[m [32mTupleDesc tupDesc = RelationGetDescr(parent);[m [32m+[m [32mAttrNumber parent_attnum;[m [32m+[m [32m+[m [32mparent_attnum = get_attnum(parentId, colName);[m [32m+[m [32mif (parent_attnum != InvalidAttrNumber &&[m [32m+[m [32mTupleDescAttr(tupDesc, parent_attnum - 1)->attnotnull)[m [32m+[m [32mereport(ERROR,[m [32m+[m [32m(errcode(ERRCODE_INVALID_TABLE_DEFINITION),[m [32m+[m [32m errmsg("column \"%s\" is marked NOT NULL in parent table",[m [32m+[m [32mcolName)));[m [32m+[m [32mheap_close(parent, AccessShareLock);[m [32m+[m [32m}[m [32m+[m /*[m * Okay, actually perform the catalog change ... if needed[m */[m [1mdiff --git a/src/include/catalog/pg_inherits_fn.h b/src/include/catalog/pg_inherits_fn.h[m [1mindex 7743388899..291861b846 100644[m [1m--- a/src/include/catalog/pg_inherits_fn.h[m [1m+++ b/src/include/catalog/pg_inherits_fn.h[m [36m@@ -20,6 +20,7 @@[m extern List *find_inheritance_children(Oid parentrelId, LOCKMODE lockmode);[m extern List *find_all_inheritors(Oid parentrelId, LOCKMODE lockmode,[m List **parents);[m [32m+[m[32mextern List *get_superclasses(Oid relationId);[m extern bool has_subclass(Oid relationId);[m extern bool has_superclass(Oid relationId);[m extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);[m