Hi,
Just a quick scan-through review: On 2018-06-20 12:51:07 -0400, Andrew Dunstan wrote: > diff --git a/src/backend/utils/adt/pg_upgrade_support.c > b/src/backend/utils/adt/pg_upgrade_support.c > index 0c54b02..2666ab2 100644 > --- a/src/backend/utils/adt/pg_upgrade_support.c > +++ b/src/backend/utils/adt/pg_upgrade_support.c > @@ -11,14 +11,19 @@ > > #include "postgres.h" > > +#include "access/heapam.h" > +#include "access/htup_details.h" > #include "catalog/binary_upgrade.h" > +#include "catalog/indexing.h" > #include "catalog/namespace.h" > #include "catalog/pg_type.h" > #include "commands/extension.h" > #include "miscadmin.h" > #include "utils/array.h" > #include "utils/builtins.h" > - > +#include "utils/lsyscache.h" > +#include "utils/rel.h" > +#include "utils/syscache.h" > Seems to delete a newline. > #define CHECK_IS_BINARY_UPGRADE > \ > do { > \ > @@ -192,3 +197,66 @@ binary_upgrade_set_record_init_privs(PG_FUNCTION_ARGS) > > PG_RETURN_VOID(); > } > + > +Datum > +binary_upgrade_set_missing_value(PG_FUNCTION_ARGS) > +{ > + Oid table_id = PG_GETARG_OID(0); > + text *attname = PG_GETARG_TEXT_P(1); > + text *value = PG_GETARG_TEXT_P(2); > + Datum valuesAtt[Natts_pg_attribute]; > + bool nullsAtt[Natts_pg_attribute]; > + bool replacesAtt[Natts_pg_attribute]; > + Datum missingval; > + Form_pg_attribute attStruct; > + Relation attrrel; > + HeapTuple atttup, newtup; > + Oid inputfunc, inputparam; > + char *cattname = text_to_cstring(attname); > + char *cvalue = text_to_cstring(value); > + > + CHECK_IS_BINARY_UPGRADE; > + > + /* Lock the attribute row and get the data */ > + attrrel = heap_open(AttributeRelationId, RowExclusiveLock); Maybe I'm being paranoid, but I feel like the relation should also be locked here. > + atttup = SearchSysCacheAttName(table_id,cattname); Missing space before 'cattname'. > + if (!HeapTupleIsValid(atttup)) > + elog(ERROR, "cache lookup failed for attribute %s of relation > %u", > + cattname, table_id); > + attStruct = (Form_pg_attribute) GETSTRUCT(atttup); > + > + /* get an array value from the value string */ > + > + /* find the io info for an arbitrary array type to get array_in Oid */ > + getTypeInputInfo(INT4ARRAYOID, &inputfunc, &inputparam); Maybe I'm confused, but why INT4ARRAYOID? If you're just looking for the oid of array_in, why not use F_ARRAY_IN? > + missingval = OidFunctionCall3( > + inputfunc, /* array_in */ > + CStringGetDatum(cvalue), > + ObjectIdGetDatum(attStruct->atttypid), > + Int32GetDatum(attStruct->atttypmod)); > + > + /* update the tuple - set atthasmissing and attmissingval */ > + MemSet(valuesAtt, 0, sizeof(valuesAtt)); > + MemSet(nullsAtt, false, sizeof(nullsAtt)); > + MemSet(replacesAtt, false, sizeof(replacesAtt)); > + > + valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true); > + replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true; > + valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval; > + replacesAtt[Anum_pg_attribute_attmissingval - 1] = true; > + > + newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel), > + valuesAtt, nullsAtt, > replacesAtt); > + CatalogTupleUpdate(attrrel, &newtup->t_self, newtup); > + /* clean up */ > + heap_freetuple(newtup); > + ReleaseSysCache(atttup); > + pfree(cattname); > + pfree(cvalue); > + pfree(DatumGetPointer(missingval)); Is this worth bothering with (except the ReleaseSysCache)? We'll clean up via memory context soon, no? Greetings, Andres Freund