From 0f83f789a1a605464d33d6a8f3856655b80efec9 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Fri, 14 Nov 2025 08:43:14 -0500 Subject: [PATCH v1 2/2] Update the remainder of catalog updates using the new APIs Apply all necessary changes to use the new macros for catalog tuples. This commit finishes the work started in the previous one. There should be no behavioral changes resulting from these commits. This simply provides a syntatic change with the additional ability to maintain the set of updated attributes during catalog updates. --- src/backend/catalog/aclchk.c | 159 +++--- src/backend/catalog/heap.c | 359 ++++++------- src/backend/catalog/index.c | 177 +++--- src/backend/catalog/partition.c | 5 +- src/backend/catalog/pg_attrdef.c | 35 +- src/backend/catalog/pg_cast.c | 18 +- src/backend/catalog/pg_collation.c | 40 +- src/backend/catalog/pg_conversion.c | 22 +- src/backend/catalog/pg_db_role_setting.c | 54 +- src/backend/catalog/pg_depend.c | 72 +-- src/backend/catalog/pg_enum.c | 45 +- src/backend/catalog/pg_inherits.c | 14 +- src/backend/catalog/pg_largeobject.c | 22 +- src/backend/catalog/pg_namespace.c | 24 +- src/backend/catalog/pg_operator.c | 119 ++-- src/backend/catalog/pg_parameter_acl.c | 11 +- src/backend/catalog/pg_proc.c | 110 ++-- src/backend/catalog/pg_publication.c | 36 +- src/backend/catalog/pg_range.c | 20 +- src/backend/catalog/pg_shdepend.c | 60 +-- src/backend/catalog/pg_subscription.c | 86 ++- src/backend/catalog/pg_type.c | 211 ++++---- src/backend/catalog/toasting.c | 7 +- src/backend/commands/amcmds.c | 15 +- src/backend/commands/cluster.c | 80 +-- src/backend/commands/collationcmds.c | 19 +- src/backend/commands/comment.c | 51 +- src/backend/commands/dbcommands.c | 133 +++-- src/backend/commands/event_trigger.c | 42 +- src/backend/commands/extension.c | 107 ++-- src/backend/commands/foreigncmds.c | 205 +++---- src/backend/commands/functioncmds.c | 52 +- src/backend/commands/indexcmds.c | 16 +- src/backend/commands/matview.c | 7 +- src/backend/commands/opclasscmds.c | 82 +-- src/backend/commands/operatorcmds.c | 54 +- src/backend/commands/policy.c | 98 ++-- src/backend/commands/proclang.c | 44 +- src/backend/commands/publicationcmds.c | 85 ++- src/backend/commands/schemacmds.c | 25 +- src/backend/commands/seclabel.c | 57 +- src/backend/commands/sequence.c | 32 +- src/backend/commands/statscmds.c | 50 +- src/backend/commands/subscriptioncmds.c | 187 +++---- src/backend/commands/tablecmds.c | 567 ++++++++++++-------- src/backend/commands/tablespace.c | 47 +- src/backend/commands/trigger.c | 107 ++-- src/backend/commands/tsearchcmds.c | 169 +++--- src/backend/commands/typecmds.c | 136 ++--- src/backend/commands/user.c | 228 +++----- src/backend/replication/logical/origin.c | 10 +- src/backend/replication/logical/tablesync.c | 22 +- src/backend/replication/logical/worker.c | 17 +- src/backend/rewrite/rewriteDefine.c | 59 +- src/backend/rewrite/rewriteSupport.c | 6 +- src/backend/statistics/extended_stats.c | 65 ++- src/backend/statistics/relation_stats.c | 40 +- src/backend/storage/large_object/inv_api.c | 53 +- src/backend/utils/cache/relcache.c | 20 +- 59 files changed, 2227 insertions(+), 2466 deletions(-) diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index cd139bd65a6..3943d780a22 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -1316,8 +1316,7 @@ SetDefaultACL(InternalDefaultACL *iacls) else { Datum values[Natts_pg_default_acl] = {0}; - bool nulls[Natts_pg_default_acl] = {0}; - bool replaces[Natts_pg_default_acl] = {0}; + bool nulls[Natts_pg_default_acl] = {false}; Oid defAclOid; if (isNew) @@ -1325,26 +1324,28 @@ SetDefaultACL(InternalDefaultACL *iacls) /* insert new entry */ defAclOid = GetNewOidWithIndex(rel, DefaultAclOidIndexId, Anum_pg_default_acl_oid); - values[Anum_pg_default_acl_oid - 1] = ObjectIdGetDatum(defAclOid); - values[Anum_pg_default_acl_defaclrole - 1] = ObjectIdGetDatum(iacls->roleid); - values[Anum_pg_default_acl_defaclnamespace - 1] = ObjectIdGetDatum(iacls->nspid); - values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype); - values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl); + HeapTupleSetValue(pg_default_acl, oid, ObjectIdGetDatum(defAclOid), values); + HeapTupleSetValue(pg_default_acl, defaclrole, ObjectIdGetDatum(iacls->roleid), values); + HeapTupleSetValue(pg_default_acl, defaclnamespace, ObjectIdGetDatum(iacls->nspid), values); + HeapTupleSetValue(pg_default_acl, defaclobjtype, CharGetDatum(objtype), values); + HeapTupleSetValue(pg_default_acl, defaclacl, PointerGetDatum(new_acl), values); newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls); - CatalogTupleInsert(rel, newtuple); + CatalogTupleInsert(rel, newtuple, NULL); } else { + Bitmapset *updated = NULL; + defAclOid = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid; /* update existing entry */ - values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl); - replaces[Anum_pg_default_acl_defaclacl - 1] = true; + HeapTupleUpdateValue(pg_default_acl, defaclacl, PointerGetDatum(new_acl), values, nulls, updated); + + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), - values, nulls, replaces); - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + bms_free(updated); } /* these dependencies don't change in an update */ @@ -1650,12 +1651,12 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname, bool need_update; HeapTuple newtuple; Datum values[Natts_pg_attribute] = {0}; - bool nulls[Natts_pg_attribute] = {0}; - bool replaces[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; int noldmembers; int nnewmembers; Oid *oldmembers; Oid *newmembers; + Bitmapset *updated = NULL; attr_tuple = SearchSysCache2(ATTNUM, ObjectIdGetDatum(relOid), @@ -1742,22 +1743,21 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname, */ if (ACL_NUM(new_acl) > 0) { - values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl); + HeapTupleUpdateValue(pg_attribute, attacl, PointerGetDatum(new_acl), values, nulls, updated); need_update = true; } else { - nulls[Anum_pg_attribute_attacl - 1] = true; + HeapTupleUpdateValueNull(pg_attribute, attacl, values, nulls, updated); need_update = !isNull; } - replaces[Anum_pg_attribute_attacl - 1] = true; if (need_update) { - newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation), - values, nulls, replaces); + newtuple = heap_update_tuple(attr_tuple, RelationGetDescr(attRelation), + values, nulls, updated); - CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple, updated, NULL); /* Update initial privileges for extensions */ recordExtensionInitPriv(relOid, RelationRelationId, attnum, @@ -1773,6 +1773,7 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname, pfree(new_acl); ReleaseSysCache(attr_tuple); + bms_free(updated); } /* @@ -1960,8 +1961,8 @@ ExecGrant_Relation(InternalGrant *istmt) Oid grantorId; HeapTuple newtuple; Datum values[Natts_pg_class] = {0}; - bool nulls[Natts_pg_class] = {0}; - bool replaces[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; + Bitmapset *updated = NULL; int nnewmembers; Oid *newmembers; ObjectType objtype; @@ -2011,13 +2012,12 @@ ExecGrant_Relation(InternalGrant *istmt) nnewmembers = aclmembers(new_acl, &newmembers); /* finished building new ACL value, now insert it */ - replaces[Anum_pg_class_relacl - 1] = true; - values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl); + HeapTupleUpdateValue(pg_class, relacl, PointerGetDatum(new_acl), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), - values, nulls, replaces); + newtuple = heap_update_tuple(tuple, RelationGetDescr(relation), + values, nulls, updated); - CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(relation, &newtuple->t_self, newtuple, updated, NULL); UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); /* Update initial privileges for extensions */ @@ -2030,6 +2030,7 @@ ExecGrant_Relation(InternalGrant *istmt) nnewmembers, newmembers); pfree(new_acl); + bms_free(updated); } else UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); @@ -2140,7 +2141,7 @@ ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, HeapTuple newtuple; Datum *values = palloc0_array(Datum, RelationGetDescr(relation)->natts); bool *nulls = palloc0_array(bool, RelationGetDescr(relation)->natts); - bool *replaces = palloc0_array(bool, RelationGetDescr(relation)->natts); + Bitmapset *updated = NULL; int noldmembers; int nnewmembers; Oid *oldmembers; @@ -2214,14 +2215,17 @@ ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, */ nnewmembers = aclmembers(new_acl, &newmembers); - /* finished building new ACL value, now insert it */ - replaces[get_object_attnum_acl(classid) - 1] = true; + /* + * Finished building new ACL value, now insert it. NOTE: We can't use + * the HeapTupleMarkColumnUpdated() macro here because + * get_object_attnum_acl(classid) provides an index. + */ values[get_object_attnum_acl(classid) - 1] = PointerGetDatum(new_acl); + updated = bms_add_member(updated, get_object_attnum_acl(classid) - FirstLowInvalidHeapAttributeNumber); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, - nulls, replaces); + newtuple = heap_update_tuple(tuple, RelationGetDescr(relation), values, nulls, updated); - CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(relation, &newtuple->t_self, newtuple, updated, NULL); UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); /* Update initial privileges for extensions */ @@ -2237,6 +2241,7 @@ ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, ReleaseSysCache(tuple); pfree(new_acl); + bms_free(updated); /* prevent error when processing duplicate objects */ CommandCounterIncrement(); @@ -2288,8 +2293,8 @@ ExecGrant_Largeobject(InternalGrant *istmt) Oid ownerId; HeapTuple newtuple; Datum values[Natts_pg_largeobject_metadata] = {0}; - bool nulls[Natts_pg_largeobject_metadata] = {0}; - bool replaces[Natts_pg_largeobject_metadata] = {0}; + bool nulls[Natts_pg_largeobject_metadata] = {false}; + Bitmapset *updated = NULL; int noldmembers; int nnewmembers; Oid *oldmembers; @@ -2367,14 +2372,12 @@ ExecGrant_Largeobject(InternalGrant *istmt) nnewmembers = aclmembers(new_acl, &newmembers); /* finished building new ACL value, now insert it */ - replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true; - values[Anum_pg_largeobject_metadata_lomacl - 1] - = PointerGetDatum(new_acl); + HeapTupleUpdateValue(pg_largeobject_metadata, lomacl, PointerGetDatum(new_acl), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), - values, nulls, replaces); + newtuple = heap_update_tuple(tuple, RelationGetDescr(relation), + values, nulls, updated); - CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(relation, &newtuple->t_self, newtuple, updated, NULL); /* Update initial privileges for extensions */ recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl); @@ -2389,6 +2392,7 @@ ExecGrant_Largeobject(InternalGrant *istmt) systable_endscan(scan); pfree(new_acl); + bms_free(updated); /* prevent error when processing duplicate objects */ CommandCounterIncrement(); @@ -2527,16 +2531,16 @@ ExecGrant_Parameter(InternalGrant *istmt) /* finished building new ACL value, now insert it */ HeapTuple newtuple; Datum values[Natts_pg_parameter_acl] = {0}; - bool nulls[Natts_pg_parameter_acl] = {0}; - bool replaces[Natts_pg_parameter_acl] = {0}; + bool nulls[Natts_pg_parameter_acl] = {false}; + Bitmapset *updated = NULL; - replaces[Anum_pg_parameter_acl_paracl - 1] = true; - values[Anum_pg_parameter_acl_paracl - 1] = PointerGetDatum(new_acl); + HeapTupleUpdateValue(pg_parameter_acl, paracl, PointerGetDatum(new_acl), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), - values, nulls, replaces); + newtuple = heap_update_tuple(tuple, RelationGetDescr(relation), + values, nulls, updated); - CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(relation, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); } /* Update initial privileges for extensions */ @@ -4667,8 +4671,8 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, if (HeapTupleIsValid(oldtuple)) { Datum values[Natts_pg_init_privs] = {0}; - bool nulls[Natts_pg_init_privs] = {0}; - bool replace[Natts_pg_init_privs] = {0}; + bool nulls[Natts_pg_init_privs] = {false}; + Bitmapset *updated = NULL; Datum oldAclDatum; bool isNull; Acl *old_acl; @@ -4687,13 +4691,13 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, /* If we have a new ACL to set, then update the row with it. */ if (new_acl && ACL_NUM(new_acl) != 0) { - values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl); - replace[Anum_pg_init_privs_initprivs - 1] = true; + HeapTupleUpdateValue(pg_init_privs, initprivs, PointerGetDatum(new_acl), values, nulls, updated); - oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation), - values, nulls, replace); + oldtuple = heap_update_tuple(oldtuple, RelationGetDescr(relation), + values, nulls, updated); - CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple); + CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple, updated, NULL); + bms_free(updated); } else { @@ -4704,7 +4708,7 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, else { Datum values[Natts_pg_init_privs] = {0}; - bool nulls[Natts_pg_init_privs] = {0}; + bool nulls[Natts_pg_init_privs] = {false}; /* * Only add a new entry if the new ACL is non-NULL. @@ -4715,19 +4719,18 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, if (new_acl && ACL_NUM(new_acl) != 0) { /* No entry found, so add it. */ - values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid); - values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid); - values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid); + HeapTupleSetValue(pg_init_privs, objoid, ObjectIdGetDatum(objoid), values); + HeapTupleSetValue(pg_init_privs, classoid, ObjectIdGetDatum(classoid), values); + HeapTupleSetValue(pg_init_privs, objsubid, Int32GetDatum(objsubid), values); /* This function only handles initial privileges of extensions */ - values[Anum_pg_init_privs_privtype - 1] = - CharGetDatum(INITPRIVS_EXTENSION); + HeapTupleSetValue(pg_init_privs, privtype, CharGetDatum(INITPRIVS_EXTENSION), values); - values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl); + HeapTupleSetValue(pg_init_privs, initprivs, PointerGetDatum(new_acl), values); tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls); - CatalogTupleInsert(relation, tuple); + CatalogTupleInsert(relation, tuple, NULL); /* Update pg_shdepend, too. */ noldmembers = 0; @@ -4826,16 +4829,16 @@ ReplaceRoleInInitPriv(Oid oldroleid, Oid newroleid, else { Datum values[Natts_pg_init_privs] = {0}; - bool nulls[Natts_pg_init_privs] = {0}; - bool replaces[Natts_pg_init_privs] = {0}; + bool nulls[Natts_pg_init_privs] = {false}; + Bitmapset *updated = NULL; /* Update existing entry. */ - values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl); - replaces[Anum_pg_init_privs_initprivs - 1] = true; + HeapTupleUpdateValue(pg_init_privs, initprivs, PointerGetDatum(new_acl), values, nulls, updated); - newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel), - values, nulls, replaces); - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + newtuple = heap_update_tuple(oldtuple, RelationGetDescr(rel), + values, nulls, updated); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); } /* @@ -4962,16 +4965,16 @@ RemoveRoleFromInitPriv(Oid roleid, Oid classid, Oid objid, int32 objsubid) else { Datum values[Natts_pg_init_privs] = {0}; - bool nulls[Natts_pg_init_privs] = {0}; - bool replaces[Natts_pg_init_privs] = {0}; + bool nulls[Natts_pg_init_privs] = {false}; + Bitmapset *updated2 = NULL; /* Update existing entry. */ - values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl); - replaces[Anum_pg_init_privs_initprivs - 1] = true; + HeapTupleUpdateValue(pg_init_privs, initprivs, PointerGetDatum(new_acl), values, nulls, updated2); - newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel), - values, nulls, replaces); - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + newtuple = heap_update_tuple(oldtuple, RelationGetDescr(rel), + values, nulls, updated2); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated2, NULL); + bms_free(updated2); } /* diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index fd6537567ea..a70d61c8f6b 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -30,6 +30,7 @@ #include "postgres.h" #include "access/genam.h" +#include "access/htup.h" #include "access/multixact.h" #include "access/relation.h" #include "access/table.h" @@ -705,7 +706,7 @@ CheckAttributeType(const char *attname, * number of elements as tupdesc or be NULL. The other variable-length fields * of pg_attribute are always initialized to null values. * - * indstate is the index state for CatalogTupleInsertWithInfo. It can be + * indstate is the index state for CatalogTupleInsert. It can be * passed as NULL, in which case we'll fetch the necessary info. (Don't do * this when inserting multiple attributes, because it's a tad more * expensive.) @@ -720,7 +721,7 @@ InsertPgAttributeTuples(Relation pg_attribute_rel, const FormExtraData_pg_attribute tupdesc_extra[], CatalogIndexState indstate) { - TupleTableSlot **slot; + TupleTableSlot **slots; TupleDesc td; int nslots; int natts = 0; @@ -732,66 +733,70 @@ InsertPgAttributeTuples(Relation pg_attribute_rel, /* Initialize the number of slots to use */ nslots = Min(tupdesc->natts, (MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_attribute))); - slot = palloc(sizeof(TupleTableSlot *) * nslots); + slots = palloc(sizeof(TupleTableSlot *) * nslots); for (int i = 0; i < nslots; i++) - slot[i] = MakeSingleTupleTableSlot(td, &TTSOpsHeapTuple); + slots[i] = MakeSingleTupleTableSlot(td, &TTSOpsHeapTuple); while (natts < tupdesc->natts) { + TupleTableSlot *slot = slots[slotCount]; + Datum *values = slot->tts_values; Form_pg_attribute attrs = TupleDescAttr(tupdesc, natts); const FormExtraData_pg_attribute *attrs_extra = tupdesc_extra ? &tupdesc_extra[natts] : NULL; - ExecClearTuple(slot[slotCount]); + ExecClearTuple(slot); - memset(slot[slotCount]->tts_isnull, false, - slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool)); + memset(slot->tts_isnull, false, + slot->tts_tupleDescriptor->natts * sizeof(bool)); if (new_rel_oid != InvalidOid) - slot[slotCount]->tts_values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_rel_oid); + HeapTupleSetValue(pg_attribute, attrelid, ObjectIdGetDatum(new_rel_oid), values); else - slot[slotCount]->tts_values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(attrs->attrelid); - - slot[slotCount]->tts_values[Anum_pg_attribute_attname - 1] = NameGetDatum(&attrs->attname); - slot[slotCount]->tts_values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(attrs->atttypid); - slot[slotCount]->tts_values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(attrs->attlen); - slot[slotCount]->tts_values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(attrs->attnum); - slot[slotCount]->tts_values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(attrs->atttypmod); - slot[slotCount]->tts_values[Anum_pg_attribute_attndims - 1] = Int16GetDatum(attrs->attndims); - slot[slotCount]->tts_values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(attrs->attbyval); - slot[slotCount]->tts_values[Anum_pg_attribute_attalign - 1] = CharGetDatum(attrs->attalign); - slot[slotCount]->tts_values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(attrs->attstorage); - slot[slotCount]->tts_values[Anum_pg_attribute_attcompression - 1] = CharGetDatum(attrs->attcompression); - slot[slotCount]->tts_values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(attrs->attnotnull); - slot[slotCount]->tts_values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(attrs->atthasdef); - slot[slotCount]->tts_values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(attrs->atthasmissing); - slot[slotCount]->tts_values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(attrs->attidentity); - slot[slotCount]->tts_values[Anum_pg_attribute_attgenerated - 1] = CharGetDatum(attrs->attgenerated); - slot[slotCount]->tts_values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(attrs->attisdropped); - slot[slotCount]->tts_values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(attrs->attislocal); - slot[slotCount]->tts_values[Anum_pg_attribute_attinhcount - 1] = Int16GetDatum(attrs->attinhcount); - slot[slotCount]->tts_values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(attrs->attcollation); + HeapTupleSetValue(pg_attribute, attrelid, ObjectIdGetDatum(attrs->attrelid), values); + + HeapTupleSetValue(pg_attribute, attname, NameGetDatum(&attrs->attname), values); + HeapTupleSetValue(pg_attribute, atttypid, ObjectIdGetDatum(attrs->atttypid), values); + HeapTupleSetValue(pg_attribute, attlen, Int16GetDatum(attrs->attlen), values); + HeapTupleSetValue(pg_attribute, attnum, Int16GetDatum(attrs->attnum), values); + HeapTupleSetValue(pg_attribute, atttypmod, Int32GetDatum(attrs->atttypmod), values); + HeapTupleSetValue(pg_attribute, attndims, Int16GetDatum(attrs->attndims), values); + HeapTupleSetValue(pg_attribute, attbyval, BoolGetDatum(attrs->attbyval), values); + HeapTupleSetValue(pg_attribute, attalign, CharGetDatum(attrs->attalign), values); + HeapTupleSetValue(pg_attribute, attstorage, CharGetDatum(attrs->attstorage), values); + HeapTupleSetValue(pg_attribute, attcompression, CharGetDatum(attrs->attcompression), values); + HeapTupleSetValue(pg_attribute, attnotnull, BoolGetDatum(attrs->attnotnull), values); + HeapTupleSetValue(pg_attribute, atthasdef, BoolGetDatum(attrs->atthasdef), values); + HeapTupleSetValue(pg_attribute, atthasmissing, BoolGetDatum(attrs->atthasmissing), values); + HeapTupleSetValue(pg_attribute, attidentity, CharGetDatum(attrs->attidentity), values); + HeapTupleSetValue(pg_attribute, attgenerated, CharGetDatum(attrs->attgenerated), values); + HeapTupleSetValue(pg_attribute, attisdropped, BoolGetDatum(attrs->attisdropped), values); + HeapTupleSetValue(pg_attribute, attislocal, BoolGetDatum(attrs->attislocal), values); + HeapTupleSetValue(pg_attribute, attinhcount, Int16GetDatum(attrs->attinhcount), values); + HeapTupleSetValue(pg_attribute, attcollation, ObjectIdGetDatum(attrs->attcollation), values); if (attrs_extra) { - slot[slotCount]->tts_values[Anum_pg_attribute_attstattarget - 1] = attrs_extra->attstattarget.value; - slot[slotCount]->tts_isnull[Anum_pg_attribute_attstattarget - 1] = attrs_extra->attstattarget.isnull; + HeapTupleSetValue(pg_attribute, attstattarget, attrs_extra->attstattarget.value, values); + if (attrs_extra->attstattarget.isnull) + HeapTupleSetValueNull(pg_attribute, attstattarget, values, slot->tts_isnull); - slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attrs_extra->attoptions.value; - slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = attrs_extra->attoptions.isnull; + HeapTupleSetValue(pg_attribute, attoptions, attrs_extra->attoptions.value, values); + if (attrs_extra->attoptions.isnull) + HeapTupleSetValueNull(pg_attribute, attoptions, values, slot->tts_isnull); } else { - slot[slotCount]->tts_isnull[Anum_pg_attribute_attstattarget - 1] = true; - slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = true; + HeapTupleSetValueNull(pg_attribute, attstattarget, values, slot->tts_isnull); + HeapTupleSetValueNull(pg_attribute, attoptions, values, slot->tts_isnull); } /* * The remaining fields are not set for new columns. */ - slot[slotCount]->tts_isnull[Anum_pg_attribute_attacl - 1] = true; - slot[slotCount]->tts_isnull[Anum_pg_attribute_attfdwoptions - 1] = true; - slot[slotCount]->tts_isnull[Anum_pg_attribute_attmissingval - 1] = true; + HeapTupleSetValueNull(pg_attribute, attacl, values, slot->tts_isnull); + HeapTupleSetValueNull(pg_attribute, attfdwoptions, values, slot->tts_isnull); + HeapTupleSetValueNull(pg_attribute, attmissingval, values, slot->tts_isnull); - ExecStoreVirtualTuple(slot[slotCount]); + ExecStoreVirtualTuple(slot); slotCount++; /* @@ -808,8 +813,7 @@ InsertPgAttributeTuples(Relation pg_attribute_rel, } /* insert the new tuples and update the indexes */ - CatalogTuplesMultiInsertWithInfo(pg_attribute_rel, slot, slotCount, - indstate); + CatalogTuplesMultiInsert(pg_attribute_rel, slots, slotCount, indstate); slotCount = 0; } @@ -819,8 +823,8 @@ InsertPgAttributeTuples(Relation pg_attribute_rel, if (close_index) CatalogCloseIndexes(indstate); for (int i = 0; i < nslots; i++) - ExecDropSingleTupleTableSlot(slot[i]); - pfree(slot); + ExecDropSingleTupleTableSlot(slots[i]); + pfree(slots); } /* -------------------------------- @@ -914,61 +918,58 @@ InsertPgClassTuple(Relation pg_class_desc, Datum reloptions) { Form_pg_class rd_rel = new_rel_desc->rd_rel; - Datum values[Natts_pg_class]; - bool nulls[Natts_pg_class]; + Datum values[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; HeapTuple tup; /* This is a tad tedious, but way cleaner than what we used to do... */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - - values[Anum_pg_class_oid - 1] = ObjectIdGetDatum(new_rel_oid); - values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname); - values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace); - values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype); - values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype); - values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner); - values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam); - values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode); - values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace); - values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages); - values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples); - values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible); - values[Anum_pg_class_relallfrozen - 1] = Int32GetDatum(rd_rel->relallfrozen); - values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid); - values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex); - values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared); - values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence); - values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind); - values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts); - values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks); - values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules); - values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers); - values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity); - values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity); - values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass); - values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated); - values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident); - values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition); - values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite); - values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid); - values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid); + HeapTupleSetValue(pg_class, oid, ObjectIdGetDatum(new_rel_oid), values); + HeapTupleSetValue(pg_class, relname, NameGetDatum(&rd_rel->relname), values); + HeapTupleSetValue(pg_class, relnamespace, ObjectIdGetDatum(rd_rel->relnamespace), values); + HeapTupleSetValue(pg_class, reltype, ObjectIdGetDatum(rd_rel->reltype), values); + HeapTupleSetValue(pg_class, reloftype, ObjectIdGetDatum(rd_rel->reloftype), values); + HeapTupleSetValue(pg_class, relowner, ObjectIdGetDatum(rd_rel->relowner), values); + HeapTupleSetValue(pg_class, relam, ObjectIdGetDatum(rd_rel->relam), values); + HeapTupleSetValue(pg_class, relfilenode, ObjectIdGetDatum(rd_rel->relfilenode), values); + HeapTupleSetValue(pg_class, reltablespace, ObjectIdGetDatum(rd_rel->reltablespace), values); + HeapTupleSetValue(pg_class, relpages, Int32GetDatum(rd_rel->relpages), values); + HeapTupleSetValue(pg_class, reltuples, Float4GetDatum(rd_rel->reltuples), values); + HeapTupleSetValue(pg_class, relallvisible, Int32GetDatum(rd_rel->relallvisible), values); + HeapTupleSetValue(pg_class, relallfrozen, Int32GetDatum(rd_rel->relallfrozen), values); + HeapTupleSetValue(pg_class, reltoastrelid, ObjectIdGetDatum(rd_rel->reltoastrelid), values); + HeapTupleSetValue(pg_class, relhasindex, BoolGetDatum(rd_rel->relhasindex), values); + HeapTupleSetValue(pg_class, relisshared, BoolGetDatum(rd_rel->relisshared), values); + HeapTupleSetValue(pg_class, relpersistence, CharGetDatum(rd_rel->relpersistence), values); + HeapTupleSetValue(pg_class, relkind, CharGetDatum(rd_rel->relkind), values); + HeapTupleSetValue(pg_class, relnatts, Int16GetDatum(rd_rel->relnatts), values); + HeapTupleSetValue(pg_class, relchecks, Int16GetDatum(rd_rel->relchecks), values); + HeapTupleSetValue(pg_class, relhasrules, BoolGetDatum(rd_rel->relhasrules), values); + HeapTupleSetValue(pg_class, relhastriggers, BoolGetDatum(rd_rel->relhastriggers), values); + HeapTupleSetValue(pg_class, relrowsecurity, BoolGetDatum(rd_rel->relrowsecurity), values); + HeapTupleSetValue(pg_class, relforcerowsecurity, BoolGetDatum(rd_rel->relforcerowsecurity), values); + HeapTupleSetValue(pg_class, relhassubclass, BoolGetDatum(rd_rel->relhassubclass), values); + HeapTupleSetValue(pg_class, relispopulated, BoolGetDatum(rd_rel->relispopulated), values); + HeapTupleSetValue(pg_class, relreplident, CharGetDatum(rd_rel->relreplident), values); + HeapTupleSetValue(pg_class, relispartition, BoolGetDatum(rd_rel->relispartition), values); + HeapTupleSetValue(pg_class, relrewrite, ObjectIdGetDatum(rd_rel->relrewrite), values); + HeapTupleSetValue(pg_class, relfrozenxid, TransactionIdGetDatum(rd_rel->relfrozenxid), values); + HeapTupleSetValue(pg_class, relminmxid, MultiXactIdGetDatum(rd_rel->relminmxid), values); if (relacl != (Datum) 0) - values[Anum_pg_class_relacl - 1] = relacl; + HeapTupleSetValue(pg_class, relacl, relacl, values); else - nulls[Anum_pg_class_relacl - 1] = true; + HeapTupleSetValueNull(pg_class, relacl, values, nulls); if (reloptions != (Datum) 0) - values[Anum_pg_class_reloptions - 1] = reloptions; + HeapTupleSetValue(pg_class, reloptions, reloptions, values); else - nulls[Anum_pg_class_reloptions - 1] = true; + HeapTupleSetValueNull(pg_class, reloptions, values, nulls); /* relpartbound is set by updating this tuple, if necessary */ - nulls[Anum_pg_class_relpartbound - 1] = true; + HeapTupleSetValueNull(pg_class, relpartbound, values, nulls); tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls); /* finally insert the new tuple, update the indexes, and clean up */ - CatalogTupleInsert(pg_class_desc, tup); + CatalogTupleInsert(pg_class_desc, tup, NULL); heap_freetuple(tup); } @@ -1687,9 +1688,8 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) HeapTuple tuple; Form_pg_attribute attStruct; char newattname[NAMEDATALEN]; - Datum valuesAtt[Natts_pg_attribute] = {0}; - bool nullsAtt[Natts_pg_attribute] = {0}; - bool replacesAtt[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; /* * Grab an exclusive lock on the target table, which we will NOT release @@ -1710,7 +1710,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) attStruct = (Form_pg_attribute) GETSTRUCT(tuple); /* Mark the attribute as dropped */ - attStruct->attisdropped = true; + HeapTupleUpdateField(pg_attribute, attisdropped, true, attStruct, updated); /* * Set the type OID to invalid. A dropped attribute's type link cannot be @@ -1720,13 +1720,13 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) * the attribute's attlen and attalign. We set atttypid to zero here as a * means of catching code that incorrectly expects it to be valid. */ - attStruct->atttypid = InvalidOid; + HeapTupleUpdateField(pg_attribute, atttypid, InvalidOid, attStruct, updated); /* Remove any not-null constraint the column may have */ - attStruct->attnotnull = false; + HeapTupleUpdateField(pg_attribute, attnotnull, false, attStruct, updated); /* Unset this so no one tries to look up the generation expression */ - attStruct->attgenerated = '\0'; + HeapTupleUpdateField(pg_attribute, attgenerated, '\0', attStruct, updated); /* * Change the column name to something that isn't likely to conflict @@ -1734,29 +1734,33 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) snprintf(newattname, sizeof(newattname), "........pg.dropped.%d........", attnum); namestrcpy(&(attStruct->attname), newattname); + HeapTupleMarkColumnUpdated(pg_attribute, attname, updated); /* Clear the missing value */ - attStruct->atthasmissing = false; - nullsAtt[Anum_pg_attribute_attmissingval - 1] = true; - replacesAtt[Anum_pg_attribute_attmissingval - 1] = true; + HeapTupleUpdateField(pg_attribute, atthasmissing, false, attStruct, updated); + HeapTupleSetFieldNull(pg_attribute, attmissingval, nulls); + HeapTupleMarkColumnUpdated(pg_attribute, attmissingval, updated); /* * Clear the other nullable fields. This saves some space in pg_attribute * and removes no longer useful information. */ - nullsAtt[Anum_pg_attribute_attstattarget - 1] = true; - replacesAtt[Anum_pg_attribute_attstattarget - 1] = true; - nullsAtt[Anum_pg_attribute_attacl - 1] = true; - replacesAtt[Anum_pg_attribute_attacl - 1] = true; - nullsAtt[Anum_pg_attribute_attoptions - 1] = true; - replacesAtt[Anum_pg_attribute_attoptions - 1] = true; - nullsAtt[Anum_pg_attribute_attfdwoptions - 1] = true; - replacesAtt[Anum_pg_attribute_attfdwoptions - 1] = true; + HeapTupleSetFieldNull(pg_attribute, attstattarget, nulls); + HeapTupleMarkColumnUpdated(pg_attribute, attstattarget, updated); - tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel), - valuesAtt, nullsAtt, replacesAtt); + HeapTupleSetFieldNull(pg_attribute, attacl, nulls); + HeapTupleMarkColumnUpdated(pg_attribute, attacl, updated); - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + HeapTupleSetFieldNull(pg_attribute, attoptions, nulls); + HeapTupleMarkColumnUpdated(pg_attribute, attoptions, updated); + + HeapTupleSetFieldNull(pg_attribute, attfdwoptions, nulls); + HeapTupleMarkColumnUpdated(pg_attribute, attfdwoptions, updated); + + tuple = heap_update_tuple(tuple, RelationGetDescr(attr_rel), + NULL, nulls, updated); + + CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple, updated, NULL); /* * Because updating the pg_attribute row will trigger a relcache flush for @@ -1765,10 +1769,9 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) */ table_close(attr_rel, RowExclusiveLock); - RemoveStatistics(relid, attnum); - relation_close(rel, NoLock); + bms_free(updated); } /* @@ -1967,23 +1970,15 @@ RelationClearMissing(Relation rel) Oid relid = RelationGetRelid(rel); int natts = RelationGetNumberOfAttributes(rel); int attnum; - Datum repl_val[Natts_pg_attribute]; - bool repl_null[Natts_pg_attribute]; - bool repl_repl[Natts_pg_attribute]; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; Form_pg_attribute attrtuple; HeapTuple tuple, newtuple; - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false); - repl_null[Anum_pg_attribute_attmissingval - 1] = true; - - repl_repl[Anum_pg_attribute_atthasmissing - 1] = true; - repl_repl[Anum_pg_attribute_attmissingval - 1] = true; - + HeapTupleUpdateValue(pg_attribute, atthasmissing, BoolGetDatum(false), values, nulls, updated); + HeapTupleUpdateValueNull(pg_attribute, attmissingval, values, nulls, updated); /* Get a lock on pg_attribute */ attr_rel = table_open(AttributeRelationId, RowExclusiveLock); @@ -2003,10 +1998,10 @@ RelationClearMissing(Relation rel) /* ignore any where atthasmissing is not true */ if (attrtuple->atthasmissing) { - newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel), - repl_val, repl_null, repl_repl); + newtuple = heap_update_tuple(tuple, RelationGetDescr(attr_rel), + values, nulls, updated); - CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple, updated, NULL); heap_freetuple(newtuple); } @@ -2019,6 +2014,7 @@ RelationClearMissing(Relation rel) * there's nothing else to do here. */ table_close(attr_rel, RowExclusiveLock); + bms_free(updated); } /* @@ -2029,9 +2025,9 @@ RelationClearMissing(Relation rel) void StoreAttrMissingVal(Relation rel, AttrNumber attnum, Datum missingval) { - Datum valuesAtt[Natts_pg_attribute] = {0}; - bool nullsAtt[Natts_pg_attribute] = {0}; - bool replacesAtt[Natts_pg_attribute] = {0}; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; Relation attrrel; Form_pg_attribute attStruct; HeapTuple atttup, @@ -2060,17 +2056,15 @@ StoreAttrMissingVal(Relation rel, AttrNumber attnum, Datum missingval) attStruct->attalign)); /* Update the pg_attribute row */ - 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; + HeapTupleUpdateValue(pg_attribute, atthasmissing, BoolGetDatum(true), values, nulls, updated); + HeapTupleUpdateValue(pg_attribute, attmissingval, missingval, values, nulls, updated); - newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel), - valuesAtt, nullsAtt, replacesAtt); - CatalogTupleUpdate(attrrel, &newtup->t_self, newtup); + newtup = heap_update_tuple(atttup, RelationGetDescr(attrrel), + values, nulls, updated); + CatalogTupleUpdate(attrrel, &newtup->t_self, newtup, updated, NULL); /* clean up */ + bms_free(updated); ReleaseSysCache(atttup); table_close(attrrel, RowExclusiveLock); } @@ -2085,9 +2079,9 @@ StoreAttrMissingVal(Relation rel, AttrNumber attnum, Datum missingval) void SetAttrMissing(Oid relid, char *attname, char *value) { - Datum valuesAtt[Natts_pg_attribute] = {0}; - bool nullsAtt[Natts_pg_attribute] = {0}; - bool replacesAtt[Natts_pg_attribute] = {0}; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; Datum missingval; Form_pg_attribute attStruct; Relation attrrel, @@ -2120,16 +2114,15 @@ SetAttrMissing(Oid relid, char *attname, char *value) Int32GetDatum(attStruct->atttypmod)); /* update the tuple - set atthasmissing and attmissingval */ - 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; + HeapTupleUpdateValue(pg_attribute, atthasmissing, BoolGetDatum(true), values, nulls, updated); + HeapTupleUpdateValue(pg_attribute, attmissingval, missingval, values, nulls, updated); - newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel), - valuesAtt, nullsAtt, replacesAtt); - CatalogTupleUpdate(attrrel, &newtup->t_self, newtup); + newtup = heap_update_tuple(atttup, RelationGetDescr(attrrel), + values, nulls, updated); + CatalogTupleUpdate(attrrel, &newtup->t_self, newtup, updated, NULL); /* clean up */ + bms_free(updated); ReleaseSysCache(atttup); table_close(attrrel, RowExclusiveLock); table_close(tablerel, AccessExclusiveLock); @@ -2719,6 +2712,7 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, SysScanDesc conscan; ScanKeyData skey[3]; HeapTuple tup; + Bitmapset *updated = NULL; /* Search for a pg_constraint entry with same name and relation */ conDesc = table_open(ConstraintRelationId, RowExclusiveLock); @@ -2834,24 +2828,25 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, */ if (rel->rd_rel->relispartition) { - con->coninhcount = 1; - con->conislocal = false; + HeapTupleUpdateField(pg_constraint, coninhcount, 1, con, updated); + HeapTupleUpdateField(pg_constraint, conislocal, false, con, updated); } else { if (is_local) - con->conislocal = true; + HeapTupleUpdateField(pg_constraint, conislocal, true, con, updated); else if (pg_add_s16_overflow(con->coninhcount, 1, &con->coninhcount)) ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); + HeapTupleUpdateField(pg_constraint, coninhcount, con->coninhcount, con, updated); } if (is_no_inherit) { Assert(is_local); - con->connoinherit = true; + HeapTupleUpdateField(pg_constraint, connoinherit, true, con, updated); } /* @@ -2863,11 +2858,12 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, if (is_enforced && !con->conenforced) { Assert(is_local); - con->conenforced = true; - con->convalidated = true; + HeapTupleUpdateField(pg_constraint, conenforced, true, con, updated); + HeapTupleUpdateField(pg_constraint, convalidated, true, con, updated); } - CatalogTupleUpdate(conDesc, &tup->t_self, tup); + CatalogTupleUpdate(conDesc, &tup->t_self, tup, updated, NULL); + bms_free(updated); } systable_endscan(conscan); @@ -3148,6 +3144,7 @@ SetRelationNumChecks(Relation rel, int numchecks) Relation relrel; HeapTuple reltup; Form_pg_class relStruct; + Bitmapset *updated = NULL; relrel = table_open(RelationRelationId, RowExclusiveLock); reltup = SearchSysCacheCopy1(RELOID, @@ -3159,9 +3156,10 @@ SetRelationNumChecks(Relation rel, int numchecks) if (relStruct->relchecks != numchecks) { - relStruct->relchecks = numchecks; + HeapTupleUpdateField(pg_class, relchecks, numchecks, relStruct, updated); - CatalogTupleUpdate(relrel, &reltup->t_self, reltup); + CatalogTupleUpdate(relrel, &reltup->t_self, reltup, updated, NULL); + bms_free(updated); } else { @@ -3470,7 +3468,7 @@ CopyStatistics(Oid fromrelid, Oid torelid) if (indstate == NULL) indstate = CatalogOpenIndexes(statrel); - CatalogTupleInsertWithInfo(statrel, tup, indstate); + CatalogTupleInsert(statrel, tup, indstate); heap_freetuple(tup); } @@ -3906,8 +3904,8 @@ StorePartitionKey(Relation rel, Datum partexprDatum; Relation pg_partitioned_table; HeapTuple tuple; - Datum values[Natts_pg_partitioned_table]; - bool nulls[Natts_pg_partitioned_table] = {0}; + Datum values[Natts_pg_partitioned_table] = {0}; + bool nulls[Natts_pg_partitioned_table] = {false}; ObjectAddress myself; ObjectAddress referenced; ObjectAddresses *addrs; @@ -3935,20 +3933,20 @@ StorePartitionKey(Relation rel, /* Only this can ever be NULL */ if (!partexprDatum) - nulls[Anum_pg_partitioned_table_partexprs - 1] = true; + HeapTupleSetValueNull(pg_partitioned_table, partexprs, values, nulls); - values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel)); - values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy); - values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts); - values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec); - values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec); - values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec); - values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum; + HeapTupleSetValue(pg_partitioned_table, partrelid, ObjectIdGetDatum(RelationGetRelid(rel)), values); + HeapTupleSetValue(pg_partitioned_table, partstrat, CharGetDatum(strategy), values); + HeapTupleSetValue(pg_partitioned_table, partnatts, Int16GetDatum(partnatts), values); + HeapTupleSetValue(pg_partitioned_table, partdefid, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_partitioned_table, partattrs, PointerGetDatum(partattrs_vec), values); + HeapTupleSetValue(pg_partitioned_table, partclass, PointerGetDatum(partopclass_vec), values); + HeapTupleSetValue(pg_partitioned_table, partcollation, PointerGetDatum(partcollation_vec), values); + HeapTupleSetValue(pg_partitioned_table, partexprs, partexprDatum, values); tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls); - CatalogTupleInsert(pg_partitioned_table, tuple); + CatalogTupleInsert(pg_partitioned_table, tuple, NULL); table_close(pg_partitioned_table, RowExclusiveLock); /* Mark this relation as dependent on a few things as follows */ @@ -4052,9 +4050,9 @@ StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound) Relation classRel; HeapTuple tuple, newtuple; - Datum new_val[Natts_pg_class]; - bool new_null[Natts_pg_class], - new_repl[Natts_pg_class]; + Datum values[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; + Bitmapset *updated = NULL; Oid defaultPartOid; /* Update pg_class tuple */ @@ -4065,12 +4063,14 @@ StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound) elog(ERROR, "cache lookup failed for relation %u", RelationGetRelid(rel)); + #ifdef USE_ASSERT_CHECKING { Form_pg_class classForm; bool isnull; classForm = (Form_pg_class) GETSTRUCT(tuple); + Assert(!classForm->relispartition); (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound, &isnull); @@ -4079,26 +4079,23 @@ StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound) #endif /* Fill in relpartbound value */ - memset(new_val, 0, sizeof(new_val)); - memset(new_null, false, sizeof(new_null)); - memset(new_repl, false, sizeof(new_repl)); - new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound)); - new_null[Anum_pg_class_relpartbound - 1] = false; - new_repl[Anum_pg_class_relpartbound - 1] = true; - newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel), - new_val, new_null, new_repl); + HeapTupleUpdateValue(pg_class, relpartbound, CStringGetTextDatum(nodeToString(bound)), values, nulls, updated); + newtuple = heap_update_tuple(tuple, RelationGetDescr(classRel), + values, nulls, updated); + /* Also set the flag */ - ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true; + HeapTupleUpdateField(pg_class, relispartition, true, (Form_pg_class) GETSTRUCT(newtuple), updated); /* * We already checked for no inheritance children, but reset * relhassubclass in case it was left over. */ if (rel->rd_rel->relkind == RELKIND_RELATION && rel->rd_rel->relhassubclass) - ((Form_pg_class) GETSTRUCT(newtuple))->relhassubclass = false; + HeapTupleUpdateField(pg_class, relhassubclass, false, (Form_pg_class) GETSTRUCT(newtuple), updated); - CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple, updated, NULL); heap_freetuple(newtuple); + bms_free(updated); table_close(classRel, RowExclusiveLock); /* diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 5d9db167e59..31e78342d63 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -579,8 +579,8 @@ UpdateIndexRelation(Oid indexoid, int2vector *indoption; Datum exprsDatum; Datum predDatum; - Datum values[Natts_pg_index]; - bool nulls[Natts_pg_index] = {0}; + Datum values[Natts_pg_index] = {0}; + bool nulls[Natts_pg_index] = {false}; Relation pg_index; HeapTuple tuple; int i; @@ -634,38 +634,38 @@ UpdateIndexRelation(Oid indexoid, /* * Build a pg_index tuple */ - values[Anum_pg_index_indexrelid - 1] = ObjectIdGetDatum(indexoid); - values[Anum_pg_index_indrelid - 1] = ObjectIdGetDatum(heapoid); - values[Anum_pg_index_indnatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexAttrs); - values[Anum_pg_index_indnkeyatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexKeyAttrs); - values[Anum_pg_index_indisunique - 1] = BoolGetDatum(indexInfo->ii_Unique); - values[Anum_pg_index_indnullsnotdistinct - 1] = BoolGetDatum(indexInfo->ii_NullsNotDistinct); - values[Anum_pg_index_indisprimary - 1] = BoolGetDatum(primary); - values[Anum_pg_index_indisexclusion - 1] = BoolGetDatum(isexclusion); - values[Anum_pg_index_indimmediate - 1] = BoolGetDatum(immediate); - values[Anum_pg_index_indisclustered - 1] = BoolGetDatum(false); - values[Anum_pg_index_indisvalid - 1] = BoolGetDatum(isvalid); - values[Anum_pg_index_indcheckxmin - 1] = BoolGetDatum(false); - values[Anum_pg_index_indisready - 1] = BoolGetDatum(isready); - values[Anum_pg_index_indislive - 1] = BoolGetDatum(true); - values[Anum_pg_index_indisreplident - 1] = BoolGetDatum(false); - values[Anum_pg_index_indkey - 1] = PointerGetDatum(indkey); - values[Anum_pg_index_indcollation - 1] = PointerGetDatum(indcollation); - values[Anum_pg_index_indclass - 1] = PointerGetDatum(indclass); - values[Anum_pg_index_indoption - 1] = PointerGetDatum(indoption); - values[Anum_pg_index_indexprs - 1] = exprsDatum; + HeapTupleSetValue(pg_index, indexrelid, ObjectIdGetDatum(indexoid), values); + HeapTupleSetValue(pg_index, indrelid, ObjectIdGetDatum(heapoid), values); + HeapTupleSetValue(pg_index, indnatts, Int16GetDatum(indexInfo->ii_NumIndexAttrs), values); + HeapTupleSetValue(pg_index, indnkeyatts, Int16GetDatum(indexInfo->ii_NumIndexKeyAttrs), values); + HeapTupleSetValue(pg_index, indisunique, BoolGetDatum(indexInfo->ii_Unique), values); + HeapTupleSetValue(pg_index, indnullsnotdistinct, BoolGetDatum(indexInfo->ii_NullsNotDistinct), values); + HeapTupleSetValue(pg_index, indisprimary, BoolGetDatum(primary), values); + HeapTupleSetValue(pg_index, indisexclusion, BoolGetDatum(isexclusion), values); + HeapTupleSetValue(pg_index, indimmediate, BoolGetDatum(immediate), values); + HeapTupleSetValue(pg_index, indisclustered, BoolGetDatum(false), values); + HeapTupleSetValue(pg_index, indisvalid, BoolGetDatum(isvalid), values); + HeapTupleSetValue(pg_index, indcheckxmin, BoolGetDatum(false), values); + HeapTupleSetValue(pg_index, indisready, BoolGetDatum(isready), values); + HeapTupleSetValue(pg_index, indislive, BoolGetDatum(true), values); + HeapTupleSetValue(pg_index, indisreplident, BoolGetDatum(false), values); + HeapTupleSetValue(pg_index, indkey, PointerGetDatum(indkey), values); + HeapTupleSetValue(pg_index, indcollation, PointerGetDatum(indcollation), values); + HeapTupleSetValue(pg_index, indclass, PointerGetDatum(indclass), values); + HeapTupleSetValue(pg_index, indoption, PointerGetDatum(indoption), values); + HeapTupleSetValue(pg_index, indexprs, exprsDatum, values); if (exprsDatum == (Datum) 0) - nulls[Anum_pg_index_indexprs - 1] = true; - values[Anum_pg_index_indpred - 1] = predDatum; + HeapTupleSetValueNull(pg_index, indexprs, values, nulls); + HeapTupleSetValue(pg_index, indpred, predDatum, values); if (predDatum == (Datum) 0) - nulls[Anum_pg_index_indpred - 1] = true; + HeapTupleSetValueNull(pg_index, indpred, values, nulls); tuple = heap_form_tuple(RelationGetDescr(pg_index), values, nulls); /* * insert the tuple into the pg_index catalog */ - CatalogTupleInsert(pg_index, tuple); + CatalogTupleInsert(pg_index, tuple, NULL); /* * close the relation and free the tuple @@ -1569,6 +1569,8 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) Oid indexConstraintOid; List *constraintOids = NIL; ListCell *lc; + Bitmapset *oldUpdated = NULL; + Bitmapset *newUpdated = NULL; /* * Take a necessary lock on the old and new index before swapping them. @@ -1594,14 +1596,21 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) /* Swap the names */ namestrcpy(&newClassForm->relname, NameStr(oldClassForm->relname)); namestrcpy(&oldClassForm->relname, oldName); + HeapTupleUpdateField(pg_class, relname, newClassForm->relname, newClassForm, newUpdated); + HeapTupleUpdateField(pg_class, relname, oldClassForm->relname, oldClassForm, oldUpdated); /* Swap the partition flags to track inheritance properly */ isPartition = newClassForm->relispartition; - newClassForm->relispartition = oldClassForm->relispartition; - oldClassForm->relispartition = isPartition; + HeapTupleUpdateField(pg_class, relispartition, oldClassForm->relispartition, newClassForm, newUpdated); + HeapTupleUpdateField(pg_class, relispartition, isPartition, oldClassForm, oldUpdated); - CatalogTupleUpdate(pg_class, &oldClassTuple->t_self, oldClassTuple); - CatalogTupleUpdate(pg_class, &newClassTuple->t_self, newClassTuple); + CatalogTupleUpdate(pg_class, &oldClassTuple->t_self, oldClassTuple, oldUpdated, NULL); + CatalogTupleUpdate(pg_class, &newClassTuple->t_self, newClassTuple, newUpdated, NULL); + + bms_free(oldUpdated); + oldUpdated = NULL; + bms_free(newUpdated); + newUpdated = NULL; heap_freetuple(oldClassTuple); heap_freetuple(newClassTuple); @@ -1625,34 +1634,39 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) * Copy constraint flags from the old index. This is safe because the old * index guaranteed uniqueness. */ - newIndexForm->indisprimary = oldIndexForm->indisprimary; - oldIndexForm->indisprimary = false; - newIndexForm->indisexclusion = oldIndexForm->indisexclusion; - oldIndexForm->indisexclusion = false; - newIndexForm->indimmediate = oldIndexForm->indimmediate; - oldIndexForm->indimmediate = true; + HeapTupleUpdateField(pg_index, indisprimary, oldIndexForm->indisprimary, newIndexForm, newUpdated); + HeapTupleUpdateField(pg_index, indisprimary, false, oldIndexForm, oldUpdated); + HeapTupleUpdateField(pg_index, indisexclusion, oldIndexForm->indisexclusion, newIndexForm, newUpdated); + HeapTupleUpdateField(pg_index, indisexclusion, false, oldIndexForm, oldUpdated); + HeapTupleUpdateField(pg_index, indimmediate, oldIndexForm->indimmediate, newIndexForm, newUpdated); + HeapTupleUpdateField(pg_index, indimmediate, true, oldIndexForm, oldUpdated); /* Preserve indisreplident in the new index */ - newIndexForm->indisreplident = oldIndexForm->indisreplident; + HeapTupleUpdateField(pg_index, indisreplident, oldIndexForm->indisreplident, newIndexForm, newUpdated); /* Preserve indisclustered in the new index */ - newIndexForm->indisclustered = oldIndexForm->indisclustered; + HeapTupleUpdateField(pg_index, indisclustered, oldIndexForm->indisclustered, newIndexForm, newUpdated); /* * Mark the new index as valid, and the old index as invalid similarly to * what index_set_state_flags() does. */ - newIndexForm->indisvalid = true; - oldIndexForm->indisvalid = false; - oldIndexForm->indisclustered = false; - oldIndexForm->indisreplident = false; + HeapTupleUpdateField(pg_index, indisvalid, true, newIndexForm, newUpdated); + HeapTupleUpdateField(pg_index, indisvalid, false, oldIndexForm, oldUpdated); + HeapTupleUpdateField(pg_index, indisclustered, false, oldIndexForm, oldUpdated); + HeapTupleUpdateField(pg_index, indisreplident, false, oldIndexForm, oldUpdated); - CatalogTupleUpdate(pg_index, &oldIndexTuple->t_self, oldIndexTuple); - CatalogTupleUpdate(pg_index, &newIndexTuple->t_self, newIndexTuple); + CatalogTupleUpdate(pg_index, &oldIndexTuple->t_self, oldIndexTuple, oldUpdated, NULL); + CatalogTupleUpdate(pg_index, &newIndexTuple->t_self, newIndexTuple, newUpdated, NULL); heap_freetuple(oldIndexTuple); heap_freetuple(newIndexTuple); + bms_free(oldUpdated); + oldUpdated = NULL; + bms_free(newUpdated); + newUpdated = NULL; + /* * Move constraints and triggers over to the new index */ @@ -1686,9 +1700,11 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) if (conForm->conindid == oldIndexId) { - conForm->conindid = newIndexId; + Bitmapset *updated = NULL; - CatalogTupleUpdate(pg_constraint, &constraintTuple->t_self, constraintTuple); + HeapTupleUpdateField(pg_constraint, conindid, newIndexId, conForm, updated); + CatalogTupleUpdate(pg_constraint, &constraintTuple->t_self, constraintTuple, updated, NULL); + bms_free(updated); } heap_freetuple(constraintTuple); @@ -1704,6 +1720,8 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) while (HeapTupleIsValid((triggerTuple = systable_getnext(scan)))) { + Bitmapset *updated = NULL; + Form_pg_trigger tgForm = (Form_pg_trigger) GETSTRUCT(triggerTuple); if (tgForm->tgconstrindid != oldIndexId) @@ -1713,10 +1731,9 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) triggerTuple = heap_copytuple(triggerTuple); tgForm = (Form_pg_trigger) GETSTRUCT(triggerTuple); - tgForm->tgconstrindid = newIndexId; - - CatalogTupleUpdate(pg_trigger, &triggerTuple->t_self, triggerTuple); - + HeapTupleUpdateField(pg_trigger, tgconstrindid, newIndexId, tgForm, updated); + CatalogTupleUpdate(pg_trigger, &triggerTuple->t_self, triggerTuple, updated, NULL); + bms_free(updated); heap_freetuple(triggerTuple); } @@ -1732,11 +1749,10 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) SysScanDesc sd; HeapTuple tuple; Datum values[Natts_pg_description] = {0}; - bool nulls[Natts_pg_description] = {0}; - bool replaces[Natts_pg_description] = {0}; + bool nulls[Natts_pg_description] = {false}; + Bitmapset *updated = NULL; - values[Anum_pg_description_objoid - 1] = ObjectIdGetDatum(newIndexId); - replaces[Anum_pg_description_objoid - 1] = true; + HeapTupleUpdateValue(pg_description, objoid, ObjectIdGetDatum(newIndexId), values, nulls, updated); ScanKeyInit(&skey[0], Anum_pg_description_objoid, @@ -1758,15 +1774,16 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) while ((tuple = systable_getnext(sd)) != NULL) { - tuple = heap_modify_tuple(tuple, RelationGetDescr(description), - values, nulls, replaces); - CatalogTupleUpdate(description, &tuple->t_self, tuple); + tuple = heap_update_tuple(tuple, RelationGetDescr(description), + values, nulls, updated); + CatalogTupleUpdate(description, &tuple->t_self, tuple, updated, NULL); break; /* Assume there can be only one match */ } systable_endscan(sd); table_close(description, NoLock); + bms_free(updated); } /* @@ -2061,6 +2078,7 @@ index_constraint_create(Relation heapRelation, Form_pg_index indexForm; bool dirty = false; bool marked_as_primary = false; + Bitmapset *updated = NULL; pg_index = table_open(IndexRelationId, RowExclusiveLock); @@ -2072,20 +2090,20 @@ index_constraint_create(Relation heapRelation, if (mark_as_primary && !indexForm->indisprimary) { - indexForm->indisprimary = true; + HeapTupleUpdateField(pg_index, indisprimary, true, indexForm, updated); dirty = true; marked_as_primary = true; } if (deferrable && indexForm->indimmediate) { - indexForm->indimmediate = false; + HeapTupleUpdateField(pg_index, indimmediate, false, indexForm, updated); dirty = true; } if (dirty) { - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); /* * When we mark an existing index as primary, force a relcache @@ -2102,6 +2120,7 @@ index_constraint_create(Relation heapRelation, heap_freetuple(indexTuple); table_close(pg_index, RowExclusiveLock); + bms_free(updated); } return myself; @@ -3130,6 +3149,7 @@ index_build(Relation heapRelation, Relation pg_index; HeapTuple indexTuple; Form_pg_index indexForm; + Bitmapset *updated = NULL; pg_index = table_open(IndexRelationId, RowExclusiveLock); @@ -3142,11 +3162,12 @@ index_build(Relation heapRelation, /* If it's a new index, indcheckxmin shouldn't be set ... */ Assert(!indexForm->indcheckxmin); - indexForm->indcheckxmin = true; - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + HeapTupleUpdateField(pg_index, indcheckxmin, true, indexForm, updated); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); heap_freetuple(indexTuple); table_close(pg_index, RowExclusiveLock); + bms_free(updated); } /* @@ -3505,6 +3526,7 @@ index_set_state_flags(Oid indexId, IndexStateFlagsAction action) Relation pg_index; HeapTuple indexTuple; Form_pg_index indexForm; + Bitmapset *updated = NULL; /* Open pg_index and fetch a writable copy of the index's tuple */ pg_index = table_open(IndexRelationId, RowExclusiveLock); @@ -3523,14 +3545,14 @@ index_set_state_flags(Oid indexId, IndexStateFlagsAction action) Assert(indexForm->indislive); Assert(!indexForm->indisready); Assert(!indexForm->indisvalid); - indexForm->indisready = true; + HeapTupleUpdateField(pg_index, indisready, true, indexForm, updated); break; case INDEX_CREATE_SET_VALID: /* Set indisvalid during a CREATE INDEX CONCURRENTLY sequence */ Assert(indexForm->indislive); Assert(indexForm->indisready); Assert(!indexForm->indisvalid); - indexForm->indisvalid = true; + HeapTupleUpdateField(pg_index, indisvalid, true, indexForm, updated); break; case INDEX_DROP_CLEAR_VALID: @@ -3547,9 +3569,9 @@ index_set_state_flags(Oid indexId, IndexStateFlagsAction action) * set on any invalid index, so clear that flag too. For * cleanliness, also clear indisreplident. */ - indexForm->indisvalid = false; - indexForm->indisclustered = false; - indexForm->indisreplident = false; + HeapTupleUpdateField(pg_index, indisvalid, false, indexForm, updated); + HeapTupleUpdateField(pg_index, indisclustered, false, indexForm, updated); + HeapTupleUpdateField(pg_index, indisreplident, false, indexForm, updated); break; case INDEX_DROP_SET_DEAD: @@ -3563,15 +3585,16 @@ index_set_state_flags(Oid indexId, IndexStateFlagsAction action) Assert(!indexForm->indisvalid); Assert(!indexForm->indisclustered); Assert(!indexForm->indisreplident); - indexForm->indisready = false; - indexForm->indislive = false; + HeapTupleUpdateField(pg_index, indisready, false, indexForm, updated); + HeapTupleUpdateField(pg_index, indislive, false, indexForm, updated); break; } /* ... and update it */ - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); table_close(pg_index, RowExclusiveLock); + bms_free(updated); } @@ -3850,6 +3873,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, HeapTuple indexTuple; Form_pg_index indexForm; bool index_bad; + Bitmapset *updated = NULL; pg_index = table_open(IndexRelationId, RowExclusiveLock); @@ -3866,13 +3890,13 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, (indexForm->indcheckxmin && !indexInfo->ii_BrokenHotChain)) { if (!indexInfo->ii_BrokenHotChain) - indexForm->indcheckxmin = false; + HeapTupleUpdateField(pg_index, indcheckxmin, false, indexForm, updated); else if (index_bad) - indexForm->indcheckxmin = true; - indexForm->indisvalid = true; - indexForm->indisready = true; - indexForm->indislive = true; - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + HeapTupleUpdateField(pg_index, indcheckxmin, true, indexForm, updated); + HeapTupleUpdateField(pg_index, indisvalid, true, indexForm, updated); + HeapTupleUpdateField(pg_index, indisready, true, indexForm, updated); + HeapTupleUpdateField(pg_index, indislive, true, indexForm, updated); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); /* * Invalidate the relcache for the table, so that after we commit @@ -3885,6 +3909,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, } table_close(pg_index, RowExclusiveLock); + bms_free(updated); } /* Log what we did */ diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 93d72157a46..bc252da565c 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -342,6 +342,7 @@ update_default_partition_oid(Oid parentId, Oid defaultPartId) HeapTuple tuple; Relation pg_partitioned_table; Form_pg_partitioned_table part_table_form; + Bitmapset *updated = NULL; pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock); @@ -353,10 +354,12 @@ update_default_partition_oid(Oid parentId, Oid defaultPartId) part_table_form = (Form_pg_partitioned_table) GETSTRUCT(tuple); part_table_form->partdefid = defaultPartId; - CatalogTupleUpdate(pg_partitioned_table, &tuple->t_self, tuple); + HeapTupleMarkColumnUpdated(pg_partitioned_table, partdefid, updated); + CatalogTupleUpdate(pg_partitioned_table, &tuple->t_self, tuple, updated, NULL); heap_freetuple(tuple); table_close(pg_partitioned_table, RowExclusiveLock); + bms_free(updated); } /* diff --git a/src/backend/catalog/pg_attrdef.c b/src/backend/catalog/pg_attrdef.c index 29f5691bee9..04edc23024e 100644 --- a/src/backend/catalog/pg_attrdef.c +++ b/src/backend/catalog/pg_attrdef.c @@ -39,14 +39,12 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin; Relation adrel; HeapTuple tuple; - Datum values[Natts_pg_attrdef]; - static bool nulls[Natts_pg_attrdef] = {false, false, false, false}; + Datum values[Natts_pg_attrdef] = {0}; + bool nulls[Natts_pg_attrdef] = {false}; Relation attrrel; HeapTuple atttup; Form_pg_attribute attStruct; - Datum valuesAtt[Natts_pg_attribute] = {0}; - bool nullsAtt[Natts_pg_attribute] = {0}; - bool replacesAtt[Natts_pg_attribute] = {0}; + Bitmapset *updated = NULL; char attgenerated; Oid attrdefOid; ObjectAddress colobject, @@ -64,13 +62,13 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, */ attrdefOid = GetNewOidWithIndex(adrel, AttrDefaultOidIndexId, Anum_pg_attrdef_oid); - values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid); - values[Anum_pg_attrdef_adrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel)); - values[Anum_pg_attrdef_adnum - 1] = Int16GetDatum(attnum); - values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin); + HeapTupleSetValue(pg_attrdef, oid, ObjectIdGetDatum(attrdefOid), values); + HeapTupleSetValue(pg_attrdef, adrelid, ObjectIdGetDatum(RelationGetRelid(rel)), values); + HeapTupleSetValue(pg_attrdef, adnum, Int16GetDatum(attnum), values); + HeapTupleSetValue(pg_attrdef, adbin, CStringGetTextDatum(adbin), values); tuple = heap_form_tuple(adrel->rd_att, values, nulls); - CatalogTupleInsert(adrel, tuple); + CatalogTupleInsert(adrel, tuple, NULL); defobject.classId = AttrDefaultRelationId; defobject.objectId = attrdefOid; @@ -79,7 +77,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, table_close(adrel, RowExclusiveLock); /* now can free some of the stuff allocated above */ - pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1])); + pfree(DatumGetPointer(HeapTupleValue(pg_attrdef, adbin, values))); heap_freetuple(tuple); pfree(adbin); @@ -91,22 +89,21 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, atttup = SearchSysCacheCopy2(ATTNUM, ObjectIdGetDatum(RelationGetRelid(rel)), Int16GetDatum(attnum)); + if (!HeapTupleIsValid(atttup)) elog(ERROR, "cache lookup failed for attribute %d of relation %u", attnum, RelationGetRelid(rel)); + attStruct = (Form_pg_attribute) GETSTRUCT(atttup); attgenerated = attStruct->attgenerated; - valuesAtt[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(true); - replacesAtt[Anum_pg_attribute_atthasdef - 1] = true; - - atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel), - valuesAtt, nullsAtt, replacesAtt); - - CatalogTupleUpdate(attrrel, &atttup->t_self, atttup); + Assert(bms_is_empty(updated)); + HeapTupleUpdateField(pg_attribute, atthasdef, BoolGetDatum(true), attStruct, updated); + CatalogTupleUpdate(attrrel, &atttup->t_self, atttup, updated, NULL); table_close(attrrel, RowExclusiveLock); heap_freetuple(atttup); + bms_free(updated); /* * Make a dependency so that the pg_attrdef entry goes away if the column @@ -256,7 +253,7 @@ RemoveAttrDefaultById(Oid attrdefId) ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false; - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple, NULL, NULL); /* * Our update of the pg_attribute row will force a relcache rebuild, so diff --git a/src/backend/catalog/pg_cast.c b/src/backend/catalog/pg_cast.c index 1773c9c5491..8ed900c2392 100644 --- a/src/backend/catalog/pg_cast.c +++ b/src/backend/catalog/pg_cast.c @@ -53,8 +53,8 @@ CastCreate(Oid sourcetypeid, Oid targettypeid, Relation relation; HeapTuple tuple; Oid castid; - Datum values[Natts_pg_cast]; - bool nulls[Natts_pg_cast] = {0}; + Datum values[Natts_pg_cast] = {0}; + bool nulls[Natts_pg_cast] = {false}; ObjectAddress myself, referenced; ObjectAddresses *addrs; @@ -78,16 +78,16 @@ CastCreate(Oid sourcetypeid, Oid targettypeid, /* ready to go */ castid = GetNewOidWithIndex(relation, CastOidIndexId, Anum_pg_cast_oid); - values[Anum_pg_cast_oid - 1] = ObjectIdGetDatum(castid); - values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid); - values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid); - values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid); - values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext); - values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod); + HeapTupleSetValue(pg_cast, oid, ObjectIdGetDatum(castid), values); + HeapTupleSetValue(pg_cast, castsource, ObjectIdGetDatum(sourcetypeid), values); + HeapTupleSetValue(pg_cast, casttarget, ObjectIdGetDatum(targettypeid), values); + HeapTupleSetValue(pg_cast, castfunc, ObjectIdGetDatum(funcid), values); + HeapTupleSetValue(pg_cast, castcontext, CharGetDatum(castcontext), values); + HeapTupleSetValue(pg_cast, castmethod, CharGetDatum(castmethod), values); tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls); - CatalogTupleInsert(relation, tuple); + CatalogTupleInsert(relation, tuple, NULL); addrs = new_object_addresses(); diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c index 469635b3580..e440bf577e3 100644 --- a/src/backend/catalog/pg_collation.c +++ b/src/backend/catalog/pg_collation.c @@ -54,8 +54,8 @@ CollationCreate(const char *collname, Oid collnamespace, Relation rel; TupleDesc tupDesc; HeapTuple tup; - Datum values[Natts_pg_collation]; - bool nulls[Natts_pg_collation]; + Datum values[Natts_pg_collation] = {0}; + bool nulls[Natts_pg_collation] = {false}; NameData name_name; Oid oid; ObjectAddress myself, @@ -175,38 +175,38 @@ CollationCreate(const char *collname, Oid collnamespace, namestrcpy(&name_name, collname); oid = GetNewOidWithIndex(rel, CollationOidIndexId, Anum_pg_collation_oid); - values[Anum_pg_collation_oid - 1] = ObjectIdGetDatum(oid); - values[Anum_pg_collation_collname - 1] = NameGetDatum(&name_name); - values[Anum_pg_collation_collnamespace - 1] = ObjectIdGetDatum(collnamespace); - values[Anum_pg_collation_collowner - 1] = ObjectIdGetDatum(collowner); - values[Anum_pg_collation_collprovider - 1] = CharGetDatum(collprovider); - values[Anum_pg_collation_collisdeterministic - 1] = BoolGetDatum(collisdeterministic); - values[Anum_pg_collation_collencoding - 1] = Int32GetDatum(collencoding); + HeapTupleSetValue(pg_collation, oid, ObjectIdGetDatum(oid), values); + HeapTupleSetValue(pg_collation, collname, NameGetDatum(&name_name), values); + HeapTupleSetValue(pg_collation, collnamespace, ObjectIdGetDatum(collnamespace), values); + HeapTupleSetValue(pg_collation, collowner, ObjectIdGetDatum(collowner), values); + HeapTupleSetValue(pg_collation, collprovider, CharGetDatum(collprovider), values); + HeapTupleSetValue(pg_collation, collisdeterministic, BoolGetDatum(collisdeterministic), values); + HeapTupleSetValue(pg_collation, collencoding, Int32GetDatum(collencoding), values); if (collcollate) - values[Anum_pg_collation_collcollate - 1] = CStringGetTextDatum(collcollate); + HeapTupleSetValue(pg_collation, collcollate, CStringGetTextDatum(collcollate), values); else - nulls[Anum_pg_collation_collcollate - 1] = true; + HeapTupleSetValueNull(pg_collation, collcollate, values, nulls); if (collctype) - values[Anum_pg_collation_collctype - 1] = CStringGetTextDatum(collctype); + HeapTupleSetValue(pg_collation, collctype, CStringGetTextDatum(collctype), values); else - nulls[Anum_pg_collation_collctype - 1] = true; + HeapTupleSetValueNull(pg_collation, collctype, values, nulls); if (colllocale) - values[Anum_pg_collation_colllocale - 1] = CStringGetTextDatum(colllocale); + HeapTupleSetValue(pg_collation, colllocale, CStringGetTextDatum(colllocale), values); else - nulls[Anum_pg_collation_colllocale - 1] = true; + HeapTupleSetValueNull(pg_collation, colllocale, values, nulls); if (collicurules) - values[Anum_pg_collation_collicurules - 1] = CStringGetTextDatum(collicurules); + HeapTupleSetValue(pg_collation, collicurules, CStringGetTextDatum(collicurules), values); else - nulls[Anum_pg_collation_collicurules - 1] = true; + HeapTupleSetValueNull(pg_collation, collicurules, values, nulls); if (collversion) - values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(collversion); + HeapTupleSetValue(pg_collation, collversion, CStringGetTextDatum(collversion), values); else - nulls[Anum_pg_collation_collversion - 1] = true; + HeapTupleSetValueNull(pg_collation, collversion, values, nulls); tup = heap_form_tuple(tupDesc, values, nulls); /* insert a new tuple */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); Assert(OidIsValid(oid)); /* set up dependencies for the new collation */ diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c index 090f680d190..247486ba7de 100644 --- a/src/backend/catalog/pg_conversion.c +++ b/src/backend/catalog/pg_conversion.c @@ -45,8 +45,8 @@ ConversionCreate(const char *conname, Oid connamespace, TupleDesc tupDesc; HeapTuple tup; Oid oid; - bool nulls[Natts_pg_conversion]; - Datum values[Natts_pg_conversion]; + Datum values[Natts_pg_conversion] = {0}; + bool nulls[Natts_pg_conversion] = {false}; NameData cname; ObjectAddress myself, referenced; @@ -94,19 +94,19 @@ ConversionCreate(const char *conname, Oid connamespace, namestrcpy(&cname, conname); oid = GetNewOidWithIndex(rel, ConversionOidIndexId, Anum_pg_conversion_oid); - values[Anum_pg_conversion_oid - 1] = ObjectIdGetDatum(oid); - values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname); - values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace); - values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner); - values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding); - values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding); - values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc); - values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def); + HeapTupleSetValue(pg_conversion, oid, ObjectIdGetDatum(oid), values); + HeapTupleSetValue(pg_conversion, conname, NameGetDatum(&cname), values); + HeapTupleSetValue(pg_conversion, connamespace, ObjectIdGetDatum(connamespace), values); + HeapTupleSetValue(pg_conversion, conowner, ObjectIdGetDatum(conowner), values); + HeapTupleSetValue(pg_conversion, conforencoding, Int32GetDatum(conforencoding), values); + HeapTupleSetValue(pg_conversion, contoencoding, Int32GetDatum(contoencoding), values); + HeapTupleSetValue(pg_conversion, conproc, ObjectIdGetDatum(conproc), values); + HeapTupleSetValue(pg_conversion, condefault, BoolGetDatum(def), values); tup = heap_form_tuple(tupDesc, values, nulls); /* insert a new tuple */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); myself.classId = ConversionRelationId; myself.objectId = oid; diff --git a/src/backend/catalog/pg_db_role_setting.c b/src/backend/catalog/pg_db_role_setting.c index 832e49a34be..2e95e28c0c2 100644 --- a/src/backend/catalog/pg_db_role_setting.c +++ b/src/backend/catalog/pg_db_role_setting.c @@ -74,21 +74,18 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt) if (new) { - Datum repl_val[Natts_pg_db_role_setting]; - bool repl_null[Natts_pg_db_role_setting]; - bool repl_repl[Natts_pg_db_role_setting]; + Datum values[Natts_pg_db_role_setting] = {0}; + bool nulls[Natts_pg_db_role_setting] = {false}; HeapTuple newtuple; + Bitmapset *updated = NULL; - memset(repl_repl, false, sizeof(repl_repl)); + HeapTupleUpdateValue(pg_db_role_setting, setconfig, PointerGetDatum(new), values, nulls, updated); - repl_val[Anum_pg_db_role_setting_setconfig - 1] = - PointerGetDatum(new); - repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true; - repl_null[Anum_pg_db_role_setting_setconfig - 1] = false; + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), + values, nulls, updated); + CatalogTupleUpdate(rel, &tuple->t_self, newtuple, updated, NULL); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); - CatalogTupleUpdate(rel, &tuple->t_self, newtuple); + bms_free(updated); } else CatalogTupleDelete(rel, &tuple->t_self); @@ -96,18 +93,14 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt) } else if (HeapTupleIsValid(tuple)) { - Datum repl_val[Natts_pg_db_role_setting]; - bool repl_null[Natts_pg_db_role_setting]; - bool repl_repl[Natts_pg_db_role_setting]; + Datum values[Natts_pg_db_role_setting] = {0}; + bool nulls[Natts_pg_db_role_setting] = {false}; + Bitmapset *updated = NULL; HeapTuple newtuple; Datum datum; bool isnull; ArrayType *a; - memset(repl_repl, false, sizeof(repl_repl)); - repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true; - repl_null[Anum_pg_db_role_setting_setconfig - 1] = false; - /* Extract old value of setconfig */ datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig, RelationGetDescr(rel), &isnull); @@ -121,12 +114,12 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt) if (a) { - repl_val[Anum_pg_db_role_setting_setconfig - 1] = - PointerGetDatum(a); + HeapTupleUpdateValue(pg_db_role_setting, setconfig, PointerGetDatum(a), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); - CatalogTupleUpdate(rel, &tuple->t_self, newtuple); + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), + values, nulls, updated); + CatalogTupleUpdate(rel, &tuple->t_self, newtuple, updated, NULL); + bms_free(updated); } else CatalogTupleDelete(rel, &tuple->t_self); @@ -135,21 +128,18 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt) { /* non-null valuestr means it's not RESET, so insert a new tuple */ HeapTuple newtuple; - Datum values[Natts_pg_db_role_setting]; - bool nulls[Natts_pg_db_role_setting]; + Datum values[Natts_pg_db_role_setting] = {0}; + bool nulls[Natts_pg_db_role_setting] = {false}; ArrayType *a; - memset(nulls, false, sizeof(nulls)); - a = GUCArrayAdd(NULL, setstmt->name, valuestr); - values[Anum_pg_db_role_setting_setdatabase - 1] = - ObjectIdGetDatum(databaseid); - values[Anum_pg_db_role_setting_setrole - 1] = ObjectIdGetDatum(roleid); - values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a); + HeapTupleSetValue(pg_db_role_setting, setdatabase, ObjectIdGetDatum(databaseid), values); + HeapTupleSetValue(pg_db_role_setting, setrole, ObjectIdGetDatum(roleid), values); + HeapTupleSetValue(pg_db_role_setting, setconfig, PointerGetDatum(a), values); newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls); - CatalogTupleInsert(rel, newtuple); + CatalogTupleInsert(rel, newtuple, NULL); } else { diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index c8b11f887e2..88deac7f3bd 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -61,7 +61,7 @@ recordMultipleDependencies(const ObjectAddress *depender, { Relation dependDesc; CatalogIndexState indstate; - TupleTableSlot **slot; + TupleTableSlot **slots; int i, max_slots, slot_init_count, @@ -88,7 +88,7 @@ recordMultipleDependencies(const ObjectAddress *depender, */ max_slots = Min(nreferenced, MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_depend)); - slot = palloc(sizeof(TupleTableSlot *) * max_slots); + slots = palloc(sizeof(TupleTableSlot *) * max_slots); /* Don't open indexes unless we need to make an update */ indstate = NULL; @@ -99,6 +99,9 @@ recordMultipleDependencies(const ObjectAddress *depender, slot_init_count = 0; for (i = 0; i < nreferenced; i++, referenced++) { + TupleTableSlot *slot; + Datum *values; + /* * If the referenced object is pinned by the system, there's no real * need to record dependencies on it. This saves lots of space in @@ -109,29 +112,32 @@ recordMultipleDependencies(const ObjectAddress *depender, if (slot_init_count < max_slots) { - slot[slot_stored_count] = MakeSingleTupleTableSlot(RelationGetDescr(dependDesc), - &TTSOpsHeapTuple); + slots[slot_stored_count] = MakeSingleTupleTableSlot(RelationGetDescr(dependDesc), + &TTSOpsHeapTuple); slot_init_count++; } - ExecClearTuple(slot[slot_stored_count]); + ExecClearTuple(slots[slot_stored_count]); + + slot = slots[slot_stored_count]; + values = slot->tts_values; /* * Record the dependency. Note we don't bother to check for duplicate * dependencies; there's no harm in them. */ - slot[slot_stored_count]->tts_values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId); - slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId); - slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId); - slot[slot_stored_count]->tts_values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior); - slot[slot_stored_count]->tts_values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId); - slot[slot_stored_count]->tts_values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId); - slot[slot_stored_count]->tts_values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId); - - memset(slot[slot_stored_count]->tts_isnull, false, - slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool)); - - ExecStoreVirtualTuple(slot[slot_stored_count]); + HeapTupleSetValue(pg_depend, refclassid, ObjectIdGetDatum(referenced->classId), values); + HeapTupleSetValue(pg_depend, refobjid, ObjectIdGetDatum(referenced->objectId), values); + HeapTupleSetValue(pg_depend, refobjsubid, Int32GetDatum(referenced->objectSubId), values); + HeapTupleSetValue(pg_depend, deptype, CharGetDatum((char) behavior), values); + HeapTupleSetValue(pg_depend, classid, ObjectIdGetDatum(depender->classId), values); + HeapTupleSetValue(pg_depend, objid, ObjectIdGetDatum(depender->objectId), values); + HeapTupleSetValue(pg_depend, objsubid, Int32GetDatum(depender->objectSubId), values); + + memset(slot->tts_isnull, false, + slot->tts_tupleDescriptor->natts * sizeof(bool)); + + ExecStoreVirtualTuple(slot); slot_stored_count++; /* If slots are full, insert a batch of tuples */ @@ -141,8 +147,7 @@ recordMultipleDependencies(const ObjectAddress *depender, if (indstate == NULL) indstate = CatalogOpenIndexes(dependDesc); - CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slot_stored_count, - indstate); + CatalogTuplesMultiInsert(dependDesc, slots, slot_stored_count, indstate); slot_stored_count = 0; } } @@ -154,8 +159,7 @@ recordMultipleDependencies(const ObjectAddress *depender, if (indstate == NULL) indstate = CatalogOpenIndexes(dependDesc); - CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slot_stored_count, - indstate); + CatalogTuplesMultiInsert(dependDesc, slots, slot_stored_count, indstate); } if (indstate != NULL) @@ -165,8 +169,8 @@ recordMultipleDependencies(const ObjectAddress *depender, /* Drop only the number of slots used */ for (i = 0; i < slot_init_count; i++) - ExecDropSingleTupleTableSlot(slot[i]); - pfree(slot); + ExecDropSingleTupleTableSlot(slots[i]); + pfree(slots); } /* @@ -531,14 +535,16 @@ changeDependencyFor(Oid classId, Oid objectId, CatalogTupleDelete(depRel, &tup->t_self); else { + Bitmapset *updated = NULL; + /* make a modifiable copy */ tup = heap_copytuple(tup); depform = (Form_pg_depend) GETSTRUCT(tup); - depform->refobjid = newRefObjectId; - - CatalogTupleUpdate(depRel, &tup->t_self, tup); + HeapTupleUpdateField(pg_depend, refobjid, newRefObjectId, depform, updated); + CatalogTupleUpdate(depRel, &tup->t_self, tup, updated, NULL); + bms_free(updated); heap_freetuple(tup); } @@ -588,15 +594,16 @@ changeDependenciesOf(Oid classId, Oid oldObjectId, while (HeapTupleIsValid((tup = systable_getnext(scan)))) { Form_pg_depend depform; + Bitmapset *updated = NULL; /* make a modifiable copy */ tup = heap_copytuple(tup); depform = (Form_pg_depend) GETSTRUCT(tup); - depform->objid = newObjectId; - - CatalogTupleUpdate(depRel, &tup->t_self, tup); + HeapTupleUpdateField(pg_depend, objid, newObjectId, depform, updated); + CatalogTupleUpdate(depRel, &tup->t_self, tup, updated, NULL); + bms_free(updated); heap_freetuple(tup); count++; @@ -675,15 +682,16 @@ changeDependenciesOn(Oid refClassId, Oid oldRefObjectId, else { Form_pg_depend depform; + Bitmapset *updated = NULL; /* make a modifiable copy */ tup = heap_copytuple(tup); depform = (Form_pg_depend) GETSTRUCT(tup); - depform->refobjid = newRefObjectId; - - CatalogTupleUpdate(depRel, &tup->t_self, tup); + HeapTupleUpdateField(pg_depend, refobjid, newRefObjectId, depform, updated); + CatalogTupleUpdate(depRel, &tup->t_self, tup, updated, NULL); + bms_free(updated); heap_freetuple(tup); } diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c index da9c2a46cfa..be87e9ad056 100644 --- a/src/backend/catalog/pg_enum.c +++ b/src/backend/catalog/pg_enum.c @@ -194,12 +194,12 @@ EnumValuesCreate(Oid enumTypeOid, List *vals) memset(slot[slotCount]->tts_isnull, false, slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool)); - slot[slotCount]->tts_values[Anum_pg_enum_oid - 1] = ObjectIdGetDatum(oids[elemno]); - slot[slotCount]->tts_values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid); - slot[slotCount]->tts_values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(elemno + 1); + HeapTupleSetValue(pg_enum, oid, ObjectIdGetDatum(oids[elemno]), slot[slotCount]->tts_values); + HeapTupleSetValue(pg_enum, enumtypid, ObjectIdGetDatum(enumTypeOid), slot[slotCount]->tts_values); + HeapTupleSetValue(pg_enum, enumsortorder, Float4GetDatum(elemno + 1), slot[slotCount]->tts_values); namestrcpy(enumlabel, lab); - slot[slotCount]->tts_values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(enumlabel); + HeapTupleSetValue(pg_enum, enumlabel, NameGetDatum(enumlabel), slot[slotCount]->tts_values); ExecStoreVirtualTuple(slot[slotCount]); slotCount++; @@ -207,8 +207,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals) /* if slots are full, insert a batch of tuples */ if (slotCount == nslots) { - CatalogTuplesMultiInsertWithInfo(pg_enum, slot, slotCount, - indstate); + CatalogTuplesMultiInsert(pg_enum, slot, slotCount, indstate); slotCount = 0; } @@ -217,10 +216,9 @@ EnumValuesCreate(Oid enumTypeOid, List *vals) /* Insert any tuples left in the buffer */ if (slotCount > 0) - CatalogTuplesMultiInsertWithInfo(pg_enum, slot, slotCount, - indstate); + CatalogTuplesMultiInsert(pg_enum, slot, slotCount, indstate); - /* clean up */ + /* Clean up */ pfree(oids); for (int i = 0; i < nslots; i++) ExecDropSingleTupleTableSlot(slot[i]); @@ -310,8 +308,8 @@ AddEnumLabel(Oid enumTypeOid, { Relation pg_enum; Oid newOid; - Datum values[Natts_pg_enum]; - bool nulls[Natts_pg_enum]; + Datum values[Natts_pg_enum] = {0}; + bool nulls[Natts_pg_enum] = {false}; NameData enumlabel; HeapTuple enum_tup; float4 newelemorder; @@ -577,13 +575,13 @@ restart: /* Create the new pg_enum entry */ memset(nulls, false, sizeof(nulls)); - values[Anum_pg_enum_oid - 1] = ObjectIdGetDatum(newOid); - values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid); - values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(newelemorder); + HeapTupleSetValue(pg_enum, oid, ObjectIdGetDatum(newOid), values); + HeapTupleSetValue(pg_enum, enumtypid, ObjectIdGetDatum(enumTypeOid), values); + HeapTupleSetValue(pg_enum, enumsortorder, Float4GetDatum(newelemorder), values); namestrcpy(&enumlabel, newVal); - values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel); + HeapTupleSetValue(pg_enum, enumlabel, NameGetDatum(&enumlabel), values); enum_tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls); - CatalogTupleInsert(pg_enum, enum_tup); + CatalogTupleInsert(pg_enum, enum_tup, NULL); heap_freetuple(enum_tup); table_close(pg_enum, RowExclusiveLock); @@ -629,6 +627,7 @@ RenameEnumLabel(Oid enumTypeOid, HeapTuple old_tup; bool found_new; int i; + Bitmapset *updated = NULL; /* check length of new label is ok */ if (strlen(newVal) > (NAMEDATALEN - 1)) @@ -689,9 +688,12 @@ RenameEnumLabel(Oid enumTypeOid, /* Update the pg_enum entry */ namestrcpy(&en->enumlabel, newVal); - CatalogTupleUpdate(pg_enum, &enum_tup->t_self, enum_tup); - heap_freetuple(enum_tup); + HeapTupleMarkColumnUpdated(pg_enum, enumlabel, updated); + + CatalogTupleUpdate(pg_enum, &enum_tup->t_self, enum_tup, updated, NULL); + bms_free(updated); + heap_freetuple(enum_tup); table_close(pg_enum, RowExclusiveLock); } @@ -792,9 +794,12 @@ RenumberEnumType(Relation pg_enum, HeapTuple *existing, int nelems) newsortorder = i + 1; if (en->enumsortorder != newsortorder) { - en->enumsortorder = newsortorder; + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_enum, enumsortorder, newsortorder, en, updated); - CatalogTupleUpdate(pg_enum, &newtup->t_self, newtup); + CatalogTupleUpdate(pg_enum, &newtup->t_self, newtup, updated, NULL); + bms_free(updated); } heap_freetuple(newtup); diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index 929bb53b620..a4e0338b54c 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -507,8 +507,8 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId) void StoreSingleInheritance(Oid relationId, Oid parentOid, int32 seqNumber) { - Datum values[Natts_pg_inherits]; - bool nulls[Natts_pg_inherits]; + Datum values[Natts_pg_inherits] = {0}; + bool nulls[Natts_pg_inherits] = {false}; HeapTuple tuple; Relation inhRelation; @@ -517,16 +517,16 @@ StoreSingleInheritance(Oid relationId, Oid parentOid, int32 seqNumber) /* * Make the pg_inherits entry */ - values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(relationId); - values[Anum_pg_inherits_inhparent - 1] = ObjectIdGetDatum(parentOid); - values[Anum_pg_inherits_inhseqno - 1] = Int32GetDatum(seqNumber); - values[Anum_pg_inherits_inhdetachpending - 1] = BoolGetDatum(false); + HeapTupleSetValue(pg_inherits, inhrelid, ObjectIdGetDatum(relationId), values); + HeapTupleSetValue(pg_inherits, inhparent, ObjectIdGetDatum(parentOid), values); + HeapTupleSetValue(pg_inherits, inhseqno, Int32GetDatum(seqNumber), values); + HeapTupleSetValue(pg_inherits, inhdetachpending, BoolGetDatum(false), values); memset(nulls, 0, sizeof(nulls)); tuple = heap_form_tuple(RelationGetDescr(inhRelation), values, nulls); - CatalogTupleInsert(inhRelation, tuple); + CatalogTupleInsert(inhRelation, tuple, NULL); heap_freetuple(tuple); diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c index 33e8fa96a65..e49cea50416 100644 --- a/src/backend/catalog/pg_largeobject.c +++ b/src/backend/catalog/pg_largeobject.c @@ -39,8 +39,8 @@ LargeObjectCreate(Oid loid) Relation pg_lo_meta; HeapTuple ntup; Oid loid_new; - Datum values[Natts_pg_largeobject_metadata]; - bool nulls[Natts_pg_largeobject_metadata]; + Datum values[Natts_pg_largeobject_metadata] = {0}; + bool nulls[Natts_pg_largeobject_metadata] = {false}; Oid ownerId; Acl *lomacl; @@ -50,9 +50,6 @@ LargeObjectCreate(Oid loid) /* * Insert metadata of the largeobject */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - if (OidIsValid(loid)) loid_new = loid; else @@ -62,20 +59,17 @@ LargeObjectCreate(Oid loid) ownerId = GetUserId(); lomacl = get_user_default_acl(OBJECT_LARGEOBJECT, ownerId, InvalidOid); - values[Anum_pg_largeobject_metadata_oid - 1] = ObjectIdGetDatum(loid_new); - values[Anum_pg_largeobject_metadata_lomowner - 1] - = ObjectIdGetDatum(ownerId); + HeapTupleSetValue(pg_largeobject_metadata, oid, ObjectIdGetDatum(loid_new), values); + HeapTupleSetValue(pg_largeobject_metadata, lomowner, ObjectIdGetDatum(ownerId), values); if (lomacl != NULL) - values[Anum_pg_largeobject_metadata_lomacl - 1] - = PointerGetDatum(lomacl); + HeapTupleSetValue(pg_largeobject_metadata, lomacl, PointerGetDatum(lomacl), values); else - nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true; + HeapTupleSetValueNull(pg_largeobject_metadata, lomacl, values, nulls); - ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta), - values, nulls); + ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta), values, nulls); - CatalogTupleInsert(pg_lo_meta, ntup); + CatalogTupleInsert(pg_lo_meta, ntup, NULL); heap_freetuple(ntup); diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c index 616bcc78521..fa2a970108c 100644 --- a/src/backend/catalog/pg_namespace.c +++ b/src/backend/catalog/pg_namespace.c @@ -45,12 +45,11 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp) Relation nspdesc; HeapTuple tup; Oid nspoid; - bool nulls[Natts_pg_namespace]; - Datum values[Natts_pg_namespace]; + bool nulls[Natts_pg_namespace] = {false}; + Datum values[Natts_pg_namespace] = {0}; NameData nname; TupleDesc tupDesc; ObjectAddress myself; - int i; Acl *nspacl; /* sanity checks */ @@ -72,28 +71,21 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp) nspdesc = table_open(NamespaceRelationId, RowExclusiveLock); tupDesc = nspdesc->rd_att; - /* initialize nulls and values */ - for (i = 0; i < Natts_pg_namespace; i++) - { - nulls[i] = false; - values[i] = (Datum) 0; - } - nspoid = GetNewOidWithIndex(nspdesc, NamespaceOidIndexId, Anum_pg_namespace_oid); - values[Anum_pg_namespace_oid - 1] = ObjectIdGetDatum(nspoid); + HeapTupleSetValue(pg_namespace, oid, ObjectIdGetDatum(nspoid), values); namestrcpy(&nname, nspName); - values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname); - values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId); + HeapTupleSetValue(pg_namespace, nspname, NameGetDatum(&nname), values); + HeapTupleSetValue(pg_namespace, nspowner, ObjectIdGetDatum(ownerId), values); if (nspacl != NULL) - values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(nspacl); + HeapTupleSetValue(pg_namespace, nspacl, PointerGetDatum(nspacl), values); else - nulls[Anum_pg_namespace_nspacl - 1] = true; + HeapTupleSetValueNull(pg_namespace, nspacl, values, nulls); tup = heap_form_tuple(tupDesc, values, nulls); - CatalogTupleInsert(nspdesc, tup); + CatalogTupleInsert(nspdesc, tup, NULL); Assert(OidIsValid(nspoid)); table_close(nspdesc, RowExclusiveLock); diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 44d2ccb6788..2595ef1d787 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -17,6 +17,7 @@ */ #include "postgres.h" +#include "access/htup.h" #include "access/htup_details.h" #include "access/table.h" #include "access/xact.h" @@ -199,10 +200,11 @@ OperatorShellMake(const char *operatorName, Oid operatorObjectId; int i; HeapTuple tup; - Datum values[Natts_pg_operator]; - bool nulls[Natts_pg_operator]; + Datum values[Natts_pg_operator] = {0}; + bool nulls[Natts_pg_operator] = {false}; NameData oname; TupleDesc tupDesc; + Bitmapset *updated = NULL; /* * validate operator name @@ -234,22 +236,23 @@ OperatorShellMake(const char *operatorName, */ operatorObjectId = GetNewOidWithIndex(pg_operator_desc, OperatorOidIndexId, Anum_pg_operator_oid); - values[Anum_pg_operator_oid - 1] = ObjectIdGetDatum(operatorObjectId); + + HeapTupleUpdateValue(pg_operator, oid, ObjectIdGetDatum(operatorObjectId), values, nulls, updated); namestrcpy(&oname, operatorName); - values[Anum_pg_operator_oprname - 1] = NameGetDatum(&oname); - values[Anum_pg_operator_oprnamespace - 1] = ObjectIdGetDatum(operatorNamespace); - values[Anum_pg_operator_oprowner - 1] = ObjectIdGetDatum(GetUserId()); - values[Anum_pg_operator_oprkind - 1] = CharGetDatum(leftTypeId ? 'b' : 'l'); - values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(false); - values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(false); - values[Anum_pg_operator_oprleft - 1] = ObjectIdGetDatum(leftTypeId); - values[Anum_pg_operator_oprright - 1] = ObjectIdGetDatum(rightTypeId); - values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(InvalidOid); + HeapTupleUpdateValue(pg_operator, oprname, NameGetDatum(&oname), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprnamespace, ObjectIdGetDatum(operatorNamespace), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprowner, ObjectIdGetDatum(GetUserId()), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprkind, CharGetDatum(leftTypeId ? 'b' : 'l'), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcanmerge, BoolGetDatum(false), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcanhash, BoolGetDatum(false), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprleft, ObjectIdGetDatum(leftTypeId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprright, ObjectIdGetDatum(rightTypeId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprresult, ObjectIdGetDatum(InvalidOid), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcom, ObjectIdGetDatum(InvalidOid), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprnegate, ObjectIdGetDatum(InvalidOid), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcode, ObjectIdGetDatum(InvalidOid), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprrest, ObjectIdGetDatum(InvalidOid), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprjoin, ObjectIdGetDatum(InvalidOid), values, nulls, updated); /* * create a new operator tuple @@ -259,7 +262,7 @@ OperatorShellMake(const char *operatorName, /* * insert our "shell" operator tuple */ - CatalogTupleInsert(pg_operator_desc, tup); + CatalogTupleInsert(pg_operator_desc, tup, NULL); /* Add dependencies for the entry */ makeOperatorDependencies(tup, true, false); @@ -333,9 +336,9 @@ OperatorCreate(const char *operatorName, Relation pg_operator_desc; HeapTuple tup; bool isUpdate; - bool nulls[Natts_pg_operator]; - bool replaces[Natts_pg_operator]; - Datum values[Natts_pg_operator]; + Datum values[Natts_pg_operator] = {0}; + bool nulls[Natts_pg_operator] = {false}; + Bitmapset *updated = NULL; Oid operatorObjectId; bool operatorAlreadyDefined; Oid operResultType; @@ -343,7 +346,6 @@ OperatorCreate(const char *operatorName, negatorId; bool selfCommutator = false; NameData oname; - int i; ObjectAddress address; /* @@ -447,32 +449,25 @@ OperatorCreate(const char *operatorName, else negatorId = InvalidOid; - /* - * set up values in the operator tuple - */ - - for (i = 0; i < Natts_pg_operator; ++i) - { - values[i] = (Datum) 0; - replaces[i] = true; - nulls[i] = false; - } + /* Set up values in the operator tuple */ + HeapTupleUpdateSetAllColumnsUpdated(pg_operator, updated); + HeapTupleSetColumnNotUpdated(pg_operator, oid, updated); namestrcpy(&oname, operatorName); - values[Anum_pg_operator_oprname - 1] = NameGetDatum(&oname); - values[Anum_pg_operator_oprnamespace - 1] = ObjectIdGetDatum(operatorNamespace); - values[Anum_pg_operator_oprowner - 1] = ObjectIdGetDatum(GetUserId()); - values[Anum_pg_operator_oprkind - 1] = CharGetDatum(leftTypeId ? 'b' : 'l'); - values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(canMerge); - values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(canHash); - values[Anum_pg_operator_oprleft - 1] = ObjectIdGetDatum(leftTypeId); - values[Anum_pg_operator_oprright - 1] = ObjectIdGetDatum(rightTypeId); - values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(operResultType); - values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(commutatorId); - values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(negatorId); - values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(procedureId); - values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restrictionId); - values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinId); + HeapTupleUpdateValue(pg_operator, oprname, NameGetDatum(&oname), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprnamespace, ObjectIdGetDatum(operatorNamespace), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprowner, ObjectIdGetDatum(GetUserId()), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprkind, CharGetDatum(leftTypeId ? 'b' : 'l'), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcanmerge, BoolGetDatum(canMerge), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcanhash, BoolGetDatum(canHash), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprleft, ObjectIdGetDatum(leftTypeId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprright, ObjectIdGetDatum(rightTypeId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprresult, ObjectIdGetDatum(operResultType), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcom, ObjectIdGetDatum(commutatorId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprnegate, ObjectIdGetDatum(negatorId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcode, ObjectIdGetDatum(procedureId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprrest, ObjectIdGetDatum(restrictionId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprjoin, ObjectIdGetDatum(joinId), values, nulls, updated); pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock); @@ -489,14 +484,9 @@ OperatorCreate(const char *operatorName, elog(ERROR, "cache lookup failed for operator %u", operatorObjectId); - replaces[Anum_pg_operator_oid - 1] = false; - tup = heap_modify_tuple(tup, - RelationGetDescr(pg_operator_desc), - values, - nulls, - replaces); + tup = heap_update_tuple(tup, RelationGetDescr(pg_operator_desc), values, nulls, updated); - CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup); + CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup, updated, NULL); } else { @@ -505,12 +495,12 @@ OperatorCreate(const char *operatorName, operatorObjectId = GetNewOidWithIndex(pg_operator_desc, OperatorOidIndexId, Anum_pg_operator_oid); - values[Anum_pg_operator_oid - 1] = ObjectIdGetDatum(operatorObjectId); + HeapTupleUpdateValue(pg_operator, oid, ObjectIdGetDatum(operatorObjectId), values, nulls, updated); tup = heap_form_tuple(RelationGetDescr(pg_operator_desc), values, nulls); - CatalogTupleInsert(pg_operator_desc, tup); + CatalogTupleInsert(pg_operator_desc, tup, NULL); } /* Add dependencies for the entry */ @@ -536,6 +526,7 @@ OperatorCreate(const char *operatorName, /* Post creation hook for new operator */ InvokeObjectPostCreateHook(OperatorRelationId, operatorObjectId, 0); + bms_free(updated); table_close(pg_operator_desc, RowExclusiveLock); return address; @@ -708,6 +699,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) if (HeapTupleIsValid(tup)) { Form_pg_operator t = (Form_pg_operator) GETSTRUCT(tup); + Bitmapset *updated = NULL; bool update_commutator = false; /* @@ -717,7 +709,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) */ if (isDelete && OidIsValid(t->oprcom)) { - t->oprcom = InvalidOid; + HeapTupleUpdateField(pg_operator, oprcom, InvalidOid, t, updated); update_commutator = true; } else if (!isDelete && t->oprcom != baseId) @@ -745,14 +737,14 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) NameStr(t->oprname), t->oprcom))); } - t->oprcom = baseId; + HeapTupleUpdateField(pg_operator, oprcom, baseId, t, updated); update_commutator = true; } /* If any columns were found to need modification, update tuple. */ if (update_commutator) { - CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup); + CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup, updated, NULL); /* * Do CCI to make the updated tuple visible. We must do this in @@ -763,6 +755,8 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) */ CommandCounterIncrement(); } + + bms_free(updated); } /* @@ -777,6 +771,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) { Form_pg_operator t = (Form_pg_operator) GETSTRUCT(tup); bool update_negator = false; + Bitmapset *updated = NULL; /* * We can skip doing anything if the negator's oprnegate field is @@ -785,7 +780,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) */ if (isDelete && OidIsValid(t->oprnegate)) { - t->oprnegate = InvalidOid; + HeapTupleUpdateField(pg_operator, oprnegate, InvalidOid, t, updated); update_negator = true; } else if (!isDelete && t->oprnegate != baseId) @@ -813,14 +808,14 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) NameStr(t->oprname), t->oprnegate))); } - t->oprnegate = baseId; + HeapTupleUpdateField(pg_operator, oprnegate, baseId, t, updated); update_negator = true; } /* If any columns were found to need modification, update tuple. */ if (update_negator) { - CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup); + CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup, updated, NULL); /* * In the deletion case, do CCI to make the updated tuple visible. @@ -831,6 +826,8 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) if (isDelete) CommandCounterIncrement(); } + + bms_free(updated); } /* Close relation and release catalog lock. */ diff --git a/src/backend/catalog/pg_parameter_acl.c b/src/backend/catalog/pg_parameter_acl.c index dcdf49ea408..04e3545552d 100644 --- a/src/backend/catalog/pg_parameter_acl.c +++ b/src/backend/catalog/pg_parameter_acl.c @@ -74,7 +74,7 @@ ParameterAclCreate(const char *parameter) TupleDesc tupDesc; HeapTuple tuple; Datum values[Natts_pg_parameter_acl] = {0}; - bool nulls[Natts_pg_parameter_acl] = {0}; + bool nulls[Natts_pg_parameter_acl] = {false}; /* * To prevent cluttering pg_parameter_acl with useless entries, insist @@ -96,12 +96,11 @@ ParameterAclCreate(const char *parameter) parameterId = GetNewOidWithIndex(rel, ParameterAclOidIndexId, Anum_pg_parameter_acl_oid); - values[Anum_pg_parameter_acl_oid - 1] = ObjectIdGetDatum(parameterId); - values[Anum_pg_parameter_acl_parname - 1] = - PointerGetDatum(cstring_to_text(parname)); - nulls[Anum_pg_parameter_acl_paracl - 1] = true; + HeapTupleSetValue(pg_parameter_acl, oid, ObjectIdGetDatum(parameterId), values); + HeapTupleSetValue(pg_parameter_acl, parname, PointerGetDatum(cstring_to_text(parname)), values); + HeapTupleSetValueNull(pg_parameter_acl, paracl, values, nulls); tuple = heap_form_tuple(tupDesc, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); /* Close pg_parameter_acl, but keep lock till commit. */ heap_freetuple(tuple); diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index b89b9ccda0e..252a2f4aeda 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -14,6 +14,7 @@ */ #include "postgres.h" +#include "access/htup.h" #include "access/htup_details.h" #include "access/table.h" #include "access/xact.h" @@ -134,9 +135,9 @@ ProcedureCreate(const char *procedureName, Relation rel; HeapTuple tup; HeapTuple oldtup; - bool nulls[Natts_pg_proc]; - Datum values[Natts_pg_proc]; - bool replaces[Natts_pg_proc]; + Datum values[Natts_pg_proc] = {0}; + bool nulls[Natts_pg_proc] = {false}; + Bitmapset *updated = NULL; NameData procname; TupleDesc tupDesc; bool is_update; @@ -316,67 +317,61 @@ ProcedureCreate(const char *procedureName, /* * All seems OK; prepare the data to be inserted into pg_proc. */ - - for (i = 0; i < Natts_pg_proc; ++i) - { - nulls[i] = false; - values[i] = (Datum) 0; - replaces[i] = true; - } + HeapTupleUpdateSetAllColumnsUpdated(pg_proc, updated); namestrcpy(&procname, procedureName); - values[Anum_pg_proc_proname - 1] = NameGetDatum(&procname); - values[Anum_pg_proc_pronamespace - 1] = ObjectIdGetDatum(procNamespace); - values[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(proowner); - values[Anum_pg_proc_prolang - 1] = ObjectIdGetDatum(languageObjectId); - values[Anum_pg_proc_procost - 1] = Float4GetDatum(procost); - values[Anum_pg_proc_prorows - 1] = Float4GetDatum(prorows); - values[Anum_pg_proc_provariadic - 1] = ObjectIdGetDatum(variadicType); - values[Anum_pg_proc_prosupport - 1] = ObjectIdGetDatum(prosupport); - values[Anum_pg_proc_prokind - 1] = CharGetDatum(prokind); - values[Anum_pg_proc_prosecdef - 1] = BoolGetDatum(security_definer); - values[Anum_pg_proc_proleakproof - 1] = BoolGetDatum(isLeakProof); - values[Anum_pg_proc_proisstrict - 1] = BoolGetDatum(isStrict); - values[Anum_pg_proc_proretset - 1] = BoolGetDatum(returnsSet); - values[Anum_pg_proc_provolatile - 1] = CharGetDatum(volatility); - values[Anum_pg_proc_proparallel - 1] = CharGetDatum(parallel); - values[Anum_pg_proc_pronargs - 1] = UInt16GetDatum(parameterCount); - values[Anum_pg_proc_pronargdefaults - 1] = UInt16GetDatum(list_length(parameterDefaults)); - values[Anum_pg_proc_prorettype - 1] = ObjectIdGetDatum(returnType); - values[Anum_pg_proc_proargtypes - 1] = PointerGetDatum(parameterTypes); + HeapTupleUpdateValue(pg_proc, proname, NameGetDatum(&procname), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, pronamespace, ObjectIdGetDatum(procNamespace), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proowner, ObjectIdGetDatum(proowner), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prolang, ObjectIdGetDatum(languageObjectId), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, procost, Float4GetDatum(procost), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prorows, Float4GetDatum(prorows), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, provariadic, ObjectIdGetDatum(variadicType), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prosupport, ObjectIdGetDatum(prosupport), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prokind, CharGetDatum(prokind), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prosecdef, BoolGetDatum(security_definer), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proleakproof, BoolGetDatum(isLeakProof), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proisstrict, BoolGetDatum(isStrict), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proretset, BoolGetDatum(returnsSet), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, provolatile, CharGetDatum(volatility), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proparallel, CharGetDatum(parallel), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, pronargs, UInt16GetDatum(parameterCount), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, pronargdefaults, UInt16GetDatum(list_length(parameterDefaults)), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prorettype, ObjectIdGetDatum(returnType), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proargtypes, PointerGetDatum(parameterTypes), values, nulls, updated); if (allParameterTypes != PointerGetDatum(NULL)) - values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes; + HeapTupleUpdateValue(pg_proc, proallargtypes, allParameterTypes, values, nulls, updated); else - nulls[Anum_pg_proc_proallargtypes - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proallargtypes, values, nulls, updated); if (parameterModes != PointerGetDatum(NULL)) - values[Anum_pg_proc_proargmodes - 1] = parameterModes; + HeapTupleUpdateValue(pg_proc, proargmodes, parameterModes, values, nulls, updated); else - nulls[Anum_pg_proc_proargmodes - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proargmodes, values, nulls, updated); if (parameterNames != PointerGetDatum(NULL)) - values[Anum_pg_proc_proargnames - 1] = parameterNames; + HeapTupleUpdateValue(pg_proc, proargnames, parameterNames, values, nulls, updated); else - nulls[Anum_pg_proc_proargnames - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proargnames, values, nulls, updated); if (parameterDefaults != NIL) - values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodeToString(parameterDefaults)); + HeapTupleUpdateValue(pg_proc, proargdefaults, CStringGetTextDatum(nodeToString(parameterDefaults)), values, nulls, updated); else - nulls[Anum_pg_proc_proargdefaults - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proargdefaults, values, nulls, updated); if (trftypes != PointerGetDatum(NULL)) - values[Anum_pg_proc_protrftypes - 1] = trftypes; + HeapTupleUpdateValue(pg_proc, protrftypes, trftypes, values, nulls, updated); else - nulls[Anum_pg_proc_protrftypes - 1] = true; - values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc); + HeapTupleUpdateValueNull(pg_proc, protrftypes, values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prosrc, CStringGetTextDatum(prosrc), values, nulls, updated); if (probin) - values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin); + HeapTupleUpdateValue(pg_proc, probin, CStringGetTextDatum(probin), values, nulls, updated); else - nulls[Anum_pg_proc_probin - 1] = true; + HeapTupleUpdateValueNull(pg_proc, probin, values, nulls, updated); if (prosqlbody) - values[Anum_pg_proc_prosqlbody - 1] = CStringGetTextDatum(nodeToString(prosqlbody)); + HeapTupleUpdateValue(pg_proc, prosqlbody, CStringGetTextDatum(nodeToString(prosqlbody)), values, nulls, updated); else - nulls[Anum_pg_proc_prosqlbody - 1] = true; + HeapTupleUpdateValueNull(pg_proc, prosqlbody, values, nulls, updated); if (proconfig != PointerGetDatum(NULL)) - values[Anum_pg_proc_proconfig - 1] = proconfig; + HeapTupleUpdateValue(pg_proc, proconfig, proconfig, values, nulls, updated); else - nulls[Anum_pg_proc_proconfig - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proconfig, values, nulls, updated); /* proacl will be determined later */ rel = table_open(ProcedureRelationId, RowExclusiveLock); @@ -577,13 +572,13 @@ ProcedureCreate(const char *procedureName, * Do not change existing oid, ownership or permissions, either. Note * dependency-update code below has to agree with this decision. */ - replaces[Anum_pg_proc_oid - 1] = false; - replaces[Anum_pg_proc_proowner - 1] = false; - replaces[Anum_pg_proc_proacl - 1] = false; + HeapTupleSetColumnNotUpdated(pg_proc, oid, updated); + HeapTupleSetColumnNotUpdated(pg_proc, proowner, updated); + HeapTupleSetColumnNotUpdated(pg_proc, proacl, updated); /* Okay, do it... */ - tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); + tup = heap_update_tuple(oldtup, tupDesc, values, nulls, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); ReleaseSysCache(oldtup); is_update = true; @@ -597,18 +592,23 @@ ProcedureCreate(const char *procedureName, proacl = get_user_default_acl(OBJECT_FUNCTION, proowner, procNamespace); if (proacl != NULL) - values[Anum_pg_proc_proacl - 1] = PointerGetDatum(proacl); + HeapTupleUpdateValue(pg_proc, proacl, PointerGetDatum(proacl), values, nulls, updated); else - nulls[Anum_pg_proc_proacl - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proacl, values, nulls, updated); newOid = GetNewOidWithIndex(rel, ProcedureOidIndexId, Anum_pg_proc_oid); - values[Anum_pg_proc_oid - 1] = ObjectIdGetDatum(newOid); + HeapTupleUpdateValue(pg_proc, oid, ObjectIdGetDatum(newOid), values, nulls, updated); + + /* Okay, do it... */ tup = heap_form_tuple(tupDesc, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); + is_update = false; } + bms_free(updated); + updated = NULL; retval = ((Form_pg_proc) GETSTRUCT(tup))->oid; diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index ac2f4ee3561..9521b7cd3a4 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -433,8 +433,8 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri, { Relation rel; HeapTuple tup; - Datum values[Natts_pg_publication_rel]; - bool nulls[Natts_pg_publication_rel]; + Datum values[Natts_pg_publication_rel] = {0}; + bool nulls[Natts_pg_publication_rel] = {false}; Relation targetrel = pri->relation; Oid relid = RelationGetRelid(targetrel); Oid pubreloid; @@ -477,28 +477,26 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri, pubreloid = GetNewOidWithIndex(rel, PublicationRelObjectIndexId, Anum_pg_publication_rel_oid); - values[Anum_pg_publication_rel_oid - 1] = ObjectIdGetDatum(pubreloid); - values[Anum_pg_publication_rel_prpubid - 1] = - ObjectIdGetDatum(pubid); - values[Anum_pg_publication_rel_prrelid - 1] = - ObjectIdGetDatum(relid); + HeapTupleSetValue(pg_publication_rel, oid, ObjectIdGetDatum(pubreloid), values); + HeapTupleSetValue(pg_publication_rel, prpubid, ObjectIdGetDatum(pubid), values); + HeapTupleSetValue(pg_publication_rel, prrelid, ObjectIdGetDatum(relid), values); /* Add qualifications, if available */ if (pri->whereClause != NULL) - values[Anum_pg_publication_rel_prqual - 1] = CStringGetTextDatum(nodeToString(pri->whereClause)); + HeapTupleSetValue(pg_publication_rel, prqual, CStringGetTextDatum(nodeToString(pri->whereClause)), values); else - nulls[Anum_pg_publication_rel_prqual - 1] = true; + HeapTupleSetValueNull(pg_publication_rel, prqual, values, nulls); /* Add column list, if available */ if (pri->columns) - values[Anum_pg_publication_rel_prattrs - 1] = PointerGetDatum(attnumstoint2vector(attnums)); + HeapTupleSetValue(pg_publication_rel, prattrs, PointerGetDatum(attnumstoint2vector(attnums)), values); else - nulls[Anum_pg_publication_rel_prattrs - 1] = true; + HeapTupleSetValueNull(pg_publication_rel, prattrs, values, nulls); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); /* Insert tuple into catalog. */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); /* Register dependencies as needed */ @@ -674,8 +672,8 @@ publication_add_schema(Oid pubid, Oid schemaid, bool if_not_exists) { Relation rel; HeapTuple tup; - Datum values[Natts_pg_publication_namespace]; - bool nulls[Natts_pg_publication_namespace]; + Datum values[Natts_pg_publication_namespace] = {0}; + bool nulls[Natts_pg_publication_namespace] = {false}; Oid psschid; Publication *pub = GetPublication(pubid); List *schemaRels = NIL; @@ -712,16 +710,14 @@ publication_add_schema(Oid pubid, Oid schemaid, bool if_not_exists) psschid = GetNewOidWithIndex(rel, PublicationNamespaceObjectIndexId, Anum_pg_publication_namespace_oid); - values[Anum_pg_publication_namespace_oid - 1] = ObjectIdGetDatum(psschid); - values[Anum_pg_publication_namespace_pnpubid - 1] = - ObjectIdGetDatum(pubid); - values[Anum_pg_publication_namespace_pnnspid - 1] = - ObjectIdGetDatum(schemaid); + HeapTupleSetValue(pg_publication_namespace, oid, ObjectIdGetDatum(psschid), values); + HeapTupleSetValue(pg_publication_namespace, pnpubid, ObjectIdGetDatum(pubid), values); + HeapTupleSetValue(pg_publication_namespace, pnnspid, ObjectIdGetDatum(schemaid), values); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); /* Insert tuple into catalog */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); ObjectAddressSet(myself, PublicationNamespaceRelationId, psschid); diff --git a/src/backend/catalog/pg_range.c b/src/backend/catalog/pg_range.c index 8df73e7ab71..4e4d2d37d10 100644 --- a/src/backend/catalog/pg_range.c +++ b/src/backend/catalog/pg_range.c @@ -38,8 +38,8 @@ RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation, RegProcedure rangeSubDiff, Oid multirangeTypeOid) { Relation pg_range; - Datum values[Natts_pg_range]; - bool nulls[Natts_pg_range]; + Datum values[Natts_pg_range] = {0}; + bool nulls[Natts_pg_range] = {false}; HeapTuple tup; ObjectAddress myself; ObjectAddress referenced; @@ -50,17 +50,17 @@ RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation, memset(nulls, 0, sizeof(nulls)); - values[Anum_pg_range_rngtypid - 1] = ObjectIdGetDatum(rangeTypeOid); - values[Anum_pg_range_rngsubtype - 1] = ObjectIdGetDatum(rangeSubType); - values[Anum_pg_range_rngcollation - 1] = ObjectIdGetDatum(rangeCollation); - values[Anum_pg_range_rngsubopc - 1] = ObjectIdGetDatum(rangeSubOpclass); - values[Anum_pg_range_rngcanonical - 1] = ObjectIdGetDatum(rangeCanonical); - values[Anum_pg_range_rngsubdiff - 1] = ObjectIdGetDatum(rangeSubDiff); - values[Anum_pg_range_rngmultitypid - 1] = ObjectIdGetDatum(multirangeTypeOid); + HeapTupleSetValue(pg_range, rngtypid, ObjectIdGetDatum(rangeTypeOid), values); + HeapTupleSetValue(pg_range, rngsubtype, ObjectIdGetDatum(rangeSubType), values); + HeapTupleSetValue(pg_range, rngcollation, ObjectIdGetDatum(rangeCollation), values); + HeapTupleSetValue(pg_range, rngsubopc, ObjectIdGetDatum(rangeSubOpclass), values); + HeapTupleSetValue(pg_range, rngcanonical, ObjectIdGetDatum(rangeCanonical), values); + HeapTupleSetValue(pg_range, rngsubdiff, ObjectIdGetDatum(rangeSubDiff), values); + HeapTupleSetValue(pg_range, rngmultitypid, ObjectIdGetDatum(multirangeTypeOid), values); tup = heap_form_tuple(RelationGetDescr(pg_range), values, nulls); - CatalogTupleInsert(pg_range, tup); + CatalogTupleInsert(pg_range, tup, NULL); heap_freetuple(tup); /* record type's dependencies on range-related items */ diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c index 16e3e5c7457..750f0d69e57 100644 --- a/src/backend/catalog/pg_shdepend.c +++ b/src/backend/catalog/pg_shdepend.c @@ -273,31 +273,31 @@ shdepChangeDep(Relation sdepRel, shForm->refclassid = refclassid; shForm->refobjid = refobjid; - CatalogTupleUpdate(sdepRel, &oldtup->t_self, oldtup); + CatalogTupleUpdate(sdepRel, &oldtup->t_self, oldtup, NULL, NULL); } else { /* Need to insert new entry */ - Datum values[Natts_pg_shdepend]; - bool nulls[Natts_pg_shdepend]; + Datum values[Natts_pg_shdepend] = {0}; + bool nulls[Natts_pg_shdepend] = {false}; memset(nulls, false, sizeof(nulls)); - values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(dbid); - values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classid); - values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objid); - values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubid); + HeapTupleSetValue(pg_shdepend, dbid, ObjectIdGetDatum(dbid), values); + HeapTupleSetValue(pg_shdepend, classid, ObjectIdGetDatum(classid), values); + HeapTupleSetValue(pg_shdepend, objid, ObjectIdGetDatum(objid), values); + HeapTupleSetValue(pg_shdepend, objsubid, Int32GetDatum(objsubid), values); - values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassid); - values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjid); - values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype); + HeapTupleSetValue(pg_shdepend, refclassid, ObjectIdGetDatum(refclassid), values); + HeapTupleSetValue(pg_shdepend, refobjid, ObjectIdGetDatum(refobjid), values); + HeapTupleSetValue(pg_shdepend, deptype, CharGetDatum(deptype), values); /* * we are reusing oldtup just to avoid declaring a new variable, but * it's certainly a new tuple */ oldtup = heap_form_tuple(RelationGetDescr(sdepRel), values, nulls); - CatalogTupleInsert(sdepRel, oldtup); + CatalogTupleInsert(sdepRel, oldtup, NULL); } if (oldtup) @@ -955,13 +955,13 @@ copyTemplateDependencies(Oid templateDbId, Oid newDbId) shdep = (Form_pg_shdepend) GETSTRUCT(tup); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(newDbId); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(shdep->classid); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(shdep->objid); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(shdep->objsubid); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(shdep->refclassid); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(shdep->refobjid); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(shdep->deptype); + HeapTupleSetValue(pg_shdepend, dbid, ObjectIdGetDatum(newDbId), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, classid, ObjectIdGetDatum(shdep->classid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, objid, ObjectIdGetDatum(shdep->objid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, objsubid, Int32GetDatum(shdep->objsubid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, refclassid, ObjectIdGetDatum(shdep->refclassid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, refobjid, ObjectIdGetDatum(shdep->refobjid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, deptype, CharGetDatum(shdep->deptype), slot[slot_stored_count]->tts_values); ExecStoreVirtualTuple(slot[slot_stored_count]); slot_stored_count++; @@ -969,14 +969,14 @@ copyTemplateDependencies(Oid templateDbId, Oid newDbId) /* If slots are full, insert a batch of tuples */ if (slot_stored_count == max_slots) { - CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate); + CatalogTuplesMultiInsert(sdepRel, slot, slot_stored_count, indstate); slot_stored_count = 0; } } /* Insert any tuples left in the buffer */ if (slot_stored_count > 0) - CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate); + CatalogTuplesMultiInsert(sdepRel, slot, slot_stored_count, indstate); systable_endscan(scan); @@ -1072,8 +1072,8 @@ shdepAddDependency(Relation sdepRel, SharedDependencyType deptype) { HeapTuple tup; - Datum values[Natts_pg_shdepend]; - bool nulls[Natts_pg_shdepend]; + Datum values[Natts_pg_shdepend] = {0}; + bool nulls[Natts_pg_shdepend] = {false}; /* * Make sure the object doesn't go away while we record the dependency on @@ -1087,18 +1087,18 @@ shdepAddDependency(Relation sdepRel, /* * Form the new tuple and record the dependency. */ - values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(classIdGetDbId(classId)); - values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classId); - values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objectId); - values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubId); + HeapTupleSetValue(pg_shdepend, dbid, ObjectIdGetDatum(classIdGetDbId(classId)), values); + HeapTupleSetValue(pg_shdepend, classid, ObjectIdGetDatum(classId), values); + HeapTupleSetValue(pg_shdepend, objid, ObjectIdGetDatum(objectId), values); + HeapTupleSetValue(pg_shdepend, objsubid, Int32GetDatum(objsubId), values); - values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassId); - values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjId); - values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype); + HeapTupleSetValue(pg_shdepend, refclassid, ObjectIdGetDatum(refclassId), values); + HeapTupleSetValue(pg_shdepend, refobjid, ObjectIdGetDatum(refobjId), values); + HeapTupleSetValue(pg_shdepend, deptype, CharGetDatum(deptype), values); tup = heap_form_tuple(sdepRel->rd_att, values, nulls); - CatalogTupleInsert(sdepRel, tup); + CatalogTupleInsert(sdepRel, tup, NULL); /* clean up */ heap_freetuple(tup); diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c index 180e77e9484..59765a8cea0 100644 --- a/src/backend/catalog/pg_subscription.c +++ b/src/backend/catalog/pg_subscription.c @@ -203,9 +203,9 @@ void DisableSubscription(Oid subid) { Relation rel; - bool nulls[Natts_pg_subscription]; - bool replaces[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; + Datum values[Natts_pg_subscription] = {0}; + bool nulls[Natts_pg_subscription] = {false}; + Bitmapset *updated = NULL; HeapTuple tup; /* Look up the subscription in the catalog */ @@ -217,19 +217,13 @@ DisableSubscription(Oid subid) LockSharedObject(SubscriptionRelationId, subid, 0, AccessShareLock); - /* Form a new tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - /* Set the subscription to disabled. */ - values[Anum_pg_subscription_subenabled - 1] = BoolGetDatum(false); - replaces[Anum_pg_subscription_subenabled - 1] = true; + HeapTupleUpdateValue(pg_subscription, subenabled, BoolGetDatum(false), values, nulls, updated); /* Update the catalog */ - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + bms_free(updated); heap_freetuple(tup); table_close(rel, NoLock); @@ -272,8 +266,8 @@ AddSubscriptionRelState(Oid subid, Oid relid, char state, { Relation rel; HeapTuple tup; - bool nulls[Natts_pg_subscription_rel]; - Datum values[Natts_pg_subscription_rel]; + Datum values[Natts_pg_subscription_rel] = {0}; + bool nulls[Natts_pg_subscription_rel] = {false}; LockSharedObject(SubscriptionRelationId, subid, 0, AccessShareLock); @@ -288,20 +282,18 @@ AddSubscriptionRelState(Oid subid, Oid relid, char state, relid, subid); /* Form the tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - values[Anum_pg_subscription_rel_srsubid - 1] = ObjectIdGetDatum(subid); - values[Anum_pg_subscription_rel_srrelid - 1] = ObjectIdGetDatum(relid); - values[Anum_pg_subscription_rel_srsubstate - 1] = CharGetDatum(state); + HeapTupleSetValue(pg_subscription_rel, srsubid, ObjectIdGetDatum(subid), values); + HeapTupleSetValue(pg_subscription_rel, srrelid, ObjectIdGetDatum(relid), values); + HeapTupleSetValue(pg_subscription_rel, srsubstate, CharGetDatum(state), values); if (XLogRecPtrIsValid(sublsn)) - values[Anum_pg_subscription_rel_srsublsn - 1] = LSNGetDatum(sublsn); + HeapTupleSetValue(pg_subscription_rel, srsublsn, LSNGetDatum(sublsn), values); else - nulls[Anum_pg_subscription_rel_srsublsn - 1] = true; + HeapTupleSetValueNull(pg_subscription_rel, srsublsn, values, nulls); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); /* Insert tuple into catalog. */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); @@ -326,9 +318,9 @@ UpdateSubscriptionRelState(Oid subid, Oid relid, char state, { Relation rel; HeapTuple tup; - bool nulls[Natts_pg_subscription_rel]; - Datum values[Natts_pg_subscription_rel]; - bool replaces[Natts_pg_subscription_rel]; + Datum values[Natts_pg_subscription_rel] = {0}; + bool nulls[Natts_pg_subscription_rel] = {false}; + Bitmapset *updated = NULL; if (already_locked) { @@ -358,27 +350,21 @@ UpdateSubscriptionRelState(Oid subid, Oid relid, char state, relid, subid); /* Update the tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - - replaces[Anum_pg_subscription_rel_srsubstate - 1] = true; - values[Anum_pg_subscription_rel_srsubstate - 1] = CharGetDatum(state); + HeapTupleUpdateValue(pg_subscription_rel, srsubstate, CharGetDatum(state), values, nulls, updated); - replaces[Anum_pg_subscription_rel_srsublsn - 1] = true; if (XLogRecPtrIsValid(sublsn)) - values[Anum_pg_subscription_rel_srsublsn - 1] = LSNGetDatum(sublsn); + HeapTupleUpdateValue(pg_subscription_rel, srsublsn, LSNGetDatum(sublsn), values, nulls, updated); else - nulls[Anum_pg_subscription_rel_srsublsn - 1] = true; + HeapTupleUpdateValueNull(pg_subscription_rel, srsublsn, values, nulls, updated); - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); /* Update the catalog. */ - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); /* Cleanup. */ table_close(rel, NoLock); + bms_free(updated); } /* @@ -645,9 +631,9 @@ void UpdateDeadTupleRetentionStatus(Oid subid, bool active) { Relation rel; - bool nulls[Natts_pg_subscription]; - bool replaces[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; + Datum values[Natts_pg_subscription] = {0}; + bool nulls[Natts_pg_subscription] = {false}; + Bitmapset *updated = NULL; HeapTuple tup; /* Look up the subscription in the catalog */ @@ -659,20 +645,16 @@ UpdateDeadTupleRetentionStatus(Oid subid, bool active) LockSharedObject(SubscriptionRelationId, subid, 0, AccessShareLock); - /* Form a new tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - /* Set the subscription to disabled. */ - values[Anum_pg_subscription_subretentionactive - 1] = active; - replaces[Anum_pg_subscription_subretentionactive - 1] = true; + HeapTupleUpdateValue(pg_subscription, subretentionactive, active, values, nulls, updated); /* Update the catalog */ - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); - heap_freetuple(tup); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + + /* Cleanup */ + bms_free(updated); + heap_freetuple(tup); table_close(rel, NoLock); } diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 257c7da8568..6342f9aad07 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -60,8 +60,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) TupleDesc tupDesc; int i; HeapTuple tup; - Datum values[Natts_pg_type]; - bool nulls[Natts_pg_type]; + Datum values[Natts_pg_type] = {0}; + bool nulls[Natts_pg_type] = {false}; Oid typoid; NameData name; ObjectAddress address; @@ -92,37 +92,37 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) * mistaken for a usable type. */ namestrcpy(&name, typeName); - values[Anum_pg_type_typname - 1] = NameGetDatum(&name); - values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace); - values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId); - values[Anum_pg_type_typlen - 1] = Int16GetDatum(sizeof(int32)); - values[Anum_pg_type_typbyval - 1] = BoolGetDatum(true); - values[Anum_pg_type_typtype - 1] = CharGetDatum(TYPTYPE_PSEUDO); - values[Anum_pg_type_typcategory - 1] = CharGetDatum(TYPCATEGORY_PSEUDOTYPE); - values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(false); - values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(false); - values[Anum_pg_type_typdelim - 1] = CharGetDatum(DEFAULT_TYPDELIM); - values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(F_SHELL_IN); - values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(F_SHELL_OUT); - values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typalign - 1] = CharGetDatum(TYPALIGN_INT); - values[Anum_pg_type_typstorage - 1] = CharGetDatum(TYPSTORAGE_PLAIN); - values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(false); - values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1); - values[Anum_pg_type_typndims - 1] = Int32GetDatum(0); - values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid); - nulls[Anum_pg_type_typdefaultbin - 1] = true; - nulls[Anum_pg_type_typdefault - 1] = true; - nulls[Anum_pg_type_typacl - 1] = true; + HeapTupleSetValue(pg_type, typname, NameGetDatum(&name), values); + HeapTupleSetValue(pg_type, typnamespace, ObjectIdGetDatum(typeNamespace), values); + HeapTupleSetValue(pg_type, typowner, ObjectIdGetDatum(ownerId), values); + HeapTupleSetValue(pg_type, typlen, Int16GetDatum(sizeof(int32)), values); + HeapTupleSetValue(pg_type, typbyval, BoolGetDatum(true), values); + HeapTupleSetValue(pg_type, typtype, CharGetDatum(TYPTYPE_PSEUDO), values); + HeapTupleSetValue(pg_type, typcategory, CharGetDatum(TYPCATEGORY_PSEUDOTYPE), values); + HeapTupleSetValue(pg_type, typispreferred, BoolGetDatum(false), values); + HeapTupleSetValue(pg_type, typisdefined, BoolGetDatum(false), values); + HeapTupleSetValue(pg_type, typdelim, CharGetDatum(DEFAULT_TYPDELIM), values); + HeapTupleSetValue(pg_type, typrelid, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typsubscript, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typelem, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typarray, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typinput, ObjectIdGetDatum(F_SHELL_IN), values); + HeapTupleSetValue(pg_type, typoutput, ObjectIdGetDatum(F_SHELL_OUT), values); + HeapTupleSetValue(pg_type, typreceive, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typsend, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typmodin, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typmodout, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typanalyze, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typalign, CharGetDatum(TYPALIGN_INT), values); + HeapTupleSetValue(pg_type, typstorage, CharGetDatum(TYPSTORAGE_PLAIN), values); + HeapTupleSetValue(pg_type, typnotnull, BoolGetDatum(false), values); + HeapTupleSetValue(pg_type, typbasetype, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typtypmod, Int32GetDatum(-1), values); + HeapTupleSetValue(pg_type, typndims, Int32GetDatum(0), values); + HeapTupleSetValue(pg_type, typcollation, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValueNull(pg_type, typdefaultbin, values, nulls); + HeapTupleSetValueNull(pg_type, typdefault, values, nulls); + HeapTupleSetValueNull(pg_type, typacl, values, nulls); /* Use binary-upgrade override for pg_type.oid? */ if (IsBinaryUpgrade) @@ -141,7 +141,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) Anum_pg_type_oid); } - values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typoid); + HeapTupleSetValue(pg_type, oid, ObjectIdGetDatum(typoid), values); /* * create a new type tuple @@ -151,7 +151,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) /* * insert the tuple in the relation and get the tuple's oid. */ - CatalogTupleInsert(pg_type_desc, tup); + CatalogTupleInsert(pg_type_desc, tup, NULL); /* * Create dependencies. We can/must skip this in bootstrap mode. @@ -229,13 +229,12 @@ TypeCreate(Oid newTypeOid, Oid typeObjectId; bool isDependentType; bool rebuildDeps = false; - Acl *typacl; + Acl *typacl = NULL; HeapTuple tup; - bool nulls[Natts_pg_type]; - bool replaces[Natts_pg_type]; - Datum values[Natts_pg_type]; + Datum values[Natts_pg_type] = {0}; + bool nulls[Natts_pg_type] = {false}; + Bitmapset *updated = NULL; NameData name; - int i; ObjectAddress address; /* @@ -334,78 +333,65 @@ TypeCreate(Oid newTypeOid, typeType == TYPTYPE_MULTIRANGE || (OidIsValid(relationOid) && relationKind != RELKIND_COMPOSITE_TYPE); - /* - * initialize arrays needed for heap_form_tuple or heap_modify_tuple - */ - for (i = 0; i < Natts_pg_type; ++i) - { - nulls[i] = false; - replaces[i] = true; - values[i] = (Datum) 0; - } + HeapTupleUpdateSetAllColumnsUpdated(pg_type, updated); - /* - * insert data values - */ + /* Insert data values */ namestrcpy(&name, typeName); - values[Anum_pg_type_typname - 1] = NameGetDatum(&name); - values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace); - values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId); - values[Anum_pg_type_typlen - 1] = Int16GetDatum(internalSize); - values[Anum_pg_type_typbyval - 1] = BoolGetDatum(passedByValue); - values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType); - values[Anum_pg_type_typcategory - 1] = CharGetDatum(typeCategory); - values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(typePreferred); - values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(true); - values[Anum_pg_type_typdelim - 1] = CharGetDatum(typDelim); - values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(relationOid); - values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(subscriptProcedure); - values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(elementType); - values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(arrayType); - values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(inputProcedure); - values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(outputProcedure); - values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(receiveProcedure); - values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(sendProcedure); - values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(typmodinProcedure); - values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(typmodoutProcedure); - values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(analyzeProcedure); - values[Anum_pg_type_typalign - 1] = CharGetDatum(alignment); - values[Anum_pg_type_typstorage - 1] = CharGetDatum(storage); - values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(typeNotNull); - values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(baseType); - values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(typeMod); - values[Anum_pg_type_typndims - 1] = Int32GetDatum(typNDims); - values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(typeCollation); + HeapTupleUpdateValue(pg_type, typname, NameGetDatum(&name), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typnamespace, ObjectIdGetDatum(typeNamespace), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typowner, ObjectIdGetDatum(ownerId), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typlen, Int16GetDatum(internalSize), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typbyval, BoolGetDatum(passedByValue), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typtype, CharGetDatum(typeType), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typcategory, CharGetDatum(typeCategory), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typispreferred, BoolGetDatum(typePreferred), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typisdefined, BoolGetDatum(true), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typdelim, CharGetDatum(typDelim), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typrelid, ObjectIdGetDatum(relationOid), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typsubscript, ObjectIdGetDatum(subscriptProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typelem, ObjectIdGetDatum(elementType), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typarray, ObjectIdGetDatum(arrayType), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typinput, ObjectIdGetDatum(inputProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typoutput, ObjectIdGetDatum(outputProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typreceive, ObjectIdGetDatum(receiveProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typsend, ObjectIdGetDatum(sendProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typmodin, ObjectIdGetDatum(typmodinProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typmodout, ObjectIdGetDatum(typmodoutProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typanalyze, ObjectIdGetDatum(analyzeProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typalign, CharGetDatum(alignment), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typstorage, CharGetDatum(storage), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typnotnull, BoolGetDatum(typeNotNull), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typbasetype, ObjectIdGetDatum(baseType), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typtypmod, Int32GetDatum(typeMod), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typndims, Int32GetDatum(typNDims), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typcollation, ObjectIdGetDatum(typeCollation), values, nulls, updated); /* - * initialize the default binary value for this type. Check for nulls of - * course. + * Initialize the default binary value for this type. */ if (defaultTypeBin) - values[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(defaultTypeBin); + HeapTupleUpdateValue(pg_type, typdefaultbin, CStringGetTextDatum(defaultTypeBin), values, nulls, updated); else - nulls[Anum_pg_type_typdefaultbin - 1] = true; + HeapTupleUpdateValueNull(pg_type, typdefaultbin, values, nulls, updated); /* - * initialize the default value for this type. + * Initialize the default value for this type. */ if (defaultTypeValue) - values[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultTypeValue); + HeapTupleUpdateValue(pg_type, typdefault, CStringGetTextDatum(defaultTypeValue), values, nulls, updated); else - nulls[Anum_pg_type_typdefault - 1] = true; + HeapTupleUpdateValueNull(pg_type, typdefault, values, nulls, updated); /* - * Initialize the type's ACL, too. But dependent types don't get one. + * Initialize the type's ACL too, but dependent types don't get one. */ - if (isDependentType) - typacl = NULL; - else - typacl = get_user_default_acl(OBJECT_TYPE, ownerId, - typeNamespace); + if (!isDependentType) + typacl = get_user_default_acl(OBJECT_TYPE, ownerId, typeNamespace); + if (typacl != NULL) - values[Anum_pg_type_typacl - 1] = PointerGetDatum(typacl); + HeapTupleUpdateValue(pg_type, typacl, PointerGetDatum(typacl), values, nulls, updated); else - nulls[Anum_pg_type_typacl - 1] = true; + HeapTupleUpdateValueNull(pg_type, typacl, values, nulls, updated); /* * open pg_type and prepare to insert or update a row. @@ -431,9 +417,7 @@ TypeCreate(Oid newTypeOid, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("type \"%s\" already exists", typeName))); - /* - * shell type must have been created by same owner - */ + /* Shell type must have been created by same owner */ if (typform->typowner != ownerId) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TYPE, typeName); @@ -441,18 +425,16 @@ TypeCreate(Oid newTypeOid, if (OidIsValid(newTypeOid)) elog(ERROR, "cannot assign new OID to existing shell type"); - replaces[Anum_pg_type_oid - 1] = false; + HeapTupleSetColumnNotUpdated(pg_type, oid, updated); - /* - * Okay to update existing shell type tuple - */ - tup = heap_modify_tuple(tup, + /* Okay to update existing shell type tuple */ + tup = heap_update_tuple(tup, RelationGetDescr(pg_type_desc), values, nulls, - replaces); + updated); - CatalogTupleUpdate(pg_type_desc, &tup->t_self, tup); + CatalogTupleUpdate(pg_type_desc, &tup->t_self, tup, updated, NULL); typeObjectId = typform->oid; @@ -480,12 +462,11 @@ TypeCreate(Oid newTypeOid, Anum_pg_type_oid); } - values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typeObjectId); + HeapTupleUpdateValue(pg_type, oid, ObjectIdGetDatum(typeObjectId), values, nulls, updated); - tup = heap_form_tuple(RelationGetDescr(pg_type_desc), - values, nulls); + tup = heap_form_tuple(RelationGetDescr(pg_type_desc), values, nulls); - CatalogTupleInsert(pg_type_desc, tup); + CatalogTupleInsert(pg_type_desc, tup, NULL); } /* @@ -509,9 +490,8 @@ TypeCreate(Oid newTypeOid, ObjectAddressSet(address, TypeRelationId, typeObjectId); - /* - * finish up - */ + /* Clean up */ + bms_free(updated); table_close(pg_type_desc, RowExclusiveLock); return address; @@ -765,6 +745,7 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace) Relation pg_type_desc; HeapTuple tuple; Form_pg_type typ; + Bitmapset *updated = NULL; Oid arrayOid; Oid oldTypeOid; @@ -804,12 +785,14 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace) } /* OK, do the rename --- tuple is a copy, so OK to scribble on it */ - namestrcpy(&(typ->typname), newTypeName); + namestrcpy(&typ->typname, newTypeName); + HeapTupleMarkColumnUpdated(pg_type, typname, updated); - CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple); + CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0); + bms_free(updated); heap_freetuple(tuple); table_close(pg_type_desc, RowExclusiveLock); diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c index 874a8fc89ad..368f8e63b0b 100644 --- a/src/backend/catalog/toasting.c +++ b/src/backend/catalog/toasting.c @@ -336,14 +336,17 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, if (!IsBootstrapProcessingMode()) { + Bitmapset *updated = NULL; + /* normal case, use a transactional update */ reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid)); if (!HeapTupleIsValid(reltup)) elog(ERROR, "cache lookup failed for relation %u", relOid); - ((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid = toast_relid; + HeapTupleUpdateField(pg_class, reltoastrelid, toast_relid, (Form_pg_class) GETSTRUCT(reltup), updated); + CatalogTupleUpdate(class_rel, &reltup->t_self, reltup, updated, NULL); - CatalogTupleUpdate(class_rel, &reltup->t_self, reltup); + bms_free(updated); } else { diff --git a/src/backend/commands/amcmds.c b/src/backend/commands/amcmds.c index 58ed9d216cc..2dca9051fa6 100644 --- a/src/backend/commands/amcmds.c +++ b/src/backend/commands/amcmds.c @@ -47,8 +47,8 @@ CreateAccessMethod(CreateAmStmt *stmt) ObjectAddress referenced; Oid amoid; Oid amhandler; - bool nulls[Natts_pg_am]; - Datum values[Natts_pg_am]; + Datum values[Natts_pg_am] = {0}; + bool nulls[Natts_pg_am] = {false}; HeapTuple tup; rel = table_open(AccessMethodRelationId, RowExclusiveLock); @@ -84,15 +84,14 @@ CreateAccessMethod(CreateAmStmt *stmt) memset(nulls, false, sizeof(nulls)); amoid = GetNewOidWithIndex(rel, AmOidIndexId, Anum_pg_am_oid); - values[Anum_pg_am_oid - 1] = ObjectIdGetDatum(amoid); - values[Anum_pg_am_amname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->amname)); - values[Anum_pg_am_amhandler - 1] = ObjectIdGetDatum(amhandler); - values[Anum_pg_am_amtype - 1] = CharGetDatum(stmt->amtype); + HeapTupleSetValue(pg_am, oid, ObjectIdGetDatum(amoid), values); + HeapTupleSetValue(pg_am, amname, DirectFunctionCall1(namein, CStringGetDatum(stmt->amname)), values); + HeapTupleSetValue(pg_am, amhandler, ObjectIdGetDatum(amhandler), values); + HeapTupleSetValue(pg_am, amtype, CharGetDatum(stmt->amtype), values); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); myself.classId = AccessMethodRelationId; diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index b55221d44cd..b596821e348 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -557,6 +557,7 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal) Form_pg_index indexForm; Relation pg_index; ListCell *index; + Bitmapset *updated = NULL; /* Disallow applying to a partitioned table */ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) @@ -594,16 +595,16 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal) */ if (indexForm->indisclustered) { - indexForm->indisclustered = false; - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + HeapTupleUpdateField(pg_index, indisclustered, false, indexForm, updated); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); } else if (thisIndexOid == indexOid) { /* this was checked earlier, but let's be real sure */ if (!indexForm->indisvalid) elog(ERROR, "cannot cluster on invalid index %u", indexOid); - indexForm->indisclustered = true; - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + HeapTupleUpdateField(pg_index, indisclustered, true, indexForm, updated); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); } InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0, @@ -613,6 +614,7 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal) } table_close(pg_index, RowExclusiveLock); + bms_free(updated); } /* @@ -847,6 +849,7 @@ copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verb int elevel = verbose ? INFO : DEBUG2; PGRUsage ru0; char *nspname; + Bitmapset *updated = NULL; pg_rusage_init(&ru0); @@ -1016,18 +1019,19 @@ copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verb RelationGetRelid(NewHeap)); relform = (Form_pg_class) GETSTRUCT(reltup); - relform->relpages = num_pages; - relform->reltuples = num_tuples; + HeapTupleUpdateField(pg_class, relpages, num_pages, relform, updated); + HeapTupleUpdateField(pg_class, reltuples, num_tuples, relform, updated); /* Don't update the stats for pg_class. See swap_relation_files. */ if (RelationGetRelid(OldHeap) != RelationRelationId) - CatalogTupleUpdate(relRelation, &reltup->t_self, reltup); + CatalogTupleUpdate(relRelation, &reltup->t_self, reltup, updated, NULL); else CacheInvalidateRelcacheByTuple(reltup); /* Clean up. */ heap_freetuple(reltup); table_close(relRelation, RowExclusiveLock); + bms_free(updated); /* Make the update visible */ CommandCounterIncrement(); @@ -1078,6 +1082,8 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, char swptmpchr; Oid relam1, relam2; + Bitmapset *updated1 = NULL; + Bitmapset *updated2 = NULL; /* We need writable copies of both pg_class tuples. */ relRelation = table_open(RelationRelationId, RowExclusiveLock); @@ -1107,27 +1113,27 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, Assert(!target_is_pg_class); swaptemp = relform1->relfilenode; - relform1->relfilenode = relform2->relfilenode; - relform2->relfilenode = swaptemp; + HeapTupleUpdateField(pg_class, relfilenode, relform2->relfilenode, relform1, updated1); + HeapTupleUpdateField(pg_class, relfilenode, swaptemp, relform2, updated2); swaptemp = relform1->reltablespace; - relform1->reltablespace = relform2->reltablespace; - relform2->reltablespace = swaptemp; + HeapTupleUpdateField(pg_class, reltablespace, relform2->reltablespace, relform1, updated1); + HeapTupleUpdateField(pg_class, reltablespace, swaptemp, relform2, updated2); swaptemp = relform1->relam; - relform1->relam = relform2->relam; - relform2->relam = swaptemp; + HeapTupleUpdateField(pg_class, relam, relform2->relam, relform1, updated1); + HeapTupleUpdateField(pg_class, relam, swaptemp, relform2, updated2); swptmpchr = relform1->relpersistence; - relform1->relpersistence = relform2->relpersistence; - relform2->relpersistence = swptmpchr; + HeapTupleUpdateField(pg_class, relpersistence, relform2->relpersistence, relform1, updated1); + HeapTupleUpdateField(pg_class, relpersistence, swptmpchr, relform2, updated2); /* Also swap toast links, if we're swapping by links */ if (!swap_toast_by_content) { swaptemp = relform1->reltoastrelid; - relform1->reltoastrelid = relform2->reltoastrelid; - relform2->reltoastrelid = swaptemp; + HeapTupleUpdateField(pg_class, reltoastrelid, relform2->reltoastrelid, relform1, updated1); + HeapTupleUpdateField(pg_class, reltoastrelid, swaptemp, relform2, updated2); } } else @@ -1217,8 +1223,8 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, { Assert(!TransactionIdIsValid(frozenXid) || TransactionIdIsNormal(frozenXid)); - relform1->relfrozenxid = frozenXid; - relform1->relminmxid = cutoffMulti; + HeapTupleUpdateField(pg_class, relfrozenxid, frozenXid, relform1, updated1); + HeapTupleUpdateField(pg_class, relminmxid, cutoffMulti, relform1, updated1); } /* swap size statistics too, since new rel has freshly-updated stats */ @@ -1229,20 +1235,20 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, int32 swap_allfrozen; swap_pages = relform1->relpages; - relform1->relpages = relform2->relpages; - relform2->relpages = swap_pages; + HeapTupleUpdateField(pg_class, relpages, relform2->relpages, relform1, updated1); + HeapTupleUpdateField(pg_class, relpages, swap_pages, relform2, updated2); swap_tuples = relform1->reltuples; - relform1->reltuples = relform2->reltuples; - relform2->reltuples = swap_tuples; + HeapTupleUpdateField(pg_class, reltuples, relform2->reltuples, relform1, updated1); + HeapTupleUpdateField(pg_class, reltuples, swap_tuples, relform2, updated2); swap_allvisible = relform1->relallvisible; - relform1->relallvisible = relform2->relallvisible; - relform2->relallvisible = swap_allvisible; + HeapTupleUpdateField(pg_class, relallvisible, relform2->relallvisible, relform1, updated1); + HeapTupleUpdateField(pg_class, relallvisible, swap_allvisible, relform2, updated2); swap_allfrozen = relform1->relallfrozen; - relform1->relallfrozen = relform2->relallfrozen; - relform2->relallfrozen = swap_allfrozen; + HeapTupleUpdateField(pg_class, relallfrozen, relform2->relallfrozen, relform1, updated1); + HeapTupleUpdateField(pg_class, relallfrozen, swap_allfrozen, relform2, updated2); } /* @@ -1256,13 +1262,11 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, */ if (!target_is_pg_class) { - CatalogIndexState indstate; + CatalogIndexState indstate = CatalogOpenIndexes(relRelation); + + CatalogTupleUpdate(relRelation, &reltup1->t_self, reltup1, updated1, indstate); + CatalogTupleUpdate(relRelation, &reltup2->t_self, reltup2, updated2, indstate); - indstate = CatalogOpenIndexes(relRelation); - CatalogTupleUpdateWithInfo(relRelation, &reltup1->t_self, reltup1, - indstate); - CatalogTupleUpdateWithInfo(relRelation, &reltup2->t_self, reltup2, - indstate); CatalogCloseIndexes(indstate); } else @@ -1435,6 +1439,8 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, heap_freetuple(reltup2); table_close(relRelation, RowExclusiveLock); + bms_free(updated1); + bms_free(updated2); } /* @@ -1535,6 +1541,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, Relation relRelation; HeapTuple reltup; Form_pg_class relform; + Bitmapset *updated = NULL; relRelation = table_open(RelationRelationId, RowExclusiveLock); @@ -1543,12 +1550,13 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, elog(ERROR, "cache lookup failed for relation %u", OIDOldHeap); relform = (Form_pg_class) GETSTRUCT(reltup); - relform->relfrozenxid = frozenXid; - relform->relminmxid = cutoffMulti; + HeapTupleUpdateField(pg_class, relfrozenxid, frozenXid, relform, updated); + HeapTupleUpdateField(pg_class, relminmxid, cutoffMulti, relform, updated); - CatalogTupleUpdate(relRelation, &reltup->t_self, reltup); + CatalogTupleUpdate(relRelation, &reltup->t_self, reltup, updated, NULL); table_close(relRelation, RowExclusiveLock); + bms_free(updated); } /* Destroy new heap with old filenumber */ diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c index 8acbfbbeda0..ccc6da41a40 100644 --- a/src/backend/commands/collationcmds.c +++ b/src/backend/commands/collationcmds.c @@ -427,6 +427,7 @@ AlterCollation(AlterCollationStmt *stmt) Oid collOid; HeapTuple tup; Form_pg_collation collForm; + Bitmapset *updated = NULL; Datum datum; bool isnull; char *oldversion; @@ -468,29 +469,22 @@ AlterCollation(AlterCollationStmt *stmt) elog(ERROR, "invalid collation version change"); else if (oldversion && newversion && strcmp(newversion, oldversion) != 0) { - bool nulls[Natts_pg_collation]; - bool replaces[Natts_pg_collation]; - Datum values[Natts_pg_collation]; + bool nulls[Natts_pg_collation] = {false}; + Datum values[Natts_pg_collation] = {0}; ereport(NOTICE, (errmsg("changing version from %s to %s", oldversion, newversion))); - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); + HeapTupleUpdateValue(pg_collation, collversion, CStringGetTextDatum(newversion), values, nulls, updated); - values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(newversion); - replaces[Anum_pg_collation_collversion - 1] = true; - - tup = heap_modify_tuple(tup, RelationGetDescr(rel), - values, nulls, replaces); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); } else ereport(NOTICE, (errmsg("version has not changed"))); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); InvokeObjectPostAlterHook(CollationRelationId, collOid, 0); @@ -498,6 +492,7 @@ AlterCollation(AlterCollationStmt *stmt) heap_freetuple(tup); table_close(rel, NoLock); + bms_free(updated); return address; } diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 5c783cc61f1..55f9ff3f3d4 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -147,10 +147,9 @@ CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment) SysScanDesc sd; HeapTuple oldtuple; HeapTuple newtuple = NULL; - Datum values[Natts_pg_description]; - bool nulls[Natts_pg_description]; - bool replaces[Natts_pg_description]; - int i; + Datum values[Natts_pg_description] = {0}; + bool nulls[Natts_pg_description] = {false}; + Bitmapset *updated = NULL; /* Reduce empty-string to NULL case */ if (comment != NULL && strlen(comment) == 0) @@ -159,15 +158,10 @@ CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment) /* Prepare to form or update a tuple, if necessary */ if (comment != NULL) { - for (i = 0; i < Natts_pg_description; i++) - { - nulls[i] = false; - replaces[i] = true; - } - values[Anum_pg_description_objoid - 1] = ObjectIdGetDatum(oid); - values[Anum_pg_description_classoid - 1] = ObjectIdGetDatum(classoid); - values[Anum_pg_description_objsubid - 1] = Int32GetDatum(subid); - values[Anum_pg_description_description - 1] = CStringGetTextDatum(comment); + HeapTupleUpdateValue(pg_description, objoid, ObjectIdGetDatum(oid), values, nulls, updated); + HeapTupleUpdateValue(pg_description, classoid, ObjectIdGetDatum(classoid), values, nulls, updated); + HeapTupleUpdateValue(pg_description, objsubid, Int32GetDatum(subid), values, nulls, updated); + HeapTupleUpdateValue(pg_description, description, CStringGetTextDatum(comment), values, nulls, updated); } /* Use the index to search for a matching old tuple */ @@ -198,9 +192,9 @@ CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment) CatalogTupleDelete(description, &oldtuple->t_self); else { - newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(description), values, - nulls, replaces); - CatalogTupleUpdate(description, &oldtuple->t_self, newtuple); + HeapTupleUpdateValue(pg_description, description, CStringGetTextDatum(comment), values, nulls, updated); + newtuple = heap_update_tuple(oldtuple, RelationGetDescr(description), values, nulls, updated); + CatalogTupleUpdate(description, &oldtuple->t_self, newtuple, updated, NULL); } break; /* Assume there can be only one match */ @@ -214,7 +208,7 @@ CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment) { newtuple = heap_form_tuple(RelationGetDescr(description), values, nulls); - CatalogTupleInsert(description, newtuple); + CatalogTupleInsert(description, newtuple, NULL); } if (newtuple != NULL) @@ -223,6 +217,7 @@ CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment) /* Done */ table_close(description, NoLock); + bms_free(updated); } /* @@ -242,9 +237,9 @@ CreateSharedComments(Oid oid, Oid classoid, const char *comment) SysScanDesc sd; HeapTuple oldtuple; HeapTuple newtuple = NULL; - Datum values[Natts_pg_shdescription]; - bool nulls[Natts_pg_shdescription]; - bool replaces[Natts_pg_shdescription]; + Datum values[Natts_pg_shdescription] = {0}; + bool nulls[Natts_pg_shdescription] = {false}; + Bitmapset *updated = NULL; int i; /* Reduce empty-string to NULL case */ @@ -257,11 +252,10 @@ CreateSharedComments(Oid oid, Oid classoid, const char *comment) for (i = 0; i < Natts_pg_shdescription; i++) { nulls[i] = false; - replaces[i] = true; } - values[Anum_pg_shdescription_objoid - 1] = ObjectIdGetDatum(oid); - values[Anum_pg_shdescription_classoid - 1] = ObjectIdGetDatum(classoid); - values[Anum_pg_shdescription_description - 1] = CStringGetTextDatum(comment); + HeapTupleUpdateValue(pg_shdescription, objoid, ObjectIdGetDatum(oid), values, nulls, updated); + HeapTupleUpdateValue(pg_shdescription, classoid, ObjectIdGetDatum(classoid), values, nulls, updated); + HeapTupleUpdateValue(pg_shdescription, description, CStringGetTextDatum(comment), values, nulls, updated); } /* Use the index to search for a matching old tuple */ @@ -288,9 +282,9 @@ CreateSharedComments(Oid oid, Oid classoid, const char *comment) CatalogTupleDelete(shdescription, &oldtuple->t_self); else { - newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(shdescription), - values, nulls, replaces); - CatalogTupleUpdate(shdescription, &oldtuple->t_self, newtuple); + HeapTupleUpdateValue(pg_shdescription, description, CStringGetTextDatum(comment), values, nulls, updated); + newtuple = heap_update_tuple(oldtuple, RelationGetDescr(shdescription), values, nulls, updated); + CatalogTupleUpdate(shdescription, &oldtuple->t_self, newtuple, updated, NULL); } break; /* Assume there can be only one match */ @@ -304,7 +298,7 @@ CreateSharedComments(Oid oid, Oid classoid, const char *comment) { newtuple = heap_form_tuple(RelationGetDescr(shdescription), values, nulls); - CatalogTupleInsert(shdescription, newtuple); + CatalogTupleInsert(shdescription, newtuple, NULL); } if (newtuple != NULL) @@ -313,6 +307,7 @@ CreateSharedComments(Oid oid, Oid classoid, const char *comment) /* Done */ table_close(shdescription, NoLock); + bms_free(updated); } /* diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 4d65e8c46c2..1784a38e13b 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -702,8 +702,8 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) volatile Oid dst_deftablespace; Relation pg_database_rel; HeapTuple tuple; - Datum new_record[Natts_pg_database] = {0}; - bool new_record_nulls[Natts_pg_database] = {0}; + Datum values[Natts_pg_database] = {0}; + bool nulls[Natts_pg_database] = {false}; Oid dboid = InvalidOid; Oid datdba; ListCell *option; @@ -1457,45 +1457,44 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) (dblocprovider == COLLPROVIDER_LIBC && !dblocale)); /* Form tuple */ - new_record[Anum_pg_database_oid - 1] = ObjectIdGetDatum(dboid); - new_record[Anum_pg_database_datname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(dbname)); - new_record[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(datdba); - new_record[Anum_pg_database_encoding - 1] = Int32GetDatum(encoding); - new_record[Anum_pg_database_datlocprovider - 1] = CharGetDatum(dblocprovider); - new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(dbistemplate); - new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(dballowconnections); - new_record[Anum_pg_database_dathasloginevt - 1] = BoolGetDatum(src_hasloginevt); - new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit); - new_record[Anum_pg_database_datfrozenxid - 1] = TransactionIdGetDatum(src_frozenxid); - new_record[Anum_pg_database_datminmxid - 1] = TransactionIdGetDatum(src_minmxid); - new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_deftablespace); - new_record[Anum_pg_database_datcollate - 1] = CStringGetTextDatum(dbcollate); - new_record[Anum_pg_database_datctype - 1] = CStringGetTextDatum(dbctype); + HeapTupleSetValue(pg_database, oid, ObjectIdGetDatum(dboid), values); + HeapTupleSetValue(pg_database, datname, DirectFunctionCall1(namein, CStringGetDatum(dbname)), values); + HeapTupleSetValue(pg_database, datdba, ObjectIdGetDatum(datdba), values); + HeapTupleSetValue(pg_database, encoding, Int32GetDatum(encoding), values); + HeapTupleSetValue(pg_database, datlocprovider, CharGetDatum(dblocprovider), values); + HeapTupleSetValue(pg_database, datistemplate, BoolGetDatum(dbistemplate), values); + HeapTupleSetValue(pg_database, datallowconn, BoolGetDatum(dballowconnections), values); + HeapTupleSetValue(pg_database, dathasloginevt, BoolGetDatum(src_hasloginevt), values); + HeapTupleSetValue(pg_database, datconnlimit, Int32GetDatum(dbconnlimit), values); + HeapTupleSetValue(pg_database, datfrozenxid, TransactionIdGetDatum(src_frozenxid), values); + HeapTupleSetValue(pg_database, datminmxid, TransactionIdGetDatum(src_minmxid), values); + HeapTupleSetValue(pg_database, dattablespace, ObjectIdGetDatum(dst_deftablespace), values); + HeapTupleSetValue(pg_database, datcollate, CStringGetTextDatum(dbcollate), values); + HeapTupleSetValue(pg_database, datctype, CStringGetTextDatum(dbctype), values); if (dblocale) - new_record[Anum_pg_database_datlocale - 1] = CStringGetTextDatum(dblocale); + HeapTupleSetValue(pg_database, datlocale, CStringGetTextDatum(dblocale), values); else - new_record_nulls[Anum_pg_database_datlocale - 1] = true; + HeapTupleSetValueNull(pg_database, datlocale, values, nulls); if (dbicurules) - new_record[Anum_pg_database_daticurules - 1] = CStringGetTextDatum(dbicurules); + HeapTupleSetValue(pg_database, daticurules, CStringGetTextDatum(dbicurules), values); else - new_record_nulls[Anum_pg_database_daticurules - 1] = true; + HeapTupleSetValueNull(pg_database, daticurules, values, nulls); if (dbcollversion) - new_record[Anum_pg_database_datcollversion - 1] = CStringGetTextDatum(dbcollversion); + HeapTupleSetValue(pg_database, datcollversion, CStringGetTextDatum(dbcollversion), values); else - new_record_nulls[Anum_pg_database_datcollversion - 1] = true; + HeapTupleSetValueNull(pg_database, datcollversion, values, nulls); /* * We deliberately set datacl to default (NULL), rather than copying it * from the template database. Copying it would be a bad idea when the * owner is not the same as the template's owner. */ - new_record_nulls[Anum_pg_database_datacl - 1] = true; + HeapTupleSetValueNull(pg_database, datacl, values, nulls); tuple = heap_form_tuple(RelationGetDescr(pg_database_rel), - new_record, new_record_nulls); + values, nulls); - CatalogTupleInsert(pg_database_rel, tuple); + CatalogTupleInsert(pg_database_rel, tuple, NULL); /* * Now generate additional catalog entries associated with the new DB @@ -1909,6 +1908,7 @@ RenameDatabase(const char *oldname, const char *newname) int notherbackends; int npreparedxacts; ObjectAddress address; + Bitmapset *updated = NULL; /* * Look up the target database's OID, and get exclusive lock on it. We @@ -1980,8 +1980,9 @@ RenameDatabase(const char *oldname, const char *newname) if (!HeapTupleIsValid(newtup)) elog(ERROR, "cache lookup failed for database %u", db_id); otid = newtup->t_self; - namestrcpy(&(((Form_pg_database) GETSTRUCT(newtup))->datname), newname); - CatalogTupleUpdate(rel, &otid, newtup); + namestrcpy(&((Form_pg_database) GETSTRUCT(newtup))->datname, newname); + HeapTupleMarkColumnUpdated(pg_database, datname, updated); + CatalogTupleUpdate(rel, &otid, newtup, updated, NULL); UnlockTuple(rel, &otid, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0); @@ -1992,6 +1993,7 @@ RenameDatabase(const char *oldname, const char *newname) * Close pg_database, but keep lock till commit. */ table_close(rel, NoLock); + bms_free(updated); return address; } @@ -2189,9 +2191,9 @@ movedb(const char *dbname, const char *tblspcname) PG_ENSURE_ERROR_CLEANUP(movedb_failure_callback, PointerGetDatum(&fparms)); { - Datum new_record[Natts_pg_database] = {0}; - bool new_record_nulls[Natts_pg_database] = {0}; - bool new_record_repl[Natts_pg_database] = {0}; + Datum values[Natts_pg_database] = {0}; + bool nulls[Natts_pg_database] = {false}; + Bitmapset *updated = NULL; /* * Copy files from the old tablespace to the new one @@ -2233,13 +2235,10 @@ movedb(const char *dbname, const char *tblspcname) errmsg("database \"%s\" does not exist", dbname))); LockTuple(pgdbrel, &oldtuple->t_self, InplaceUpdateTupleLock); - new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_tblspcoid); - new_record_repl[Anum_pg_database_dattablespace - 1] = true; + HeapTupleUpdateValue(pg_database, dattablespace, ObjectIdGetDatum(dst_tblspcoid), values, nulls, updated); - newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(pgdbrel), - new_record, - new_record_nulls, new_record_repl); - CatalogTupleUpdate(pgdbrel, &oldtuple->t_self, newtuple); + newtuple = heap_update_tuple(oldtuple, RelationGetDescr(pgdbrel), values, nulls, updated); + CatalogTupleUpdate(pgdbrel, &oldtuple->t_self, newtuple, updated, NULL); UnlockTuple(pgdbrel, &oldtuple->t_self, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0); @@ -2267,6 +2266,7 @@ movedb(const char *dbname, const char *tblspcname) * Close pg_database, but keep lock till commit. */ table_close(pgdbrel, NoLock); + bms_free(updated); } PG_END_ENSURE_ERROR_CLEANUP(movedb_failure_callback, PointerGetDatum(&fparms)); @@ -2382,9 +2382,9 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) DefElem *dallowconnections = NULL; DefElem *dconnlimit = NULL; DefElem *dtablespace = NULL; - Datum new_record[Natts_pg_database] = {0}; - bool new_record_nulls[Natts_pg_database] = {0}; - bool new_record_repl[Natts_pg_database] = {0}; + Datum values[Natts_pg_database] = {0}; + bool nulls[Natts_pg_database] = {false}; + Bitmapset *updated = NULL; /* Extract options from the statement node tree */ foreach(option, stmt->options) @@ -2503,24 +2503,16 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) * Build an updated tuple, perusing the information just obtained */ if (distemplate) - { - new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(dbistemplate); - new_record_repl[Anum_pg_database_datistemplate - 1] = true; - } + HeapTupleUpdateValue(pg_database, datistemplate, BoolGetDatum(dbistemplate), values, nulls, updated); + if (dallowconnections) - { - new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(dballowconnections); - new_record_repl[Anum_pg_database_datallowconn - 1] = true; - } + HeapTupleUpdateValue(pg_database, datallowconn, BoolGetDatum(dballowconnections), values, nulls, updated); + if (dconnlimit) - { - new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit); - new_record_repl[Anum_pg_database_datconnlimit - 1] = true; - } + HeapTupleUpdateValue(pg_database, datconnlimit, Int32GetDatum(dbconnlimit), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), new_record, - new_record_nulls, new_record_repl); - CatalogTupleUpdate(rel, &tuple->t_self, newtuple); + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &tuple->t_self, newtuple, updated, NULL); UnlockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(DatabaseRelationId, dboid, 0); @@ -2529,6 +2521,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) /* Close pg_database, but keep lock till commit */ table_close(rel, NoLock); + bms_free(updated); return dboid; } @@ -2597,22 +2590,21 @@ AlterDatabaseRefreshColl(AlterDatabaseRefreshCollStmt *stmt) elog(ERROR, "invalid collation version change"); else if (oldversion && newversion && strcmp(newversion, oldversion) != 0) { - bool nulls[Natts_pg_database] = {0}; - bool replaces[Natts_pg_database] = {0}; Datum values[Natts_pg_database] = {0}; + bool nulls[Natts_pg_database] = {false}; + Bitmapset *updated = NULL; HeapTuple newtuple; ereport(NOTICE, (errmsg("changing version from %s to %s", oldversion, newversion))); - values[Anum_pg_database_datcollversion - 1] = CStringGetTextDatum(newversion); - replaces[Anum_pg_database_datcollversion - 1] = true; + HeapTupleUpdateValue(pg_database, datcollversion, CStringGetTextDatum(newversion), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), - values, nulls, replaces); - CatalogTupleUpdate(rel, &tuple->t_self, newtuple); + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &tuple->t_self, newtuple, updated, NULL); heap_freetuple(newtuple); + bms_free(updated); } else ereport(NOTICE, @@ -2699,9 +2691,9 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId) */ if (datForm->datdba != newOwnerId) { - Datum repl_val[Natts_pg_database]; - bool repl_null[Natts_pg_database] = {0}; - bool repl_repl[Natts_pg_database] = {0}; + Datum values[Natts_pg_database] = {0}; + bool nulls[Natts_pg_database] = {false}; + Bitmapset *updated = NULL; Acl *newAcl; Datum aclDatum; bool isNull; @@ -2731,8 +2723,7 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId) LockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); - repl_repl[Anum_pg_database_datdba - 1] = true; - repl_val[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_database, datdba, ObjectIdGetDatum(newOwnerId), values, nulls, updated); /* * Determine the modified ACL for the new owner. This is only @@ -2746,18 +2737,18 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId) { newAcl = aclnewowner(DatumGetAclP(aclDatum), datForm->datdba, newOwnerId); - repl_repl[Anum_pg_database_datacl - 1] = true; - repl_val[Anum_pg_database_datacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_database, datacl, PointerGetDatum(newAcl), values, nulls, updated); } - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl); - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); UnlockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); heap_freetuple(newtuple); /* Update owner dependency reference */ changeDependencyOnOwner(DatabaseRelationId, db_id, newOwnerId); + bms_free(updated); } InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0); diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index f34868da5ab..5408e6d2760 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -280,8 +280,8 @@ insert_event_trigger_tuple(const char *trigname, const char *eventname, Oid evtO Relation tgrel; Oid trigoid; HeapTuple tuple; - Datum values[Natts_pg_event_trigger]; - bool nulls[Natts_pg_event_trigger]; + Datum values[Natts_pg_event_trigger] = {0}; + bool nulls[Natts_pg_event_trigger] = {false}; NameData evtnamedata, evteventdata; ObjectAddress myself, @@ -293,25 +293,23 @@ insert_event_trigger_tuple(const char *trigname, const char *eventname, Oid evtO /* Build the new pg_trigger tuple. */ trigoid = GetNewOidWithIndex(tgrel, EventTriggerOidIndexId, Anum_pg_event_trigger_oid); - values[Anum_pg_event_trigger_oid - 1] = ObjectIdGetDatum(trigoid); + HeapTupleSetValue(pg_event_trigger, oid, ObjectIdGetDatum(trigoid), values); memset(nulls, false, sizeof(nulls)); namestrcpy(&evtnamedata, trigname); - values[Anum_pg_event_trigger_evtname - 1] = NameGetDatum(&evtnamedata); + HeapTupleSetValue(pg_event_trigger, evtname, NameGetDatum(&evtnamedata), values); namestrcpy(&evteventdata, eventname); - values[Anum_pg_event_trigger_evtevent - 1] = NameGetDatum(&evteventdata); - values[Anum_pg_event_trigger_evtowner - 1] = ObjectIdGetDatum(evtOwner); - values[Anum_pg_event_trigger_evtfoid - 1] = ObjectIdGetDatum(funcoid); - values[Anum_pg_event_trigger_evtenabled - 1] = - CharGetDatum(TRIGGER_FIRES_ON_ORIGIN); + HeapTupleSetValue(pg_event_trigger, evtevent, NameGetDatum(&evteventdata), values); + HeapTupleSetValue(pg_event_trigger, evtowner, ObjectIdGetDatum(evtOwner), values); + HeapTupleSetValue(pg_event_trigger, evtfoid, ObjectIdGetDatum(funcoid), values); + HeapTupleSetValue(pg_event_trigger, evtenabled, CharGetDatum(TRIGGER_FIRES_ON_ORIGIN), values); if (taglist == NIL) - nulls[Anum_pg_event_trigger_evttags - 1] = true; + HeapTupleSetValueNull(pg_event_trigger, evttags, values, nulls); else - values[Anum_pg_event_trigger_evttags - 1] = - filter_list_to_array(taglist); + HeapTupleSetValue(pg_event_trigger, evttags, filter_list_to_array(taglist), values); /* Insert heap tuple. */ tuple = heap_form_tuple(tgrel->rd_att, values, nulls); - CatalogTupleInsert(tgrel, tuple); + CatalogTupleInsert(tgrel, tuple, NULL); heap_freetuple(tuple); /* @@ -394,6 +392,7 @@ SetDatabaseHasLoginEventTriggers(void) Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock); ItemPointerData otid; HeapTuple tuple; + Bitmapset *updated = NULL; /* * Use shared lock to prevent a conflict with EventTriggerOnLogin() trying @@ -411,8 +410,9 @@ SetDatabaseHasLoginEventTriggers(void) db = (Form_pg_database) GETSTRUCT(tuple); if (!db->dathasloginevt) { - db->dathasloginevt = true; - CatalogTupleUpdate(pg_db, &otid, tuple); + HeapTupleUpdateField(pg_database, dathasloginevt, true, db, updated); + CatalogTupleUpdate(pg_db, &otid, tuple, updated, NULL); + bms_free(updated); CommandCounterIncrement(); } UnlockTuple(pg_db, &otid, InplaceUpdateTupleLock); @@ -431,6 +431,7 @@ AlterEventTrigger(AlterEventTrigStmt *stmt) Oid trigoid; Form_pg_event_trigger evtForm; char tgenabled = stmt->tgenabled; + Bitmapset *updated = NULL; tgrel = table_open(EventTriggerRelationId, RowExclusiveLock); @@ -450,9 +451,10 @@ AlterEventTrigger(AlterEventTrigStmt *stmt) stmt->trigname); /* tuple is a copy, so we can modify it below */ - evtForm->evtenabled = tgenabled; + HeapTupleUpdateField(pg_event_trigger, evtenabled, tgenabled, evtForm, updated); - CatalogTupleUpdate(tgrel, &tup->t_self, tup); + CatalogTupleUpdate(tgrel, &tup->t_self, tup, updated, NULL); + bms_free(updated); /* * Login event triggers have an additional flag in pg_database to enable @@ -539,6 +541,7 @@ static void AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { Form_pg_event_trigger form; + Bitmapset *updated = NULL; form = (Form_pg_event_trigger) GETSTRUCT(tup); @@ -557,8 +560,9 @@ AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) NameStr(form->evtname)), errhint("The owner of an event trigger must be a superuser."))); - form->evtowner = newOwnerId; - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleUpdateField(pg_event_trigger, evtowner, newOwnerId, form, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + bms_free(updated); /* Update owner dependency reference */ changeDependencyOnOwner(EventTriggerRelationId, diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 93ef1ad106f..41ac7d2f994 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -2067,8 +2067,8 @@ InsertExtensionTuple(const char *extName, Oid extOwner, { Oid extensionOid; Relation rel; - Datum values[Natts_pg_extension]; - bool nulls[Natts_pg_extension]; + Datum values[Natts_pg_extension] = {0}; + bool nulls[Natts_pg_extension] = {false}; HeapTuple tuple; ObjectAddress myself; ObjectAddress nsp; @@ -2085,27 +2085,26 @@ InsertExtensionTuple(const char *extName, Oid extOwner, extensionOid = GetNewOidWithIndex(rel, ExtensionOidIndexId, Anum_pg_extension_oid); - values[Anum_pg_extension_oid - 1] = ObjectIdGetDatum(extensionOid); - values[Anum_pg_extension_extname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(extName)); - values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner); - values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid); - values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable); - values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion); + HeapTupleSetValue(pg_extension, oid, ObjectIdGetDatum(extensionOid), values); + HeapTupleSetValue(pg_extension, extname, DirectFunctionCall1(namein, CStringGetDatum(extName)), values); + HeapTupleSetValue(pg_extension, extowner, ObjectIdGetDatum(extOwner), values); + HeapTupleSetValue(pg_extension, extnamespace, ObjectIdGetDatum(schemaOid), values); + HeapTupleSetValue(pg_extension, extrelocatable, BoolGetDatum(relocatable), values); + HeapTupleSetValue(pg_extension, extversion, CStringGetTextDatum(extVersion), values); if (extConfig == PointerGetDatum(NULL)) - nulls[Anum_pg_extension_extconfig - 1] = true; + HeapTupleSetValueNull(pg_extension, extconfig, values, nulls); else - values[Anum_pg_extension_extconfig - 1] = extConfig; + HeapTupleSetValue(pg_extension, extconfig, extConfig, values); if (extCondition == PointerGetDatum(NULL)) - nulls[Anum_pg_extension_extcondition - 1] = true; + HeapTupleSetValueNull(pg_extension, extcondition, values, nulls); else - values[Anum_pg_extension_extcondition - 1] = extCondition; + HeapTupleSetValue(pg_extension, extcondition, extCondition, values); tuple = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); table_close(rel, RowExclusiveLock); @@ -2674,9 +2673,9 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) int arrayLength; int arrayIndex; bool isnull; - Datum repl_val[Natts_pg_extension]; - bool repl_null[Natts_pg_extension]; - bool repl_repl[Natts_pg_extension]; + Datum values[Natts_pg_extension] = {0}; + bool nulls[Natts_pg_extension] = {false}; + Bitmapset *updated = NULL; ArrayType *a; /* @@ -2731,10 +2730,6 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) elog(ERROR, "could not find tuple for extension %u", CurrentExtensionObject); - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - /* Build or modify the extconfig value */ elementDatum = ObjectIdGetDatum(tableoid); @@ -2784,8 +2779,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) true /* OID's typbyval */ , TYPALIGN_INT /* OID's typalign */ ); } - repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a); - repl_repl[Anum_pg_extension_extconfig - 1] = true; + HeapTupleUpdateValue(pg_extension, extconfig, PointerGetDatum(a), values, nulls, updated); /* Build or modify the extcondition value */ elementDatum = PointerGetDatum(wherecond); @@ -2820,17 +2814,16 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) false /* TEXT's typbyval */ , TYPALIGN_INT /* TEXT's typalign */ ); } - repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a); - repl_repl[Anum_pg_extension_extcondition - 1] = true; + HeapTupleUpdateValue(pg_extension, extcondition, PointerGetDatum(a), values, nulls, updated); - extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel), - repl_val, repl_null, repl_repl); + extTup = heap_update_tuple(extTup, RelationGetDescr(extRel), values, nulls, updated); - CatalogTupleUpdate(extRel, &extTup->t_self, extTup); + CatalogTupleUpdate(extRel, &extTup->t_self, extTup, updated, NULL); systable_endscan(extScan); table_close(extRel, RowExclusiveLock); + bms_free(updated); PG_RETURN_VOID(); } @@ -2906,9 +2899,9 @@ extension_config_remove(Oid extensionoid, Oid tableoid) int arrayLength; int arrayIndex; bool isnull; - Datum repl_val[Natts_pg_extension]; - bool repl_null[Natts_pg_extension]; - bool repl_repl[Natts_pg_extension]; + Datum values[Natts_pg_extension] = {0}; + bool nulls[Natts_pg_extension] = {false}; + Bitmapset *updated = NULL; ArrayType *a; /* Find the pg_extension tuple */ @@ -2975,14 +2968,10 @@ extension_config_remove(Oid extensionoid, Oid tableoid) } /* Modify or delete the extconfig value */ - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - if (arrayLength <= 1) { /* removing only element, just set array to null */ - repl_null[Anum_pg_extension_extconfig - 1] = true; + HeapTupleUpdateValueNull(pg_extension, extconfig, values, nulls, updated); } else { @@ -2999,9 +2988,8 @@ extension_config_remove(Oid extensionoid, Oid tableoid) a = construct_array_builtin(dvalues, arrayLength - 1, OIDOID); - repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a); + HeapTupleUpdateValue(pg_extension, extconfig, PointerGetDatum(a), values, nulls, updated); } - repl_repl[Anum_pg_extension_extconfig - 1] = true; /* Modify or delete the extcondition value */ arrayDatum = heap_getattr(extTup, Anum_pg_extension_extcondition, @@ -3026,7 +3014,7 @@ extension_config_remove(Oid extensionoid, Oid tableoid) if (arrayLength <= 1) { /* removing only element, just set array to null */ - repl_null[Anum_pg_extension_extcondition - 1] = true; + HeapTupleUpdateValueNull(pg_extension, extcondition, values, nulls, updated); } else { @@ -3042,19 +3030,17 @@ extension_config_remove(Oid extensionoid, Oid tableoid) dvalues[i] = dvalues[i + 1]; a = construct_array_builtin(dvalues, arrayLength - 1, TEXTOID); - - repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a); + HeapTupleUpdateValue(pg_extension, extcondition, PointerGetDatum(a), values, nulls, updated); } - repl_repl[Anum_pg_extension_extcondition - 1] = true; - extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel), - repl_val, repl_null, repl_repl); + extTup = heap_update_tuple(extTup, RelationGetDescr(extRel), values, nulls, updated); - CatalogTupleUpdate(extRel, &extTup->t_self, extTup); + CatalogTupleUpdate(extRel, &extTup->t_self, extTup, updated, NULL); systable_endscan(extScan); table_close(extRel, RowExclusiveLock); + bms_free(updated); } /* @@ -3072,6 +3058,7 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o SysScanDesc extScan; HeapTuple extTup; Form_pg_extension extForm; + Bitmapset *updated = NULL; Relation depRel; SysScanDesc depScan; HeapTuple depTup; @@ -3253,11 +3240,12 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o relation_close(depRel, AccessShareLock); /* Now adjust pg_extension.extnamespace */ - extForm->extnamespace = nspOid; + HeapTupleUpdateField(pg_extension, extnamespace, nspOid, extForm, updated); - CatalogTupleUpdate(extRel, &extTup->t_self, extTup); + CatalogTupleUpdate(extRel, &extTup->t_self, extTup, updated, NULL); table_close(extRel, RowExclusiveLock); + bms_free(updated); /* update dependency to point to the new schema */ if (changeDependencyFor(ExtensionRelationId, extensionOid, @@ -3447,9 +3435,9 @@ ApplyExtensionUpdates(Oid extensionOid, SysScanDesc extScan; HeapTuple extTup; Form_pg_extension extForm; - Datum values[Natts_pg_extension]; - bool nulls[Natts_pg_extension]; - bool repl[Natts_pg_extension]; + Datum values[Natts_pg_extension] = {0}; + bool nulls[Natts_pg_extension] = {false}; + Bitmapset *updated = NULL; ObjectAddress myself; ListCell *lc; @@ -3486,21 +3474,14 @@ ApplyExtensionUpdates(Oid extensionOid, /* * Modify extrelocatable and extversion in the pg_extension tuple */ - memset(values, 0, sizeof(values)); - memset(nulls, 0, sizeof(nulls)); - memset(repl, 0, sizeof(repl)); - - values[Anum_pg_extension_extrelocatable - 1] = - BoolGetDatum(control->relocatable); - repl[Anum_pg_extension_extrelocatable - 1] = true; - values[Anum_pg_extension_extversion - 1] = - CStringGetTextDatum(versionName); - repl[Anum_pg_extension_extversion - 1] = true; + HeapTupleUpdateValue(pg_extension, extrelocatable, BoolGetDatum(control->relocatable), values, nulls, updated); + HeapTupleUpdateValue(pg_extension, extversion, CStringGetTextDatum(versionName), values, nulls, updated); - extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel), - values, nulls, repl); + extTup = heap_update_tuple(extTup, RelationGetDescr(extRel), + values, nulls, updated); - CatalogTupleUpdate(extRel, &extTup->t_self, extTup); + CatalogTupleUpdate(extRel, &extTup->t_self, extTup, updated, NULL); + bms_free(updated); systable_endscan(extScan); diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index 536065dc515..571814ada29 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -216,9 +216,9 @@ static void AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { Form_pg_foreign_data_wrapper form; - Datum repl_val[Natts_pg_foreign_data_wrapper]; - bool repl_null[Natts_pg_foreign_data_wrapper]; - bool repl_repl[Natts_pg_foreign_data_wrapper]; + Datum values[Natts_pg_foreign_data_wrapper] = {0}; + bool nulls[Natts_pg_foreign_data_wrapper] = {false}; + Bitmapset *updated = NULL; Acl *newAcl; Datum aclDatum; bool isNull; @@ -243,11 +243,7 @@ AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerI if (form->fdwowner != newOwnerId) { - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_foreign_data_wrapper_fdwowner - 1] = true; - repl_val[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_foreign_data_wrapper, fdwowner, ObjectIdGetDatum(newOwnerId), values, nulls, updated); aclDatum = heap_getattr(tup, Anum_pg_foreign_data_wrapper_fdwacl, @@ -258,19 +254,18 @@ AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerI { newAcl = aclnewowner(DatumGetAclP(aclDatum), form->fdwowner, newOwnerId); - repl_repl[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true; - repl_val[Anum_pg_foreign_data_wrapper_fdwacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_foreign_data_wrapper, fdwacl, PointerGetDatum(newAcl), values, nulls, updated); } - tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, - repl_repl); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); /* Update owner dependency reference */ changeDependencyOnOwner(ForeignDataWrapperRelationId, form->oid, newOwnerId); + bms_free(updated); } InvokeObjectPostAlterHook(ForeignDataWrapperRelationId, @@ -349,9 +344,9 @@ static void AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { Form_pg_foreign_server form; - Datum repl_val[Natts_pg_foreign_server]; - bool repl_null[Natts_pg_foreign_server]; - bool repl_repl[Natts_pg_foreign_server]; + Datum values[Natts_pg_foreign_server] = {0}; + bool nulls[Natts_pg_foreign_server] = {false}; + Bitmapset *updated = NULL; Acl *newAcl; Datum aclDatum; bool isNull; @@ -386,11 +381,7 @@ AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) } } - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_foreign_server_srvowner - 1] = true; - repl_val[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_foreign_server, srvowner, ObjectIdGetDatum(newOwnerId), values, nulls, updated); aclDatum = heap_getattr(tup, Anum_pg_foreign_server_srvacl, @@ -401,18 +392,17 @@ AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { newAcl = aclnewowner(DatumGetAclP(aclDatum), form->srvowner, newOwnerId); - repl_repl[Anum_pg_foreign_server_srvacl - 1] = true; - repl_val[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_foreign_server, srvacl, PointerGetDatum(newAcl), values, nulls, updated); } - tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, - repl_repl); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); /* Update owner dependency reference */ changeDependencyOnOwner(ForeignServerRelationId, form->oid, newOwnerId); + bms_free(updated); } InvokeObjectPostAlterHook(ForeignServerRelationId, @@ -569,8 +559,8 @@ ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt) { Relation rel; - Datum values[Natts_pg_foreign_data_wrapper]; - bool nulls[Natts_pg_foreign_data_wrapper]; + Datum values[Natts_pg_foreign_data_wrapper] = {0}; + bool nulls[Natts_pg_foreign_data_wrapper] = {false}; HeapTuple tuple; Oid fdwId; bool handler_given; @@ -612,20 +602,19 @@ CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt) fdwId = GetNewOidWithIndex(rel, ForeignDataWrapperOidIndexId, Anum_pg_foreign_data_wrapper_oid); - values[Anum_pg_foreign_data_wrapper_oid - 1] = ObjectIdGetDatum(fdwId); - values[Anum_pg_foreign_data_wrapper_fdwname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname)); - values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId); + HeapTupleSetValue(pg_foreign_data_wrapper, oid, ObjectIdGetDatum(fdwId), values); + HeapTupleSetValue(pg_foreign_data_wrapper, fdwname, DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname)), values); + HeapTupleSetValue(pg_foreign_data_wrapper, fdwowner, ObjectIdGetDatum(ownerId), values); /* Lookup handler and validator functions, if given */ parse_func_options(pstate, stmt->func_options, &handler_given, &fdwhandler, &validator_given, &fdwvalidator); - values[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler); - values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator); + HeapTupleSetValue(pg_foreign_data_wrapper, fdwhandler, ObjectIdGetDatum(fdwhandler), values); + HeapTupleSetValue(pg_foreign_data_wrapper, fdwvalidator, ObjectIdGetDatum(fdwvalidator), values); - nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true; + HeapTupleSetValueNull(pg_foreign_data_wrapper, fdwacl, values, nulls); fdwoptions = transformGenericOptions(ForeignDataWrapperRelationId, PointerGetDatum(NULL), @@ -633,13 +622,13 @@ CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt) fdwvalidator); if (DatumGetPointer(fdwoptions) != NULL) - values[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = fdwoptions; + HeapTupleSetValue(pg_foreign_data_wrapper, fdwoptions, fdwoptions, values); else - nulls[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true; + HeapTupleSetValueNull(pg_foreign_data_wrapper, fdwoptions, values, nulls); tuple = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); @@ -687,9 +676,9 @@ AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt) Relation rel; HeapTuple tp; Form_pg_foreign_data_wrapper fdwForm; - Datum repl_val[Natts_pg_foreign_data_wrapper]; - bool repl_null[Natts_pg_foreign_data_wrapper]; - bool repl_repl[Natts_pg_foreign_data_wrapper]; + Datum values[Natts_pg_foreign_data_wrapper] = {0}; + bool nulls[Natts_pg_foreign_data_wrapper] = {false}; + Bitmapset *updated = NULL; Oid fdwId; bool isnull; Datum datum; @@ -720,18 +709,13 @@ AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt) fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp); fdwId = fdwForm->oid; - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - parse_func_options(pstate, stmt->func_options, &handler_given, &fdwhandler, &validator_given, &fdwvalidator); if (handler_given) { - repl_val[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler); - repl_repl[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = true; + HeapTupleUpdateValue(pg_foreign_data_wrapper, fdwhandler, ObjectIdGetDatum(fdwhandler), values, nulls, updated); /* * It could be that the behavior of accessing foreign table changes @@ -743,8 +727,7 @@ AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt) if (validator_given) { - repl_val[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator); - repl_repl[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = true; + HeapTupleUpdateValue(pg_foreign_data_wrapper, fdwvalidator, ObjectIdGetDatum(fdwvalidator), values, nulls, updated); /* * It could be that existing options for the FDW or dependent SERVER, @@ -784,18 +767,15 @@ AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt) fdwvalidator); if (DatumGetPointer(datum) != NULL) - repl_val[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = datum; + HeapTupleUpdateValue(pg_foreign_data_wrapper, fdwoptions, datum, values, nulls, updated); else - repl_null[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true; - - repl_repl[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true; + HeapTupleUpdateValueNull(pg_foreign_data_wrapper, fdwoptions, values, nulls, updated); } /* Everything looks good - update the tuple */ - tp = heap_modify_tuple(tp, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + tp = heap_update_tuple(tp, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tp->t_self, tp); + CatalogTupleUpdate(rel, &tp->t_self, tp, updated, NULL); heap_freetuple(tp); @@ -837,6 +817,7 @@ AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt) InvokeObjectPostAlterHook(ForeignDataWrapperRelationId, fdwId, 0); table_close(rel, RowExclusiveLock); + bms_free(updated); return myself; } @@ -850,8 +831,8 @@ CreateForeignServer(CreateForeignServerStmt *stmt) { Relation rel; Datum srvoptions; - Datum values[Natts_pg_foreign_server]; - bool nulls[Natts_pg_foreign_server]; + Datum values[Natts_pg_foreign_server] = {0}; + bool nulls[Natts_pg_foreign_server] = {false}; HeapTuple tuple; Oid srvId; Oid ownerId; @@ -914,28 +895,25 @@ CreateForeignServer(CreateForeignServerStmt *stmt) srvId = GetNewOidWithIndex(rel, ForeignServerOidIndexId, Anum_pg_foreign_server_oid); - values[Anum_pg_foreign_server_oid - 1] = ObjectIdGetDatum(srvId); - values[Anum_pg_foreign_server_srvname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->servername)); - values[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(ownerId); - values[Anum_pg_foreign_server_srvfdw - 1] = ObjectIdGetDatum(fdw->fdwid); + HeapTupleSetValue(pg_foreign_server, oid, ObjectIdGetDatum(srvId), values); + HeapTupleSetValue(pg_foreign_server, srvname, DirectFunctionCall1(namein, CStringGetDatum(stmt->servername)), values); + HeapTupleSetValue(pg_foreign_server, srvowner, ObjectIdGetDatum(ownerId), values); + HeapTupleSetValue(pg_foreign_server, srvfdw, ObjectIdGetDatum(fdw->fdwid), values); /* Add server type if supplied */ if (stmt->servertype) - values[Anum_pg_foreign_server_srvtype - 1] = - CStringGetTextDatum(stmt->servertype); + HeapTupleSetValue(pg_foreign_server, srvtype, CStringGetTextDatum(stmt->servertype), values); else - nulls[Anum_pg_foreign_server_srvtype - 1] = true; + HeapTupleSetValueNull(pg_foreign_server, srvtype, values, nulls); /* Add server version if supplied */ if (stmt->version) - values[Anum_pg_foreign_server_srvversion - 1] = - CStringGetTextDatum(stmt->version); + HeapTupleSetValue(pg_foreign_server, srvversion, CStringGetTextDatum(stmt->version), values); else - nulls[Anum_pg_foreign_server_srvversion - 1] = true; + HeapTupleSetValueNull(pg_foreign_server, srvversion, values, nulls); /* Start with a blank acl */ - nulls[Anum_pg_foreign_server_srvacl - 1] = true; + HeapTupleSetValueNull(pg_foreign_server, srvacl, values, nulls); /* Add server options */ srvoptions = transformGenericOptions(ForeignServerRelationId, @@ -944,13 +922,13 @@ CreateForeignServer(CreateForeignServerStmt *stmt) fdw->fdwvalidator); if (DatumGetPointer(srvoptions) != NULL) - values[Anum_pg_foreign_server_srvoptions - 1] = srvoptions; + HeapTupleSetValue(pg_foreign_server, srvoptions, srvoptions, values); else - nulls[Anum_pg_foreign_server_srvoptions - 1] = true; + HeapTupleSetValueNull(pg_foreign_server, srvoptions, values, nulls); tuple = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); @@ -986,9 +964,9 @@ AlterForeignServer(AlterForeignServerStmt *stmt) { Relation rel; HeapTuple tp; - Datum repl_val[Natts_pg_foreign_server]; - bool repl_null[Natts_pg_foreign_server]; - bool repl_repl[Natts_pg_foreign_server]; + Datum values[Natts_pg_foreign_server] = {0}; + bool nulls[Natts_pg_foreign_server] = {false}; + Bitmapset *updated = NULL; Oid srvId; Form_pg_foreign_server srvForm; ObjectAddress address; @@ -1013,22 +991,15 @@ AlterForeignServer(AlterForeignServerStmt *stmt) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FOREIGN_SERVER, stmt->servername); - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - if (stmt->has_version) { /* * Change the server VERSION string. */ if (stmt->version) - repl_val[Anum_pg_foreign_server_srvversion - 1] = - CStringGetTextDatum(stmt->version); + HeapTupleUpdateValue(pg_foreign_server, srvversion, CStringGetTextDatum(stmt->version), values, nulls, updated); else - repl_null[Anum_pg_foreign_server_srvversion - 1] = true; - - repl_repl[Anum_pg_foreign_server_srvversion - 1] = true; + HeapTupleUpdateValueNull(pg_foreign_server, srvversion, values, nulls, updated); } if (stmt->options) @@ -1052,18 +1023,15 @@ AlterForeignServer(AlterForeignServerStmt *stmt) fdw->fdwvalidator); if (DatumGetPointer(datum) != NULL) - repl_val[Anum_pg_foreign_server_srvoptions - 1] = datum; + HeapTupleUpdateValue(pg_foreign_server, srvoptions, datum, values, nulls, updated); else - repl_null[Anum_pg_foreign_server_srvoptions - 1] = true; - - repl_repl[Anum_pg_foreign_server_srvoptions - 1] = true; + HeapTupleUpdateValueNull(pg_foreign_server, srvoptions, values, nulls, updated); } /* Everything looks good - update the tuple */ - tp = heap_modify_tuple(tp, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + tp = heap_update_tuple(tp, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tp->t_self, tp); + CatalogTupleUpdate(rel, &tp->t_self, tp, updated, NULL); InvokeObjectPostAlterHook(ForeignServerRelationId, srvId, 0); @@ -1072,6 +1040,7 @@ AlterForeignServer(AlterForeignServerStmt *stmt) heap_freetuple(tp); table_close(rel, RowExclusiveLock); + bms_free(updated); return address; } @@ -1112,8 +1081,8 @@ CreateUserMapping(CreateUserMappingStmt *stmt) { Relation rel; Datum useoptions; - Datum values[Natts_pg_user_mapping]; - bool nulls[Natts_pg_user_mapping]; + Datum values[Natts_pg_user_mapping] = {0}; + bool nulls[Natts_pg_user_mapping] = {false}; HeapTuple tuple; Oid useId; Oid umId; @@ -1177,9 +1146,9 @@ CreateUserMapping(CreateUserMappingStmt *stmt) umId = GetNewOidWithIndex(rel, UserMappingOidIndexId, Anum_pg_user_mapping_oid); - values[Anum_pg_user_mapping_oid - 1] = ObjectIdGetDatum(umId); - values[Anum_pg_user_mapping_umuser - 1] = ObjectIdGetDatum(useId); - values[Anum_pg_user_mapping_umserver - 1] = ObjectIdGetDatum(srv->serverid); + HeapTupleSetValue(pg_user_mapping, oid, ObjectIdGetDatum(umId), values); + HeapTupleSetValue(pg_user_mapping, umuser, ObjectIdGetDatum(useId), values); + HeapTupleSetValue(pg_user_mapping, umserver, ObjectIdGetDatum(srv->serverid), values); /* Add user options */ useoptions = transformGenericOptions(UserMappingRelationId, @@ -1188,13 +1157,13 @@ CreateUserMapping(CreateUserMappingStmt *stmt) fdw->fdwvalidator); if (DatumGetPointer(useoptions) != NULL) - values[Anum_pg_user_mapping_umoptions - 1] = useoptions; + HeapTupleSetValue(pg_user_mapping, umoptions, useoptions, values); else - nulls[Anum_pg_user_mapping_umoptions - 1] = true; + HeapTupleSetValueNull(pg_user_mapping, umoptions, values, nulls); tuple = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); @@ -1238,9 +1207,9 @@ AlterUserMapping(AlterUserMappingStmt *stmt) { Relation rel; HeapTuple tp; - Datum repl_val[Natts_pg_user_mapping]; - bool repl_null[Natts_pg_user_mapping]; - bool repl_repl[Natts_pg_user_mapping]; + Datum values[Natts_pg_user_mapping] = {0}; + bool nulls[Natts_pg_user_mapping] = {false}; + Bitmapset *updated = NULL; Oid useId; Oid umId; ForeignServer *srv; @@ -1272,10 +1241,6 @@ AlterUserMapping(AlterUserMappingStmt *stmt) if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for user mapping %u", umId); - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - if (stmt->options) { ForeignDataWrapper *fdw; @@ -1302,18 +1267,15 @@ AlterUserMapping(AlterUserMappingStmt *stmt) fdw->fdwvalidator); if (DatumGetPointer(datum) != NULL) - repl_val[Anum_pg_user_mapping_umoptions - 1] = datum; + HeapTupleUpdateValue(pg_user_mapping, umoptions, datum, values, nulls, updated); else - repl_null[Anum_pg_user_mapping_umoptions - 1] = true; - - repl_repl[Anum_pg_user_mapping_umoptions - 1] = true; + HeapTupleUpdateValueNull(pg_user_mapping, umoptions, values, nulls, updated); } /* Everything looks good - update the tuple */ - tp = heap_modify_tuple(tp, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + tp = heap_update_tuple(tp, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tp->t_self, tp); + CatalogTupleUpdate(rel, &tp->t_self, tp, updated, NULL); InvokeObjectPostAlterHook(UserMappingRelationId, umId, 0); @@ -1323,6 +1285,7 @@ AlterUserMapping(AlterUserMappingStmt *stmt) heap_freetuple(tp); table_close(rel, RowExclusiveLock); + bms_free(updated); return address; } @@ -1416,8 +1379,8 @@ CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid) { Relation ftrel; Datum ftoptions; - Datum values[Natts_pg_foreign_table]; - bool nulls[Natts_pg_foreign_table]; + Datum values[Natts_pg_foreign_table] = {0}; + bool nulls[Natts_pg_foreign_table] = {false}; HeapTuple tuple; AclResult aclresult; ObjectAddress myself; @@ -1456,8 +1419,8 @@ CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid) memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - values[Anum_pg_foreign_table_ftrelid - 1] = ObjectIdGetDatum(relid); - values[Anum_pg_foreign_table_ftserver - 1] = ObjectIdGetDatum(server->serverid); + HeapTupleSetValue(pg_foreign_table, ftrelid, ObjectIdGetDatum(relid), values); + HeapTupleSetValue(pg_foreign_table, ftserver, ObjectIdGetDatum(server->serverid), values); /* Add table generic options */ ftoptions = transformGenericOptions(ForeignTableRelationId, PointerGetDatum(NULL), @@ -1465,13 +1428,13 @@ CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid) fdw->fdwvalidator); if (DatumGetPointer(ftoptions) != NULL) - values[Anum_pg_foreign_table_ftoptions - 1] = ftoptions; + HeapTupleSetValue(pg_foreign_table, ftoptions, ftoptions, values); else - nulls[Anum_pg_foreign_table_ftoptions - 1] = true; + HeapTupleSetValueNull(pg_foreign_table, ftoptions, values, nulls); tuple = heap_form_tuple(ftrel->rd_att, values, nulls); - CatalogTupleInsert(ftrel, tuple); + CatalogTupleInsert(ftrel, tuple, NULL); heap_freetuple(tuple); diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 0335e982b31..b530c3aabf0 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -1375,6 +1375,7 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt) DefElem *rows_item = NULL; DefElem *support_item = NULL; DefElem *parallel_item = NULL; + Bitmapset *updated = NULL; ObjectAddress address; rel = table_open(ProcedureRelationId, RowExclusiveLock); @@ -1489,9 +1490,8 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt) Datum datum; bool isnull; ArrayType *a; - Datum repl_val[Natts_pg_proc]; - bool repl_null[Natts_pg_proc]; - bool repl_repl[Natts_pg_proc]; + Datum values[Natts_pg_proc] = {0}; + bool nulls[Natts_pg_proc] = {false}; /* extract existing proconfig setting */ datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull); @@ -1501,27 +1501,19 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt) a = update_proconfig_value(a, set_items); /* update the tuple */ - memset(repl_repl, false, sizeof(repl_repl)); - repl_repl[Anum_pg_proc_proconfig - 1] = true; - if (a == NULL) - { - repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0; - repl_null[Anum_pg_proc_proconfig - 1] = true; - } + HeapTupleUpdateValueNull(pg_proc, proconfig, values, nulls, updated); else - { - repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a); - repl_null[Anum_pg_proc_proconfig - 1] = false; - } + HeapTupleUpdateValue(pg_proc, proconfig, PointerGetDatum(a), values, nulls, updated); - tup = heap_modify_tuple(tup, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + tup = heap_update_tuple(tup, RelationGetDescr(rel), + values, nulls, updated); } /* DO NOT put more touches of procForm below here; it's now dangling. */ /* Do the update */ - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0); @@ -1838,9 +1830,9 @@ CreateTransform(CreateTransformStmt *stmt) Oid tosqlfuncid; AclResult aclresult; Form_pg_proc procstruct; - Datum values[Natts_pg_transform]; - bool nulls[Natts_pg_transform] = {0}; - bool replaces[Natts_pg_transform] = {0}; + Datum values[Natts_pg_transform] = {0}; + bool nulls[Natts_pg_transform] = {false}; + Bitmapset *updated = NULL; Oid transformid; HeapTuple tuple; HeapTuple newtuple; @@ -1941,10 +1933,10 @@ CreateTransform(CreateTransformStmt *stmt) /* * Ready to go */ - values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid); - values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid); - values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid); - values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid); + HeapTupleUpdateValue(pg_transform, trftype, ObjectIdGetDatum(typeid), values, nulls, updated); + HeapTupleUpdateValue(pg_transform, trflang, ObjectIdGetDatum(langid), values, nulls, updated); + HeapTupleUpdateValue(pg_transform, trffromsql, ObjectIdGetDatum(fromsqlfuncid), values, nulls, updated); + HeapTupleUpdateValue(pg_transform, trftosql, ObjectIdGetDatum(tosqlfuncid), values, nulls, updated); relation = table_open(TransformRelationId, RowExclusiveLock); @@ -1962,11 +1954,8 @@ CreateTransform(CreateTransformStmt *stmt) format_type_be(typeid), stmt->lang))); - replaces[Anum_pg_transform_trffromsql - 1] = true; - replaces[Anum_pg_transform_trftosql - 1] = true; - - newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces); - CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + newtuple = heap_update_tuple(tuple, RelationGetDescr(relation), values, nulls, updated); + CatalogTupleUpdate(relation, &newtuple->t_self, newtuple, updated, NULL); transformid = form->oid; ReleaseSysCache(tuple); @@ -1976,9 +1965,9 @@ CreateTransform(CreateTransformStmt *stmt) { transformid = GetNewOidWithIndex(relation, TransformOidIndexId, Anum_pg_transform_oid); - values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid); + HeapTupleUpdateValue(pg_transform, oid, ObjectIdGetDatum(transformid), values, nulls, updated); newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls); - CatalogTupleInsert(relation, newtuple); + CatalogTupleInsert(relation, newtuple, NULL); is_replace = false; } @@ -2020,6 +2009,7 @@ CreateTransform(CreateTransformStmt *stmt) InvokeObjectPostCreateHook(TransformRelationId, transformid, 0); heap_freetuple(newtuple); + bms_free(updated); table_close(relation, RowExclusiveLock); diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 5712fac3697..26309495ba9 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -1553,6 +1553,8 @@ DefineIndex(Oid tableId, Relation pg_index = table_open(IndexRelationId, RowExclusiveLock); HeapTuple tup, newtup; + Form_pg_index indexForm; + Bitmapset *updated = NULL; tup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexRelationId)); @@ -1560,8 +1562,10 @@ DefineIndex(Oid tableId, elog(ERROR, "cache lookup failed for index %u", indexRelationId); newtup = heap_copytuple(tup); - ((Form_pg_index) GETSTRUCT(newtup))->indisvalid = false; - CatalogTupleUpdate(pg_index, &tup->t_self, newtup); + indexForm = (Form_pg_index) GETSTRUCT(newtup); + HeapTupleUpdateField(pg_index, indisvalid, false, indexForm, updated); + CatalogTupleUpdate(pg_index, &tup->t_self, newtup, updated, NULL); + bms_free(updated); ReleaseSysCache(tup); table_close(pg_index, RowExclusiveLock); heap_freetuple(newtup); @@ -4576,6 +4580,8 @@ update_relispartition(Oid relationId, bool newval) HeapTuple tup; Relation classRel; ItemPointerData otid; + Form_pg_class classForm; + Bitmapset *updated = NULL; classRel = table_open(RelationRelationId, RowExclusiveLock); tup = SearchSysCacheLockedCopy1(RELOID, ObjectIdGetDatum(relationId)); @@ -4583,8 +4589,10 @@ update_relispartition(Oid relationId, bool newval) elog(ERROR, "cache lookup failed for relation %u", relationId); otid = tup->t_self; Assert(((Form_pg_class) GETSTRUCT(tup))->relispartition != newval); - ((Form_pg_class) GETSTRUCT(tup))->relispartition = newval; - CatalogTupleUpdate(classRel, &otid, tup); + classForm = (Form_pg_class) GETSTRUCT(tup); + HeapTupleUpdateField(pg_class, relispartition, newval, classForm, updated); + CatalogTupleUpdate(classRel, &otid, tup, updated, NULL); + bms_free(updated); UnlockTuple(classRel, &otid, InplaceUpdateTupleLock); heap_freetuple(tup); table_close(classRel, RowExclusiveLock); diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index ef7c0d624f1..d4da5308373 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -79,6 +79,7 @@ SetMatViewPopulatedState(Relation relation, bool newstate) { Relation pgrel; HeapTuple tuple; + Bitmapset *updated = NULL; Assert(relation->rd_rel->relkind == RELKIND_MATVIEW); @@ -94,12 +95,12 @@ SetMatViewPopulatedState(Relation relation, bool newstate) elog(ERROR, "cache lookup failed for relation %u", RelationGetRelid(relation)); - ((Form_pg_class) GETSTRUCT(tuple))->relispopulated = newstate; - - CatalogTupleUpdate(pgrel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_class, relispopulated, newstate, (Form_pg_class) GETSTRUCT(tuple), updated); + CatalogTupleUpdate(pgrel, &tuple->t_self, tuple, updated, NULL); heap_freetuple(tuple); table_close(pgrel, RowExclusiveLock); + bms_free(updated); /* * Advance command counter to make the updated pg_class row locally diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index a6dd8eab518..38648c340ab 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -246,8 +246,8 @@ CreateOpFamily(CreateOpFamilyStmt *stmt, const char *opfname, Oid opfamilyoid; Relation rel; HeapTuple tup; - Datum values[Natts_pg_opfamily]; - bool nulls[Natts_pg_opfamily]; + Datum values[Natts_pg_opfamily] = {0}; + bool nulls[Natts_pg_opfamily] = {false}; NameData opfName; ObjectAddress myself, referenced; @@ -275,16 +275,16 @@ CreateOpFamily(CreateOpFamilyStmt *stmt, const char *opfname, opfamilyoid = GetNewOidWithIndex(rel, OpfamilyOidIndexId, Anum_pg_opfamily_oid); - values[Anum_pg_opfamily_oid - 1] = ObjectIdGetDatum(opfamilyoid); - values[Anum_pg_opfamily_opfmethod - 1] = ObjectIdGetDatum(amoid); + HeapTupleSetValue(pg_opfamily, oid, ObjectIdGetDatum(opfamilyoid), values); + HeapTupleSetValue(pg_opfamily, opfmethod, ObjectIdGetDatum(amoid), values); namestrcpy(&opfName, opfname); - values[Anum_pg_opfamily_opfname - 1] = NameGetDatum(&opfName); - values[Anum_pg_opfamily_opfnamespace - 1] = ObjectIdGetDatum(namespaceoid); - values[Anum_pg_opfamily_opfowner - 1] = ObjectIdGetDatum(GetUserId()); + HeapTupleSetValue(pg_opfamily, opfname, NameGetDatum(&opfName), values); + HeapTupleSetValue(pg_opfamily, opfnamespace, ObjectIdGetDatum(namespaceoid), values); + HeapTupleSetValue(pg_opfamily, opfowner, ObjectIdGetDatum(GetUserId()), values); tup = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); @@ -350,8 +350,8 @@ DefineOpClass(CreateOpClassStmt *stmt) HeapTuple tup; Form_pg_am amform; IndexAmRoutine *amroutine; - Datum values[Natts_pg_opclass]; - bool nulls[Natts_pg_opclass]; + Datum values[Natts_pg_opclass] = {0}; + bool nulls[Natts_pg_opclass] = {false}; AclResult aclresult; NameData opcName; ObjectAddress myself, @@ -653,20 +653,20 @@ DefineOpClass(CreateOpClassStmt *stmt) opclassoid = GetNewOidWithIndex(rel, OpclassOidIndexId, Anum_pg_opclass_oid); - values[Anum_pg_opclass_oid - 1] = ObjectIdGetDatum(opclassoid); - values[Anum_pg_opclass_opcmethod - 1] = ObjectIdGetDatum(amoid); + HeapTupleSetValue(pg_opclass, oid, ObjectIdGetDatum(opclassoid), values); + HeapTupleSetValue(pg_opclass, opcmethod, ObjectIdGetDatum(amoid), values); namestrcpy(&opcName, opcname); - values[Anum_pg_opclass_opcname - 1] = NameGetDatum(&opcName); - values[Anum_pg_opclass_opcnamespace - 1] = ObjectIdGetDatum(namespaceoid); - values[Anum_pg_opclass_opcowner - 1] = ObjectIdGetDatum(GetUserId()); - values[Anum_pg_opclass_opcfamily - 1] = ObjectIdGetDatum(opfamilyoid); - values[Anum_pg_opclass_opcintype - 1] = ObjectIdGetDatum(typeoid); - values[Anum_pg_opclass_opcdefault - 1] = BoolGetDatum(stmt->isDefault); - values[Anum_pg_opclass_opckeytype - 1] = ObjectIdGetDatum(storageoid); + HeapTupleSetValue(pg_opclass, opcname, NameGetDatum(&opcName), values); + HeapTupleSetValue(pg_opclass, opcnamespace, ObjectIdGetDatum(namespaceoid), values); + HeapTupleSetValue(pg_opclass, opcowner, ObjectIdGetDatum(GetUserId()), values); + HeapTupleSetValue(pg_opclass, opcfamily, ObjectIdGetDatum(opfamilyoid), values); + HeapTupleSetValue(pg_opclass, opcintype, ObjectIdGetDatum(typeoid), values); + HeapTupleSetValue(pg_opclass, opcdefault, BoolGetDatum(stmt->isDefault), values); + HeapTupleSetValue(pg_opclass, opckeytype, ObjectIdGetDatum(storageoid), values); tup = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); @@ -1455,8 +1455,8 @@ storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators, bool isAdd) { Relation rel; - Datum values[Natts_pg_amop]; - bool nulls[Natts_pg_amop]; + Datum values[Natts_pg_amop] = {0}; + bool nulls[Natts_pg_amop] = {false}; HeapTuple tup; Oid entryoid; ObjectAddress myself, @@ -1496,19 +1496,19 @@ storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, entryoid = GetNewOidWithIndex(rel, AccessMethodOperatorOidIndexId, Anum_pg_amop_oid); - values[Anum_pg_amop_oid - 1] = ObjectIdGetDatum(entryoid); - values[Anum_pg_amop_amopfamily - 1] = ObjectIdGetDatum(opfamilyoid); - values[Anum_pg_amop_amoplefttype - 1] = ObjectIdGetDatum(op->lefttype); - values[Anum_pg_amop_amoprighttype - 1] = ObjectIdGetDatum(op->righttype); - values[Anum_pg_amop_amopstrategy - 1] = Int16GetDatum(op->number); - values[Anum_pg_amop_amoppurpose - 1] = CharGetDatum(oppurpose); - values[Anum_pg_amop_amopopr - 1] = ObjectIdGetDatum(op->object); - values[Anum_pg_amop_amopmethod - 1] = ObjectIdGetDatum(amoid); - values[Anum_pg_amop_amopsortfamily - 1] = ObjectIdGetDatum(op->sortfamily); + HeapTupleSetValue(pg_amop, oid, ObjectIdGetDatum(entryoid), values); + HeapTupleSetValue(pg_amop, amopfamily, ObjectIdGetDatum(opfamilyoid), values); + HeapTupleSetValue(pg_amop, amoplefttype, ObjectIdGetDatum(op->lefttype), values); + HeapTupleSetValue(pg_amop, amoprighttype, ObjectIdGetDatum(op->righttype), values); + HeapTupleSetValue(pg_amop, amopstrategy, Int16GetDatum(op->number), values); + HeapTupleSetValue(pg_amop, amoppurpose, CharGetDatum(oppurpose), values); + HeapTupleSetValue(pg_amop, amopopr, ObjectIdGetDatum(op->object), values); + HeapTupleSetValue(pg_amop, amopmethod, ObjectIdGetDatum(amoid), values); + HeapTupleSetValue(pg_amop, amopsortfamily, ObjectIdGetDatum(op->sortfamily), values); tup = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); @@ -1585,8 +1585,8 @@ storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *procedures, bool isAdd) { Relation rel; - Datum values[Natts_pg_amproc]; - bool nulls[Natts_pg_amproc]; + Datum values[Natts_pg_amproc] = {0}; + bool nulls[Natts_pg_amproc] = {false}; HeapTuple tup; Oid entryoid; ObjectAddress myself, @@ -1623,16 +1623,16 @@ storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, entryoid = GetNewOidWithIndex(rel, AccessMethodProcedureOidIndexId, Anum_pg_amproc_oid); - values[Anum_pg_amproc_oid - 1] = ObjectIdGetDatum(entryoid); - values[Anum_pg_amproc_amprocfamily - 1] = ObjectIdGetDatum(opfamilyoid); - values[Anum_pg_amproc_amproclefttype - 1] = ObjectIdGetDatum(proc->lefttype); - values[Anum_pg_amproc_amprocrighttype - 1] = ObjectIdGetDatum(proc->righttype); - values[Anum_pg_amproc_amprocnum - 1] = Int16GetDatum(proc->number); - values[Anum_pg_amproc_amproc - 1] = ObjectIdGetDatum(proc->object); + HeapTupleSetValue(pg_amproc, oid, ObjectIdGetDatum(entryoid), values); + HeapTupleSetValue(pg_amproc, amprocfamily, ObjectIdGetDatum(opfamilyoid), values); + HeapTupleSetValue(pg_amproc, amproclefttype, ObjectIdGetDatum(proc->lefttype), values); + HeapTupleSetValue(pg_amproc, amprocrighttype, ObjectIdGetDatum(proc->righttype), values); + HeapTupleSetValue(pg_amproc, amprocnum, Int16GetDatum(proc->number), values); + HeapTupleSetValue(pg_amproc, amproc, ObjectIdGetDatum(proc->object), values); tup = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c index 673648f1fc6..649c37b80ae 100644 --- a/src/backend/commands/operatorcmds.c +++ b/src/backend/commands/operatorcmds.c @@ -466,11 +466,9 @@ AlterOperator(AlterOperatorStmt *stmt) Relation catalog; HeapTuple tup; Form_pg_operator oprForm; - int i; ListCell *pl; - Datum values[Natts_pg_operator]; - bool nulls[Natts_pg_operator]; - bool replaces[Natts_pg_operator]; + Datum values[Natts_pg_operator] = {0}; + bool nulls[Natts_pg_operator] = {false}; List *restrictionName = NIL; /* optional restrict. sel. function */ bool updateRestriction = false; Oid restrictionOid; @@ -485,6 +483,7 @@ AlterOperator(AlterOperatorStmt *stmt) bool updateMerges = false; bool canHash = false; bool updateHashes = false; + Bitmapset *updated = NULL; /* Look up the operator */ oprId = LookupOperWithArgs(stmt->opername, false); @@ -646,47 +645,27 @@ AlterOperator(AlterOperatorStmt *stmt) canHash); /* Update the tuple */ - for (i = 0; i < Natts_pg_operator; ++i) - { - values[i] = (Datum) 0; - replaces[i] = false; - nulls[i] = false; - } if (updateRestriction) - { - replaces[Anum_pg_operator_oprrest - 1] = true; - values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restrictionOid); - } + HeapTupleUpdateValue(pg_operator, oprrest, ObjectIdGetDatum(restrictionOid), values, nulls, updated); + if (updateJoin) - { - replaces[Anum_pg_operator_oprjoin - 1] = true; - values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinOid); - } + HeapTupleUpdateValue(pg_operator, oprjoin, ObjectIdGetDatum(joinOid), values, nulls, updated); + if (OidIsValid(commutatorOid)) - { - replaces[Anum_pg_operator_oprcom - 1] = true; - values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(commutatorOid); - } + HeapTupleUpdateValue(pg_operator, oprcom, ObjectIdGetDatum(commutatorOid), values, nulls, updated); + if (OidIsValid(negatorOid)) - { - replaces[Anum_pg_operator_oprnegate - 1] = true; - values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(negatorOid); - } + HeapTupleUpdateValue(pg_operator, oprnegate, ObjectIdGetDatum(negatorOid), values, nulls, updated); + if (updateMerges) - { - replaces[Anum_pg_operator_oprcanmerge - 1] = true; - values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(canMerge); - } + HeapTupleUpdateValue(pg_operator, oprcanmerge, BoolGetDatum(canMerge), values, nulls, updated); + if (updateHashes) - { - replaces[Anum_pg_operator_oprcanhash - 1] = true; - values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(canHash); - } + HeapTupleUpdateValue(pg_operator, oprcanhash, BoolGetDatum(canHash), values, nulls, updated); - tup = heap_modify_tuple(tup, RelationGetDescr(catalog), - values, nulls, replaces); + tup = heap_update_tuple(tup, RelationGetDescr(catalog), values, nulls, updated); - CatalogTupleUpdate(catalog, &tup->t_self, tup); + CatalogTupleUpdate(catalog, &tup->t_self, tup, updated, NULL); address = makeOperatorDependencies(tup, false, true); @@ -696,6 +675,7 @@ AlterOperator(AlterOperatorStmt *stmt) InvokeObjectPostAlterHook(OperatorRelationId, oprId, 0); table_close(catalog, NoLock); + bms_free(updated); return address; } diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c index 83056960fe4..10c7857ade5 100644 --- a/src/backend/commands/policy.c +++ b/src/backend/commands/policy.c @@ -427,6 +427,7 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id) Datum *role_oids; bool attr_isnull; bool keep_policy = true; + Bitmapset *updated = NULL; int i, j; @@ -483,29 +484,19 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id) if (num_roles > 0) { ArrayType *role_ids; - Datum values[Natts_pg_policy]; - bool isnull[Natts_pg_policy]; - bool replaces[Natts_pg_policy]; + Datum values[Natts_pg_policy] = {0}; + bool nulls[Natts_pg_policy] = {false}; HeapTuple new_tuple; HeapTuple reltup; ObjectAddress target; ObjectAddress myself; - /* zero-clear */ - memset(values, 0, sizeof(values)); - memset(replaces, 0, sizeof(replaces)); - memset(isnull, 0, sizeof(isnull)); - /* This is the array for the new tuple */ role_ids = construct_array_builtin(role_oids, num_roles, OIDOID); - replaces[Anum_pg_policy_polroles - 1] = true; - values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids); - - new_tuple = heap_modify_tuple(tuple, - RelationGetDescr(pg_policy_rel), - values, isnull, replaces); - CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple); + HeapTupleUpdateValue(pg_policy, polroles, PointerGetDatum(role_ids), values, nulls, updated); + new_tuple = heap_update_tuple(tuple, RelationGetDescr(pg_policy_rel), values, nulls, updated); + CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple, updated, NULL); /* Remove all the old shared dependencies (roles) */ deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0); @@ -552,8 +543,8 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id) } /* Clean up. */ + bms_free(updated); systable_endscan(sscan); - table_close(pg_policy_rel, RowExclusiveLock); return keep_policy; @@ -584,8 +575,8 @@ CreatePolicy(CreatePolicyStmt *stmt) ScanKeyData skey[2]; SysScanDesc sscan; HeapTuple policy_tuple; - Datum values[Natts_pg_policy]; - bool isnull[Natts_pg_policy]; + Datum values[Natts_pg_policy] = {0}; + bool nulls[Natts_pg_policy] = {false}; ObjectAddress target; ObjectAddress myself; int i; @@ -619,10 +610,6 @@ CreatePolicy(CreatePolicyStmt *stmt) qual_pstate = make_parsestate(NULL); with_check_pstate = make_parsestate(NULL); - /* zero-clear */ - memset(values, 0, sizeof(values)); - memset(isnull, 0, sizeof(isnull)); - /* Get id of table. Also handles permissions checks. */ table_id = RangeVarGetRelidExtended(stmt->table, AccessExclusiveLock, 0, @@ -688,30 +675,29 @@ CreatePolicy(CreatePolicyStmt *stmt) policy_id = GetNewOidWithIndex(pg_policy_rel, PolicyOidIndexId, Anum_pg_policy_oid); - values[Anum_pg_policy_oid - 1] = ObjectIdGetDatum(policy_id); - values[Anum_pg_policy_polrelid - 1] = ObjectIdGetDatum(table_id); - values[Anum_pg_policy_polname - 1] = DirectFunctionCall1(namein, - CStringGetDatum(stmt->policy_name)); - values[Anum_pg_policy_polcmd - 1] = CharGetDatum(polcmd); - values[Anum_pg_policy_polpermissive - 1] = BoolGetDatum(stmt->permissive); - values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids); + HeapTupleSetValue(pg_policy, oid, ObjectIdGetDatum(policy_id), values); + HeapTupleSetValue(pg_policy, polrelid, ObjectIdGetDatum(table_id), values); + HeapTupleSetValue(pg_policy, polname, DirectFunctionCall1(namein, + CStringGetDatum(stmt->policy_name)), values); + HeapTupleSetValue(pg_policy, polcmd, CharGetDatum(polcmd), values); + HeapTupleSetValue(pg_policy, polpermissive, BoolGetDatum(stmt->permissive), values); + HeapTupleSetValue(pg_policy, polroles, PointerGetDatum(role_ids), values); /* Add qual if present. */ if (qual) - values[Anum_pg_policy_polqual - 1] = CStringGetTextDatum(nodeToString(qual)); + HeapTupleSetValue(pg_policy, polqual, CStringGetTextDatum(nodeToString(qual)), values); else - isnull[Anum_pg_policy_polqual - 1] = true; + HeapTupleSetValueNull(pg_policy, polqual, values, nulls); /* Add WITH CHECK qual if present */ if (with_check_qual) - values[Anum_pg_policy_polwithcheck - 1] = CStringGetTextDatum(nodeToString(with_check_qual)); + HeapTupleSetValue(pg_policy, polwithcheck, CStringGetTextDatum(nodeToString(with_check_qual)), values); else - isnull[Anum_pg_policy_polwithcheck - 1] = true; + HeapTupleSetValueNull(pg_policy, polwithcheck, values, nulls); - policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values, - isnull); + policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values, nulls); - CatalogTupleInsert(pg_policy_rel, policy_tuple); + CatalogTupleInsert(pg_policy_rel, policy_tuple, NULL); /* Record Dependencies */ target.classId = RelationRelationId; @@ -782,9 +768,9 @@ AlterPolicy(AlterPolicyStmt *stmt) SysScanDesc sscan; HeapTuple policy_tuple; HeapTuple new_tuple; - Datum values[Natts_pg_policy]; - bool isnull[Natts_pg_policy]; - bool replaces[Natts_pg_policy]; + Datum values[Natts_pg_policy] = {0}; + bool nulls[Natts_pg_policy] = {false}; + Bitmapset *updated = NULL; ObjectAddress target; ObjectAddress myself; Datum polcmd_datum; @@ -854,11 +840,6 @@ AlterPolicy(AlterPolicyStmt *stmt) free_parsestate(with_check_pstate); } - /* zero-clear */ - memset(values, 0, sizeof(values)); - memset(replaces, 0, sizeof(replaces)); - memset(isnull, 0, sizeof(isnull)); - /* Find policy to update. */ pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock); @@ -918,8 +899,7 @@ AlterPolicy(AlterPolicyStmt *stmt) if (role_ids != NULL) { - replaces[Anum_pg_policy_polroles - 1] = true; - values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids); + HeapTupleUpdateValue(pg_policy, polroles, PointerGetDatum(role_ids), values, nulls, updated); } else { @@ -953,9 +933,7 @@ AlterPolicy(AlterPolicyStmt *stmt) if (qual != NULL) { - replaces[Anum_pg_policy_polqual - 1] = true; - values[Anum_pg_policy_polqual - 1] - = CStringGetTextDatum(nodeToString(qual)); + HeapTupleUpdateValue(pg_policy, polqual, CStringGetTextDatum(nodeToString(qual)), values, nulls, updated); } else { @@ -995,9 +973,7 @@ AlterPolicy(AlterPolicyStmt *stmt) if (with_check_qual != NULL) { - replaces[Anum_pg_policy_polwithcheck - 1] = true; - values[Anum_pg_policy_polwithcheck - 1] - = CStringGetTextDatum(nodeToString(with_check_qual)); + HeapTupleUpdateValue(pg_policy, polwithcheck, CStringGetTextDatum(nodeToString(with_check_qual)), values, nulls, updated); } else { @@ -1036,10 +1012,10 @@ AlterPolicy(AlterPolicyStmt *stmt) } } - new_tuple = heap_modify_tuple(policy_tuple, + new_tuple = heap_update_tuple(policy_tuple, RelationGetDescr(pg_policy_rel), - values, isnull, replaces); - CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple); + values, nulls, updated); + CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple, updated, NULL); /* Update Dependencies. */ deleteDependencyRecordsFor(PolicyRelationId, policy_id, false); @@ -1081,6 +1057,7 @@ AlterPolicy(AlterPolicyStmt *stmt) CacheInvalidateRelcache(target_table); /* Clean up. */ + bms_free(updated); systable_endscan(sscan); relation_close(target_table, NoLock); table_close(pg_policy_rel, RowExclusiveLock); @@ -1102,6 +1079,8 @@ rename_policy(RenameStmt *stmt) ScanKeyData skey[2]; SysScanDesc sscan; HeapTuple policy_tuple; + Form_pg_policy polform; + Bitmapset *updated = NULL; ObjectAddress address; /* Get id of table. Also handles permissions checks. */ @@ -1169,11 +1148,12 @@ rename_policy(RenameStmt *stmt) opoloid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid; policy_tuple = heap_copytuple(policy_tuple); + polform = (Form_pg_policy) GETSTRUCT(policy_tuple); + namestrcpy(&polform->polname, stmt->newname); + HeapTupleMarkColumnUpdated(pg_policy, polname, updated); - namestrcpy(&((Form_pg_policy) GETSTRUCT(policy_tuple))->polname, - stmt->newname); - - CatalogTupleUpdate(pg_policy_rel, &policy_tuple->t_self, policy_tuple); + CatalogTupleUpdate(pg_policy_rel, &policy_tuple->t_self, policy_tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(PolicyRelationId, opoloid, 0); diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index d75e2fa74b2..1eab7775537 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -46,9 +46,9 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) Oid funcargtypes[1]; Relation rel; TupleDesc tupDesc; - Datum values[Natts_pg_language]; - bool nulls[Natts_pg_language]; - bool replaces[Natts_pg_language]; + Datum values[Natts_pg_language] = {0}; + bool nulls[Natts_pg_language] = {false}; + Bitmapset *updated = NULL; NameData langname; HeapTuple oldtup; HeapTuple tup; @@ -104,19 +104,15 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) tupDesc = RelationGetDescr(rel); /* Prepare data to be inserted */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, true, sizeof(replaces)); - namestrcpy(&langname, languageName); - values[Anum_pg_language_lanname - 1] = NameGetDatum(&langname); - values[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(languageOwner); - values[Anum_pg_language_lanispl - 1] = BoolGetDatum(true); - values[Anum_pg_language_lanpltrusted - 1] = BoolGetDatum(stmt->pltrusted); - values[Anum_pg_language_lanplcallfoid - 1] = ObjectIdGetDatum(handlerOid); - values[Anum_pg_language_laninline - 1] = ObjectIdGetDatum(inlineOid); - values[Anum_pg_language_lanvalidator - 1] = ObjectIdGetDatum(valOid); - nulls[Anum_pg_language_lanacl - 1] = true; + HeapTupleUpdateValue(pg_language, lanname, NameGetDatum(&langname), values, nulls, updated); + HeapTupleUpdateValue(pg_language, lanowner, ObjectIdGetDatum(languageOwner), values, nulls, updated); + HeapTupleUpdateValue(pg_language, lanispl, BoolGetDatum(true), values, nulls, updated); + HeapTupleUpdateValue(pg_language, lanpltrusted, BoolGetDatum(stmt->pltrusted), values, nulls, updated); + HeapTupleUpdateValue(pg_language, lanplcallfoid, ObjectIdGetDatum(handlerOid), values, nulls, updated); + HeapTupleUpdateValue(pg_language, laninline, ObjectIdGetDatum(inlineOid), values, nulls, updated); + HeapTupleUpdateValue(pg_language, lanvalidator, ObjectIdGetDatum(valOid), values, nulls, updated); + HeapTupleUpdateValueNull(pg_language, lanacl, values, nulls, updated); /* Check for pre-existing definition */ oldtup = SearchSysCache1(LANGNAME, PointerGetDatum(languageName)); @@ -142,13 +138,13 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) * Do not change existing oid, ownership or permissions. Note * dependency-update code below has to agree with this decision. */ - replaces[Anum_pg_language_oid - 1] = false; - replaces[Anum_pg_language_lanowner - 1] = false; - replaces[Anum_pg_language_lanacl - 1] = false; + HeapTupleSetColumnNotUpdated(pg_language, oid, updated); + HeapTupleSetColumnNotUpdated(pg_language, lanowner, updated); + HeapTupleSetColumnNotUpdated(pg_language, lanacl, updated); /* Okay, do it... */ - tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); + tup = heap_update_tuple(oldtup, tupDesc, values, nulls, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); langoid = oldform->oid; ReleaseSysCache(oldtup); @@ -157,11 +153,10 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) else { /* Creating a new language */ - langoid = GetNewOidWithIndex(rel, LanguageOidIndexId, - Anum_pg_language_oid); - values[Anum_pg_language_oid - 1] = ObjectIdGetDatum(langoid); + langoid = GetNewOidWithIndex(rel, LanguageOidIndexId, Anum_pg_language_oid); + HeapTupleUpdateValue(pg_language, oid, ObjectIdGetDatum(langoid), values, nulls, updated); tup = heap_form_tuple(tupDesc, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); is_update = false; } @@ -213,6 +208,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) InvokeObjectPostCreateHook(LanguageRelationId, myself.objectId, 0); table_close(rel, RowExclusiveLock); + bms_free(updated); return myself; } diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c index 1faf3a8c372..fefce1e394c 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -828,8 +828,8 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) Relation rel; ObjectAddress myself; Oid puboid; - bool nulls[Natts_pg_publication]; - Datum values[Natts_pg_publication]; + Datum values[Natts_pg_publication] = {0}; + bool nulls[Natts_pg_publication] = {false}; HeapTuple tup; bool publish_given; PublicationActions pubactions; @@ -871,9 +871,8 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - values[Anum_pg_publication_pubname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname)); - values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId()); + HeapTupleSetValue(pg_publication, pubname, DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname)), values); + HeapTupleSetValue(pg_publication, pubowner, ObjectIdGetDatum(GetUserId()), values); parse_publication_options(pstate, stmt->options, @@ -892,28 +891,20 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) puboid = GetNewOidWithIndex(rel, PublicationObjectIndexId, Anum_pg_publication_oid); - values[Anum_pg_publication_oid - 1] = ObjectIdGetDatum(puboid); - values[Anum_pg_publication_puballtables - 1] = - BoolGetDatum(stmt->for_all_tables); - values[Anum_pg_publication_puballsequences - 1] = - BoolGetDatum(stmt->for_all_sequences); - values[Anum_pg_publication_pubinsert - 1] = - BoolGetDatum(pubactions.pubinsert); - values[Anum_pg_publication_pubupdate - 1] = - BoolGetDatum(pubactions.pubupdate); - values[Anum_pg_publication_pubdelete - 1] = - BoolGetDatum(pubactions.pubdelete); - values[Anum_pg_publication_pubtruncate - 1] = - BoolGetDatum(pubactions.pubtruncate); - values[Anum_pg_publication_pubviaroot - 1] = - BoolGetDatum(publish_via_partition_root); - values[Anum_pg_publication_pubgencols - 1] = - CharGetDatum(publish_generated_columns); + HeapTupleSetValue(pg_publication, oid, ObjectIdGetDatum(puboid), values); + HeapTupleSetValue(pg_publication, puballtables, BoolGetDatum(stmt->for_all_tables), values); + HeapTupleSetValue(pg_publication, puballsequences, BoolGetDatum(stmt->for_all_sequences), values); + HeapTupleSetValue(pg_publication, pubinsert, BoolGetDatum(pubactions.pubinsert), values); + HeapTupleSetValue(pg_publication, pubupdate, BoolGetDatum(pubactions.pubupdate), values); + HeapTupleSetValue(pg_publication, pubdelete, BoolGetDatum(pubactions.pubdelete), values); + HeapTupleSetValue(pg_publication, pubtruncate, BoolGetDatum(pubactions.pubtruncate), values); + HeapTupleSetValue(pg_publication, pubviaroot, BoolGetDatum(publish_via_partition_root), values); + HeapTupleSetValue(pg_publication, pubgencols, CharGetDatum(publish_generated_columns), values); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); /* Insert tuple into catalog. */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); recordDependencyOnOwner(PublicationRelationId, puboid, GetUserId()); @@ -991,9 +982,9 @@ static void AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt, Relation rel, HeapTuple tup) { - bool nulls[Natts_pg_publication]; - bool replaces[Natts_pg_publication]; - Datum values[Natts_pg_publication]; + Datum values[Natts_pg_publication] = {0}; + bool nulls[Natts_pg_publication] = {false}; + Bitmapset *updated = NULL; bool publish_given; PublicationActions pubactions; bool publish_via_partition_root_given; @@ -1103,42 +1094,25 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt, } /* Everything ok, form a new tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - if (publish_given) { - values[Anum_pg_publication_pubinsert - 1] = BoolGetDatum(pubactions.pubinsert); - replaces[Anum_pg_publication_pubinsert - 1] = true; - - values[Anum_pg_publication_pubupdate - 1] = BoolGetDatum(pubactions.pubupdate); - replaces[Anum_pg_publication_pubupdate - 1] = true; - - values[Anum_pg_publication_pubdelete - 1] = BoolGetDatum(pubactions.pubdelete); - replaces[Anum_pg_publication_pubdelete - 1] = true; - - values[Anum_pg_publication_pubtruncate - 1] = BoolGetDatum(pubactions.pubtruncate); - replaces[Anum_pg_publication_pubtruncate - 1] = true; + HeapTupleUpdateValue(pg_publication, pubinsert, BoolGetDatum(pubactions.pubinsert), values, nulls, updated); + HeapTupleUpdateValue(pg_publication, pubupdate, BoolGetDatum(pubactions.pubupdate), values, nulls, updated); + HeapTupleUpdateValue(pg_publication, pubdelete, BoolGetDatum(pubactions.pubdelete), values, nulls, updated); + HeapTupleUpdateValue(pg_publication, pubtruncate, BoolGetDatum(pubactions.pubtruncate), values, nulls, updated); } if (publish_via_partition_root_given) - { - values[Anum_pg_publication_pubviaroot - 1] = BoolGetDatum(publish_via_partition_root); - replaces[Anum_pg_publication_pubviaroot - 1] = true; - } + HeapTupleUpdateValue(pg_publication, pubviaroot, BoolGetDatum(publish_via_partition_root), values, nulls, updated); if (publish_generated_columns_given) - { - values[Anum_pg_publication_pubgencols - 1] = CharGetDatum(publish_generated_columns); - replaces[Anum_pg_publication_pubgencols - 1] = true; - } + HeapTupleUpdateValue(pg_publication, pubgencols, CharGetDatum(publish_generated_columns), values, nulls, updated); - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); /* Update the catalog. */ - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + bms_free(updated); CommandCounterIncrement(); @@ -2043,6 +2017,7 @@ static void AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { Form_pg_publication form; + Bitmapset *updated = NULL; form = (Form_pg_publication) GETSTRUCT(tup); @@ -2079,8 +2054,10 @@ AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) } } - form->pubowner = newOwnerId; - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleUpdateField(pg_publication, pubowner, newOwnerId, form, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + + bms_free(updated); /* Update owner dependency reference */ changeDependencyOnOwner(PublicationRelationId, diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 3cc1472103a..460e2b21fc9 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -255,6 +255,7 @@ RenameSchema(const char *oldname, const char *newname) AclResult aclresult; ObjectAddress address; Form_pg_namespace nspform; + Bitmapset *updated = NULL; rel = table_open(NamespaceRelationId, RowExclusiveLock); @@ -292,7 +293,8 @@ RenameSchema(const char *oldname, const char *newname) /* rename */ namestrcpy(&nspform->nspname, newname); - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleMarkColumnUpdated(pg_namespace, nspname, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); InvokeObjectPostAlterHook(NamespaceRelationId, nspOid, 0); @@ -300,6 +302,7 @@ RenameSchema(const char *oldname, const char *newname) table_close(rel, NoLock); heap_freetuple(tup); + bms_free(updated); return address; } @@ -374,14 +377,14 @@ AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId) */ if (nspForm->nspowner != newOwnerId) { - Datum repl_val[Natts_pg_namespace]; - bool repl_null[Natts_pg_namespace]; - bool repl_repl[Natts_pg_namespace]; + Datum values[Natts_pg_namespace] = {0}; + bool nulls[Natts_pg_namespace] = {false}; Acl *newAcl; Datum aclDatum; bool isNull; HeapTuple newtuple; AclResult aclresult; + Bitmapset *updated = NULL; /* Otherwise, must be owner of the existing object */ if (!object_ownercheck(NamespaceRelationId, nspForm->oid, GetUserId())) @@ -406,11 +409,7 @@ AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId) aclcheck_error(aclresult, OBJECT_DATABASE, get_database_name(MyDatabaseId)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_namespace_nspowner - 1] = true; - repl_val[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_namespace, nspowner, ObjectIdGetDatum(newOwnerId), values, nulls, updated); /* * Determine the modified ACL for the new owner. This is only @@ -423,19 +422,19 @@ AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId) { newAcl = aclnewowner(DatumGetAclP(aclDatum), nspForm->nspowner, newOwnerId); - repl_repl[Anum_pg_namespace_nspacl - 1] = true; - repl_val[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_namespace, nspacl, PointerGetDatum(newAcl), values, nulls, updated); } - newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl); + newtuple = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); heap_freetuple(newtuple); /* Update owner dependency reference */ changeDependencyOnOwner(NamespaceRelationId, nspForm->oid, newOwnerId); + bms_free(updated); } InvokeObjectPostAlterHook(NamespaceRelationId, diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c index cee5d7bbb9c..903e3e151d5 100644 --- a/src/backend/commands/seclabel.c +++ b/src/backend/commands/seclabel.c @@ -334,18 +334,16 @@ SetSharedSecurityLabel(const ObjectAddress *object, SysScanDesc scan; HeapTuple oldtup; HeapTuple newtup = NULL; - Datum values[Natts_pg_shseclabel]; - bool nulls[Natts_pg_shseclabel]; - bool replaces[Natts_pg_shseclabel]; + Datum values[Natts_pg_shseclabel] = {0}; + bool nulls[Natts_pg_shseclabel] = {false}; + Bitmapset *updated = NULL; /* Prepare to form or update a tuple, if necessary. */ - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - values[Anum_pg_shseclabel_objoid - 1] = ObjectIdGetDatum(object->objectId); - values[Anum_pg_shseclabel_classoid - 1] = ObjectIdGetDatum(object->classId); - values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider); + HeapTupleUpdateValue(pg_shseclabel, objoid, ObjectIdGetDatum(object->objectId), values, nulls, updated); + HeapTupleUpdateValue(pg_shseclabel, classoid, ObjectIdGetDatum(object->classId), values, nulls, updated); + HeapTupleUpdateValue(pg_shseclabel, provider, CStringGetTextDatum(provider), values, nulls, updated); if (label != NULL) - values[Anum_pg_shseclabel_label - 1] = CStringGetTextDatum(label); + HeapTupleUpdateValue(pg_shseclabel, label, CStringGetTextDatum(label), values, nulls, updated); /* Use the index to search for a matching old tuple */ ScanKeyInit(&keys[0], @@ -373,10 +371,9 @@ SetSharedSecurityLabel(const ObjectAddress *object, CatalogTupleDelete(pg_shseclabel, &oldtup->t_self); else { - replaces[Anum_pg_shseclabel_label - 1] = true; - newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_shseclabel), - values, nulls, replaces); - CatalogTupleUpdate(pg_shseclabel, &oldtup->t_self, newtup); + HeapTupleUpdateValue(pg_shseclabel, label, CStringGetTextDatum(label), values, nulls, updated); + newtup = heap_update_tuple(oldtup, RelationGetDescr(pg_shseclabel), values, nulls, updated); + CatalogTupleUpdate(pg_shseclabel, &oldtup->t_self, newtup, updated, NULL); } } systable_endscan(scan); @@ -386,13 +383,14 @@ SetSharedSecurityLabel(const ObjectAddress *object, { newtup = heap_form_tuple(RelationGetDescr(pg_shseclabel), values, nulls); - CatalogTupleInsert(pg_shseclabel, newtup); + CatalogTupleInsert(pg_shseclabel, newtup, NULL); } if (newtup != NULL) heap_freetuple(newtup); table_close(pg_shseclabel, RowExclusiveLock); + bms_free(updated); } /* @@ -409,9 +407,9 @@ SetSecurityLabel(const ObjectAddress *object, SysScanDesc scan; HeapTuple oldtup; HeapTuple newtup = NULL; - Datum values[Natts_pg_seclabel]; - bool nulls[Natts_pg_seclabel]; - bool replaces[Natts_pg_seclabel]; + Datum values[Natts_pg_seclabel] = {0}; + bool nulls[Natts_pg_seclabel] = {false}; + Bitmapset *updated = NULL; /* Shared objects have their own security label catalog. */ if (IsSharedRelation(object->classId)) @@ -421,14 +419,12 @@ SetSecurityLabel(const ObjectAddress *object, } /* Prepare to form or update a tuple, if necessary. */ - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(object->objectId); - values[Anum_pg_seclabel_classoid - 1] = ObjectIdGetDatum(object->classId); - values[Anum_pg_seclabel_objsubid - 1] = Int32GetDatum(object->objectSubId); - values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider); + HeapTupleUpdateValue(pg_seclabel, objoid, ObjectIdGetDatum(object->objectId), values, nulls, updated); + HeapTupleUpdateValue(pg_seclabel, classoid, ObjectIdGetDatum(object->classId), values, nulls, updated); + HeapTupleUpdateValue(pg_seclabel, objsubid, Int32GetDatum(object->objectSubId), values, nulls, updated); + HeapTupleUpdateValue(pg_seclabel, provider, CStringGetTextDatum(provider), values, nulls, updated); if (label != NULL) - values[Anum_pg_seclabel_label - 1] = CStringGetTextDatum(label); + HeapTupleUpdateValue(pg_seclabel, label, CStringGetTextDatum(label), values, nulls, updated); /* Use the index to search for a matching old tuple */ ScanKeyInit(&keys[0], @@ -460,10 +456,9 @@ SetSecurityLabel(const ObjectAddress *object, CatalogTupleDelete(pg_seclabel, &oldtup->t_self); else { - replaces[Anum_pg_seclabel_label - 1] = true; - newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel), - values, nulls, replaces); - CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup); + HeapTupleUpdateValue(pg_seclabel, label, CStringGetTextDatum(label), values, nulls, updated); + newtup = heap_update_tuple(oldtup, RelationGetDescr(pg_seclabel), values, nulls, updated); + CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup, updated, NULL); } } systable_endscan(scan); @@ -471,9 +466,8 @@ SetSecurityLabel(const ObjectAddress *object, /* If we didn't find an old tuple, insert a new one */ if (newtup == NULL && label != NULL) { - newtup = heap_form_tuple(RelationGetDescr(pg_seclabel), - values, nulls); - CatalogTupleInsert(pg_seclabel, newtup); + newtup = heap_form_tuple(RelationGetDescr(pg_seclabel), values, nulls); + CatalogTupleInsert(pg_seclabel, newtup, NULL); } /* Update indexes, if necessary */ @@ -481,6 +475,7 @@ SetSecurityLabel(const ObjectAddress *object, heap_freetuple(newtup); table_close(pg_seclabel, RowExclusiveLock); + bms_free(updated); } /* diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 8d671b7a29d..d936745d184 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -136,8 +136,8 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq) TupleDesc tupDesc; Datum value[SEQ_COL_LASTCOL]; bool null[SEQ_COL_LASTCOL]; - Datum pgs_values[Natts_pg_sequence]; - bool pgs_nulls[Natts_pg_sequence]; + Datum pgs_values[Natts_pg_sequence] = {0}; + bool pgs_nulls[Natts_pg_sequence] = {false}; int i; /* @@ -232,17 +232,17 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq) memset(pgs_nulls, 0, sizeof(pgs_nulls)); - pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum(seqoid); - pgs_values[Anum_pg_sequence_seqtypid - 1] = ObjectIdGetDatum(seqform.seqtypid); - pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast(seqform.seqstart); - pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast(seqform.seqincrement); - pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast(seqform.seqmax); - pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast(seqform.seqmin); - pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast(seqform.seqcache); - pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum(seqform.seqcycle); + HeapTupleSetValue(pg_sequence, seqrelid, ObjectIdGetDatum(seqoid), pgs_values); + HeapTupleSetValue(pg_sequence, seqtypid, ObjectIdGetDatum(seqform.seqtypid), pgs_values); + HeapTupleSetValue(pg_sequence, seqstart, Int64GetDatumFast(seqform.seqstart), pgs_values); + HeapTupleSetValue(pg_sequence, seqincrement, Int64GetDatumFast(seqform.seqincrement), pgs_values); + HeapTupleSetValue(pg_sequence, seqmax, Int64GetDatumFast(seqform.seqmax), pgs_values); + HeapTupleSetValue(pg_sequence, seqmin, Int64GetDatumFast(seqform.seqmin), pgs_values); + HeapTupleSetValue(pg_sequence, seqcache, Int64GetDatumFast(seqform.seqcache), pgs_values); + HeapTupleSetValue(pg_sequence, seqcycle, BoolGetDatum(seqform.seqcycle), pgs_values); tuple = heap_form_tuple(tupDesc, pgs_values, pgs_nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); table_close(rel, RowExclusiveLock); @@ -455,6 +455,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt) bool is_called; int64 last_value; HeapTuple newdatatuple; + Bitmapset *updated = NULL; /* Open and lock sequence, and check for ownership along the way. */ relid = RangeVarGetRelidExtended(stmt->sequence, @@ -536,8 +537,15 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt) if (owned_by) process_owned_by(seqrel, owned_by, stmt->for_identity); + /* + * Mark all sequence columns as potentially updated since init_params can + * modify any field + */ + HeapTupleUpdateSetAllColumnsUpdated(pg_sequence, updated); + /* update the pg_sequence tuple (we could skip this in some cases...) */ - CatalogTupleUpdate(rel, &seqtuple->t_self, seqtuple); + CatalogTupleUpdate(rel, &seqtuple->t_self, seqtuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, relid, 0); diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index 0cf0ea43f19..4addbed0754 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -71,8 +71,8 @@ CreateStatistics(CreateStatsStmt *stmt, bool check_rights) Oid namespaceId; Oid stxowner = GetUserId(); HeapTuple htup; - Datum values[Natts_pg_statistic_ext]; - bool nulls[Natts_pg_statistic_ext]; + Datum values[Natts_pg_statistic_ext] = {0}; + bool nulls[Natts_pg_statistic_ext] = {false}; int2vector *stxkeys; List *stxexprs = NIL; Datum exprsDatum; @@ -525,22 +525,22 @@ CreateStatistics(CreateStatsStmt *stmt, bool check_rights) statoid = GetNewOidWithIndex(statrel, StatisticExtOidIndexId, Anum_pg_statistic_ext_oid); - values[Anum_pg_statistic_ext_oid - 1] = ObjectIdGetDatum(statoid); - values[Anum_pg_statistic_ext_stxrelid - 1] = ObjectIdGetDatum(relid); - values[Anum_pg_statistic_ext_stxname - 1] = NameGetDatum(&stxname); - values[Anum_pg_statistic_ext_stxnamespace - 1] = ObjectIdGetDatum(namespaceId); - values[Anum_pg_statistic_ext_stxowner - 1] = ObjectIdGetDatum(stxowner); - values[Anum_pg_statistic_ext_stxkeys - 1] = PointerGetDatum(stxkeys); - nulls[Anum_pg_statistic_ext_stxstattarget - 1] = true; - values[Anum_pg_statistic_ext_stxkind - 1] = PointerGetDatum(stxkind); - - values[Anum_pg_statistic_ext_stxexprs - 1] = exprsDatum; + HeapTupleSetValue(pg_statistic_ext, oid, ObjectIdGetDatum(statoid), values); + HeapTupleSetValue(pg_statistic_ext, stxrelid, ObjectIdGetDatum(relid), values); + HeapTupleSetValue(pg_statistic_ext, stxname, NameGetDatum(&stxname), values); + HeapTupleSetValue(pg_statistic_ext, stxnamespace, ObjectIdGetDatum(namespaceId), values); + HeapTupleSetValue(pg_statistic_ext, stxowner, ObjectIdGetDatum(stxowner), values); + HeapTupleSetValue(pg_statistic_ext, stxkeys, PointerGetDatum(stxkeys), values); + HeapTupleSetValueNull(pg_statistic_ext, stxstattarget, values, nulls); + HeapTupleSetValue(pg_statistic_ext, stxkind, PointerGetDatum(stxkind), values); + + HeapTupleSetValue(pg_statistic_ext, stxexprs, exprsDatum, values); if (exprsDatum == (Datum) 0) - nulls[Anum_pg_statistic_ext_stxexprs - 1] = true; + HeapTupleSetValueNull(pg_statistic_ext, stxexprs, values, nulls); /* insert it into pg_statistic_ext */ htup = heap_form_tuple(statrel->rd_att, values, nulls); - CatalogTupleInsert(statrel, htup); + CatalogTupleInsert(statrel, htup, NULL); heap_freetuple(htup); relation_close(statrel, RowExclusiveLock); @@ -636,9 +636,9 @@ AlterStatistics(AlterStatsStmt *stmt) Oid stxoid; HeapTuple oldtup; HeapTuple newtup; - Datum repl_val[Natts_pg_statistic_ext]; - bool repl_null[Natts_pg_statistic_ext]; - bool repl_repl[Natts_pg_statistic_ext]; + Datum values[Natts_pg_statistic_ext] = {0}; + bool nulls[Natts_pg_statistic_ext] = {false}; + Bitmapset *updated = NULL; ObjectAddress address; int newtarget = 0; bool newtarget_default; @@ -713,23 +713,16 @@ AlterStatistics(AlterStatsStmt *stmt) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_STATISTIC_EXT, NameListToString(stmt->defnames)); - /* Build new tuple. */ - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - /* replace the stxstattarget column */ - repl_repl[Anum_pg_statistic_ext_stxstattarget - 1] = true; if (!newtarget_default) - repl_val[Anum_pg_statistic_ext_stxstattarget - 1] = Int16GetDatum(newtarget); + HeapTupleUpdateValue(pg_statistic_ext, stxstattarget, Int16GetDatum(newtarget), values, nulls, updated); else - repl_null[Anum_pg_statistic_ext_stxstattarget - 1] = true; + HeapTupleUpdateValueNull(pg_statistic_ext, stxstattarget, values, nulls, updated); - newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + newtup = heap_update_tuple(oldtup, RelationGetDescr(rel), values, nulls, updated); /* Update system catalog. */ - CatalogTupleUpdate(rel, &newtup->t_self, newtup); + CatalogTupleUpdate(rel, &newtup->t_self, newtup, updated, NULL); InvokeObjectPostAlterHook(StatisticExtRelationId, stxoid, 0); @@ -740,6 +733,7 @@ AlterStatistics(AlterStatsStmt *stmt) * other fields, there is no need to update dependencies. */ + bms_free(updated); heap_freetuple(newtup); ReleaseSysCache(oldtup); diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index 5930e8c5816..e368bfb35f7 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -589,8 +589,8 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt, Relation rel; ObjectAddress myself; Oid subid; - bool nulls[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; + Datum values[Natts_pg_subscription] = {0}; + bool nulls[Natts_pg_subscription] = {false}; Oid owner = GetUserId(); HeapTuple tup; char *conninfo; @@ -710,47 +710,35 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt, subid = GetNewOidWithIndex(rel, SubscriptionObjectIndexId, Anum_pg_subscription_oid); - values[Anum_pg_subscription_oid - 1] = ObjectIdGetDatum(subid); - values[Anum_pg_subscription_subdbid - 1] = ObjectIdGetDatum(MyDatabaseId); - values[Anum_pg_subscription_subskiplsn - 1] = LSNGetDatum(InvalidXLogRecPtr); - values[Anum_pg_subscription_subname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->subname)); - values[Anum_pg_subscription_subowner - 1] = ObjectIdGetDatum(owner); - values[Anum_pg_subscription_subenabled - 1] = BoolGetDatum(opts.enabled); - values[Anum_pg_subscription_subbinary - 1] = BoolGetDatum(opts.binary); - values[Anum_pg_subscription_substream - 1] = CharGetDatum(opts.streaming); - values[Anum_pg_subscription_subtwophasestate - 1] = - CharGetDatum(opts.twophase ? - LOGICALREP_TWOPHASE_STATE_PENDING : - LOGICALREP_TWOPHASE_STATE_DISABLED); - values[Anum_pg_subscription_subdisableonerr - 1] = BoolGetDatum(opts.disableonerr); - values[Anum_pg_subscription_subpasswordrequired - 1] = BoolGetDatum(opts.passwordrequired); - values[Anum_pg_subscription_subrunasowner - 1] = BoolGetDatum(opts.runasowner); - values[Anum_pg_subscription_subfailover - 1] = BoolGetDatum(opts.failover); - values[Anum_pg_subscription_subretaindeadtuples - 1] = - BoolGetDatum(opts.retaindeadtuples); - values[Anum_pg_subscription_submaxretention - 1] = - Int32GetDatum(opts.maxretention); - values[Anum_pg_subscription_subretentionactive - 1] = - Int32GetDatum(opts.retaindeadtuples); - values[Anum_pg_subscription_subconninfo - 1] = - CStringGetTextDatum(conninfo); + HeapTupleSetValue(pg_subscription, oid, ObjectIdGetDatum(subid), values); + HeapTupleSetValue(pg_subscription, subdbid, ObjectIdGetDatum(MyDatabaseId), values); + HeapTupleSetValue(pg_subscription, subskiplsn, LSNGetDatum(InvalidXLogRecPtr), values); + HeapTupleSetValue(pg_subscription, subname, DirectFunctionCall1(namein, CStringGetDatum(stmt->subname)), values); + HeapTupleSetValue(pg_subscription, subowner, ObjectIdGetDatum(owner), values); + HeapTupleSetValue(pg_subscription, subenabled, BoolGetDatum(opts.enabled), values); + HeapTupleSetValue(pg_subscription, subbinary, BoolGetDatum(opts.binary), values); + HeapTupleSetValue(pg_subscription, substream, CharGetDatum(opts.streaming), values); + HeapTupleSetValue(pg_subscription, subtwophasestate, CharGetDatum(opts.twophase ? LOGICALREP_TWOPHASE_STATE_PENDING : LOGICALREP_TWOPHASE_STATE_DISABLED), values); + HeapTupleSetValue(pg_subscription, subdisableonerr, BoolGetDatum(opts.disableonerr), values); + HeapTupleSetValue(pg_subscription, subpasswordrequired, BoolGetDatum(opts.passwordrequired), values); + HeapTupleSetValue(pg_subscription, subrunasowner, BoolGetDatum(opts.runasowner), values); + HeapTupleSetValue(pg_subscription, subfailover, BoolGetDatum(opts.failover), values); + HeapTupleSetValue(pg_subscription, subretaindeadtuples, BoolGetDatum(opts.retaindeadtuples), values); + HeapTupleSetValue(pg_subscription, submaxretention, Int32GetDatum(opts.maxretention), values); + HeapTupleSetValue(pg_subscription, subretentionactive, Int32GetDatum(opts.retaindeadtuples), values); + HeapTupleSetValue(pg_subscription, subconninfo, CStringGetTextDatum(conninfo), values); if (opts.slot_name) - values[Anum_pg_subscription_subslotname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(opts.slot_name)); + HeapTupleSetValue(pg_subscription, subslotname, DirectFunctionCall1(namein, CStringGetDatum(opts.slot_name)), values); else - nulls[Anum_pg_subscription_subslotname - 1] = true; - values[Anum_pg_subscription_subsynccommit - 1] = - CStringGetTextDatum(opts.synchronous_commit); - values[Anum_pg_subscription_subpublications - 1] = - publicationListToArray(publications); - values[Anum_pg_subscription_suborigin - 1] = - CStringGetTextDatum(opts.origin); + HeapTupleSetValueNull(pg_subscription, subslotname, values, nulls); + HeapTupleSetValue(pg_subscription, subsynccommit, CStringGetTextDatum(opts.synchronous_commit), values); + HeapTupleSetValue(pg_subscription, subpublications, publicationListToArray(publications), values); + HeapTupleSetValue(pg_subscription, suborigin, CStringGetTextDatum(opts.origin), values); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); /* Insert tuple into catalog. */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); recordDependencyOnOwner(SubscriptionRelationId, subid, owner); @@ -1335,9 +1323,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, { Relation rel; ObjectAddress myself; - bool nulls[Natts_pg_subscription]; - bool replaces[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; + Datum values[Natts_pg_subscription] = {0}; + bool nulls[Natts_pg_subscription] = {false}; HeapTuple tup; Oid subid; bool update_tuple = false; @@ -1352,6 +1339,7 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, Form_pg_subscription form; bits32 supported_opts; SubOpts opts = {0}; + Bitmapset *updated = NULL; rel = table_open(SubscriptionRelationId, RowExclusiveLock); @@ -1396,7 +1384,6 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, /* Form a new tuple. */ memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); switch (stmt->kind) { @@ -1431,41 +1418,27 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, "slot_name = NONE"))); if (opts.slot_name) - values[Anum_pg_subscription_subslotname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(opts.slot_name)); + HeapTupleUpdateValue(pg_subscription, subslotname, + DirectFunctionCall1(namein, CStringGetDatum(opts.slot_name)), values, nulls, updated); else - nulls[Anum_pg_subscription_subslotname - 1] = true; - replaces[Anum_pg_subscription_subslotname - 1] = true; + HeapTupleUpdateValueNull(pg_subscription, subslotname, values, nulls, updated); } if (opts.synchronous_commit) - { - values[Anum_pg_subscription_subsynccommit - 1] = - CStringGetTextDatum(opts.synchronous_commit); - replaces[Anum_pg_subscription_subsynccommit - 1] = true; - } + HeapTupleUpdateValue(pg_subscription, subsynccommit, + CStringGetTextDatum(opts.synchronous_commit), values, nulls, updated); if (IsSet(opts.specified_opts, SUBOPT_BINARY)) - { - values[Anum_pg_subscription_subbinary - 1] = - BoolGetDatum(opts.binary); - replaces[Anum_pg_subscription_subbinary - 1] = true; - } + HeapTupleUpdateValue(pg_subscription, subbinary, + BoolGetDatum(opts.binary), values, nulls, updated); if (IsSet(opts.specified_opts, SUBOPT_STREAMING)) - { - values[Anum_pg_subscription_substream - 1] = - CharGetDatum(opts.streaming); - replaces[Anum_pg_subscription_substream - 1] = true; - } + HeapTupleUpdateValue(pg_subscription, substream, + CharGetDatum(opts.streaming), values, nulls, updated); if (IsSet(opts.specified_opts, SUBOPT_DISABLE_ON_ERR)) - { - values[Anum_pg_subscription_subdisableonerr - 1] - = BoolGetDatum(opts.disableonerr); - replaces[Anum_pg_subscription_subdisableonerr - 1] - = true; - } + HeapTupleUpdateValue(pg_subscription, subdisableonerr, + BoolGetDatum(opts.disableonerr), values, nulls, updated); if (IsSet(opts.specified_opts, SUBOPT_PASSWORD_REQUIRED)) { @@ -1476,18 +1449,13 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, errmsg("password_required=false is superuser-only"), errhint("Subscriptions with the password_required option set to false may only be created or modified by the superuser."))); - values[Anum_pg_subscription_subpasswordrequired - 1] - = BoolGetDatum(opts.passwordrequired); - replaces[Anum_pg_subscription_subpasswordrequired - 1] - = true; + HeapTupleUpdateValue(pg_subscription, subpasswordrequired, + BoolGetDatum(opts.passwordrequired), values, nulls, updated); } if (IsSet(opts.specified_opts, SUBOPT_RUN_AS_OWNER)) - { - values[Anum_pg_subscription_subrunasowner - 1] = - BoolGetDatum(opts.runasowner); - replaces[Anum_pg_subscription_subrunasowner - 1] = true; - } + HeapTupleUpdateValue(pg_subscription, subrunasowner, + BoolGetDatum(opts.runasowner), values, nulls, updated); if (IsSet(opts.specified_opts, SUBOPT_TWOPHASE_COMMIT)) { @@ -1546,11 +1514,10 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, errhint("Resolve these transactions and try again."))); /* Change system catalog accordingly */ - values[Anum_pg_subscription_subtwophasestate - 1] = - CharGetDatum(opts.twophase ? - LOGICALREP_TWOPHASE_STATE_PENDING : - LOGICALREP_TWOPHASE_STATE_DISABLED); - replaces[Anum_pg_subscription_subtwophasestate - 1] = true; + HeapTupleUpdateValue(pg_subscription, subtwophasestate, + CharGetDatum(opts.twophase ? + LOGICALREP_TWOPHASE_STATE_PENDING : + LOGICALREP_TWOPHASE_STATE_DISABLED), values, nulls, updated); } if (IsSet(opts.specified_opts, SUBOPT_FAILOVER)) @@ -1565,16 +1532,14 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, CheckAlterSubOption(sub, "failover", update_failover, isTopLevel); - values[Anum_pg_subscription_subfailover - 1] = - BoolGetDatum(opts.failover); - replaces[Anum_pg_subscription_subfailover - 1] = true; + HeapTupleUpdateValue(pg_subscription, subfailover, + BoolGetDatum(opts.failover), values, nulls, updated); } if (IsSet(opts.specified_opts, SUBOPT_RETAIN_DEAD_TUPLES)) { - values[Anum_pg_subscription_subretaindeadtuples - 1] = - BoolGetDatum(opts.retaindeadtuples); - replaces[Anum_pg_subscription_subretaindeadtuples - 1] = true; + HeapTupleUpdateValue(pg_subscription, subretaindeadtuples, + BoolGetDatum(opts.retaindeadtuples), values, nulls, updated); /* * Update the retention status only if there's a change in @@ -1592,9 +1557,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, */ if (opts.retaindeadtuples != sub->retaindeadtuples) { - values[Anum_pg_subscription_subretentionactive - 1] = - BoolGetDatum(opts.retaindeadtuples); - replaces[Anum_pg_subscription_subretentionactive - 1] = true; + HeapTupleUpdateValue(pg_subscription, subretentionactive, + BoolGetDatum(opts.retaindeadtuples), values, nulls, updated); retention_active = opts.retaindeadtuples; } @@ -1629,9 +1593,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, if (IsSet(opts.specified_opts, SUBOPT_MAX_RETENTION_DURATION)) { - values[Anum_pg_subscription_submaxretention - 1] = - Int32GetDatum(opts.maxretention); - replaces[Anum_pg_subscription_submaxretention - 1] = true; + HeapTupleUpdateValue(pg_subscription, submaxretention, + Int32GetDatum(opts.maxretention), values, nulls, updated); max_retention = opts.maxretention; } @@ -1650,9 +1613,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, if (IsSet(opts.specified_opts, SUBOPT_ORIGIN)) { - values[Anum_pg_subscription_suborigin - 1] = - CStringGetTextDatum(opts.origin); - replaces[Anum_pg_subscription_suborigin - 1] = true; + HeapTupleUpdateValue(pg_subscription, suborigin, + CStringGetTextDatum(opts.origin), values, nulls, updated); /* * Check if changes from different origins may be received @@ -1689,9 +1651,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, WARNING, sub->retaindeadtuples, sub->retentionactive, false); - values[Anum_pg_subscription_subenabled - 1] = - BoolGetDatum(opts.enabled); - replaces[Anum_pg_subscription_subenabled - 1] = true; + HeapTupleUpdateValue(pg_subscription, subenabled, + BoolGetDatum(opts.enabled), values, nulls, updated); if (opts.enabled) ApplyLauncherWakeupAtCommit(); @@ -1715,9 +1676,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, walrcv_check_conninfo(stmt->conninfo, sub->passwordrequired && !sub->ownersuperuser); - values[Anum_pg_subscription_subconninfo - 1] = - CStringGetTextDatum(stmt->conninfo); - replaces[Anum_pg_subscription_subconninfo - 1] = true; + HeapTupleUpdateValue(pg_subscription, subconninfo, + CStringGetTextDatum(stmt->conninfo), values, nulls, updated); update_tuple = true; /* @@ -1734,9 +1694,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, parse_subscription_options(pstate, stmt->options, supported_opts, &opts); - values[Anum_pg_subscription_subpublications - 1] = - publicationListToArray(stmt->publication); - replaces[Anum_pg_subscription_subpublications - 1] = true; + HeapTupleUpdateValue(pg_subscription, subpublications, + publicationListToArray(stmt->publication), values, nulls, updated); update_tuple = true; @@ -1782,9 +1741,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, supported_opts, &opts); publist = merge_publications(sub->publications, stmt->publication, isadd, stmt->subname); - values[Anum_pg_subscription_subpublications - 1] = - publicationListToArray(publist); - replaces[Anum_pg_subscription_subpublications - 1] = true; + HeapTupleUpdateValue(pg_subscription, subpublications, + publicationListToArray(publist), values, nulls, updated); update_tuple = true; @@ -1915,8 +1873,7 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, LSN_FORMAT_ARGS(remote_lsn)))); } - values[Anum_pg_subscription_subskiplsn - 1] = LSNGetDatum(opts.lsn); - replaces[Anum_pg_subscription_subskiplsn - 1] = true; + HeapTupleUpdateValue(pg_subscription, subskiplsn, LSNGetDatum(opts.lsn), values, nulls, updated); update_tuple = true; break; @@ -1930,10 +1887,9 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, /* Update the catalog if needed. */ if (update_tuple) { - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); heap_freetuple(tup); } @@ -2000,6 +1956,7 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, /* Wake up related replication workers to handle this change quickly. */ LogicalRepWorkersWakeupAtCommit(subid); + bms_free(updated); return myself; } @@ -2355,6 +2312,7 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { Form_pg_subscription form; AclResult aclresult; + Bitmapset *updated = NULL; form = (Form_pg_subscription) GETSTRUCT(tup); @@ -2391,8 +2349,8 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) aclcheck_error(aclresult, OBJECT_DATABASE, get_database_name(MyDatabaseId)); - form->subowner = newOwnerId; - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleUpdateField(pg_subscription, subowner, newOwnerId, form, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); /* Update owner dependency reference */ changeDependencyOnOwner(SubscriptionRelationId, @@ -2405,6 +2363,7 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) /* Wake up related background processes to handle this change quickly. */ ApplyLauncherWakeupAtCommit(); LogicalRepWorkersWakeupAtCommit(form->oid); + bms_free(updated); } /* diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 23ebaa3f230..c7ecb2c10cc 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -3641,6 +3641,7 @@ SetRelationHasSubclass(Oid relationId, bool relhassubclass) Relation relationRelation; HeapTuple tuple; Form_pg_class classtuple; + Bitmapset *updated = NULL; Assert(CheckRelationOidLockedByMe(relationId, ShareUpdateExclusiveLock, false) || @@ -3658,8 +3659,8 @@ SetRelationHasSubclass(Oid relationId, bool relhassubclass) if (classtuple->relhassubclass != relhassubclass) { - classtuple->relhassubclass = relhassubclass; - CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_class, relhassubclass, relhassubclass, classtuple, updated); + CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple, updated, NULL); } else { @@ -3668,6 +3669,7 @@ SetRelationHasSubclass(Oid relationId, bool relhassubclass) } heap_freetuple(tuple); + bms_free(updated); table_close(relationRelation, RowExclusiveLock); } @@ -3747,6 +3749,8 @@ SetRelationTableSpace(Relation rel, HeapTuple tuple; ItemPointerData otid; Form_pg_class rd_rel; + Bitmapset *updated = NULL; + Oid field = InvalidOid; Oid reloid = RelationGetRelid(rel); Assert(CheckRelationTableSpaceMove(rel, newTableSpaceId)); @@ -3761,11 +3765,16 @@ SetRelationTableSpace(Relation rel, rd_rel = (Form_pg_class) GETSTRUCT(tuple); /* Update the pg_class row. */ - rd_rel->reltablespace = (newTableSpaceId == MyDatabaseTableSpace) ? - InvalidOid : newTableSpaceId; + if (newTableSpaceId != MyDatabaseTableSpace) + field = newTableSpaceId; + + HeapTupleUpdateField(pg_class, reltablespace, field, rd_rel, updated); + if (RelFileNumberIsValid(newRelFilenumber)) - rd_rel->relfilenode = newRelFilenumber; - CatalogTupleUpdate(pg_class, &otid, tuple); + HeapTupleUpdateField(pg_class, relfilenode, newRelFilenumber, rd_rel, updated); + + CatalogTupleUpdate(pg_class, &otid, tuple, updated, NULL); + UnlockTuple(pg_class, &otid, InplaceUpdateTupleLock); /* @@ -3777,6 +3786,7 @@ SetRelationTableSpace(Relation rel, rd_rel->reltablespace); heap_freetuple(tuple); + bms_free(updated); table_close(pg_class, RowExclusiveLock); } @@ -3846,6 +3856,7 @@ renameatt_internal(Oid myrelid, HeapTuple atttup; Form_pg_attribute attform; AttrNumber attnum; + Bitmapset *updated = NULL; /* * Grab an exclusive lock on the target table, which we will NOT release @@ -3959,9 +3970,9 @@ renameatt_internal(Oid myrelid, (void) check_for_column_name_collision(targetrelation, newattname, false); /* apply the update */ - namestrcpy(&(attform->attname), newattname); - - CatalogTupleUpdate(attrelation, &atttup->t_self, atttup); + namestrcpy(&attform->attname, newattname); + CatalogTupleUpdate(attrelation, &atttup->t_self, atttup, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum); @@ -4267,6 +4278,7 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bo HeapTuple reltup; Form_pg_class relform; Oid namespaceId; + Bitmapset *updated = NULL; /* * Grab a lock on the target relation, which we will NOT release until end @@ -4312,9 +4324,11 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bo * Update pg_class tuple with new relname. (Scribbling on reltup is OK * because it's a copy...) */ - namestrcpy(&(relform->relname), newrelname); - CatalogTupleUpdate(relrelation, &otid, reltup); + namestrcpy(&relform->relname, newrelname); + CatalogTupleUpdate(relrelation, &otid, reltup, updated, NULL); + bms_free(updated); + UnlockTuple(relrelation, &otid, InplaceUpdateTupleLock); InvokeObjectPostAlterHookArg(RelationRelationId, myrelid, 0, @@ -4357,6 +4371,7 @@ ResetRelRewrite(Oid myrelid) Relation relrelation; /* for RELATION relation */ HeapTuple reltup; Form_pg_class relform; + Bitmapset *updated = NULL; /* * Find relation's pg_class tuple. @@ -4368,13 +4383,11 @@ ResetRelRewrite(Oid myrelid) elog(ERROR, "cache lookup failed for relation %u", myrelid); relform = (Form_pg_class) GETSTRUCT(reltup); - /* - * Update pg_class tuple. - */ - relform->relrewrite = InvalidOid; - - CatalogTupleUpdate(relrelation, &reltup->t_self, reltup); + /* Update pg_class tuple */ + HeapTupleUpdateField(pg_class, relrewrite, InvalidOid, relform, updated); + CatalogTupleUpdate(relrelation, &reltup->t_self, reltup, updated, NULL); + bms_free(updated); heap_freetuple(reltup); table_close(relrelation, RowExclusiveLock); } @@ -7227,6 +7240,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, AlterTableCmd *childcmd; ObjectAddress address; TupleDesc tupdesc; + Bitmapset *updated = NULL; /* since this function recurses, it could be driven to stack overflow */ check_stack_depth(); @@ -7286,8 +7300,13 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); - CatalogTupleUpdate(attrdesc, &tuple->t_self, tuple); + HeapTupleMarkColumnUpdated(pg_attribute, attinhcount, updated); + + CatalogTupleUpdate(attrdesc, &tuple->t_self, tuple, updated, NULL); + + bms_free(updated); + updated = NULL; heap_freetuple(tuple); /* Inform the user about the merge */ @@ -7385,9 +7404,10 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, /* * Update pg_class tuple as appropriate */ - relform->relnatts = newattnum; - - CatalogTupleUpdate(pgclass, &reltup->t_self, reltup); + Assert(bms_is_empty(updated)); + HeapTupleUpdateField(pg_class, relnatts, newattnum, relform, updated); + CatalogTupleUpdate(pgclass, &reltup->t_self, reltup, updated, NULL); + bms_free(updated); heap_freetuple(reltup); @@ -7851,6 +7871,7 @@ set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum, { Relation attr_rel; HeapTuple tuple; + Bitmapset *updated = NULL; attr_rel = table_open(AttributeRelationId, RowExclusiveLock); @@ -7864,8 +7885,9 @@ set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum, attr = (Form_pg_attribute) GETSTRUCT(tuple); - attr->attnotnull = true; - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attnotnull, true, attr, updated); + CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); /* * If the nullness isn't already proven by validated constraints, have @@ -7944,6 +7966,7 @@ ATExecSetNotNull(List **wqueue, Relation rel, char *conName, char *colName, { Form_pg_constraint conForm = (Form_pg_constraint) GETSTRUCT(tuple); bool changed = false; + Bitmapset *updated = NULL; /* * Don't let a NO INHERIT constraint be changed into inherit. @@ -7967,11 +7990,12 @@ ATExecSetNotNull(List **wqueue, Relation rel, char *conName, char *colName, ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); + HeapTupleMarkColumnUpdated(pg_constraint, coninhcount, updated); changed = true; } else if (!conForm->conislocal) { - conForm->conislocal = true; + HeapTupleUpdateField(pg_constraint, conislocal, true, conForm, updated); changed = true; } else if (!conForm->convalidated) @@ -7990,7 +8014,8 @@ ATExecSetNotNull(List **wqueue, Relation rel, char *conName, char *colName, constr_rel = table_open(ConstraintRelationId, RowExclusiveLock); - CatalogTupleUpdate(constr_rel, &tuple->t_self, tuple); + CatalogTupleUpdate(constr_rel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); ObjectAddressSet(address, ConstraintRelationId, conForm->oid); table_close(constr_rel, RowExclusiveLock); } @@ -8238,6 +8263,7 @@ ATExecAddIdentity(Relation rel, const char *colName, AttrNumber attnum; ObjectAddress address; ColumnDef *cdef = castNode(ColumnDef, def); + Bitmapset *updated = NULL; bool ispartitioned; ispartitioned = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE); @@ -8318,8 +8344,9 @@ ATExecAddIdentity(Relation rel, const char *colName, errmsg("column \"%s\" of relation \"%s\" already has a default value", colName, RelationGetRelationName(rel)))); - attTup->attidentity = cdef->identity; - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attidentity, cdef->identity, attTup, updated); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -8432,8 +8459,11 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, if (generatedEl) { - attTup->attidentity = defGetInt32(generatedEl); - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_attribute, attidentity, defGetInt32(generatedEl), attTup, updated); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -8488,6 +8518,7 @@ ATExecDropIdentity(Relation rel, const char *colName, bool missing_ok, LOCKMODE Oid seqid; ObjectAddress seqaddress; bool ispartitioned; + Bitmapset *updated = NULL; ispartitioned = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE); if (ispartitioned && !recurse) @@ -8536,8 +8567,9 @@ ATExecDropIdentity(Relation rel, const char *colName, bool missing_ok, LOCKMODE } } - attTup->attidentity = '\0'; - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attidentity, '\0', attTup, updated); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -8799,6 +8831,7 @@ ATExecDropExpression(Relation rel, const char *colName, bool missing_ok, LOCKMOD Relation attrelation; Oid attrdefoid; ObjectAddress address; + Bitmapset *updated = NULL; attrelation = table_open(AttributeRelationId, RowExclusiveLock); tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName); @@ -8852,8 +8885,9 @@ ATExecDropExpression(Relation rel, const char *colName, bool missing_ok, LOCKMOD * Mark the column as no longer generated. (The atthasdef flag needs to * get cleared too, but RemoveAttrDefault will handle that.) */ - attTup->attgenerated = '\0'; - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attgenerated, '\0', attTup, updated); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -8905,9 +8939,9 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa Form_pg_attribute attrtuple; AttrNumber attnum; ObjectAddress address; - Datum repl_val[Natts_pg_attribute]; - bool repl_null[Natts_pg_attribute]; - bool repl_repl[Natts_pg_attribute]; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; /* * We allow referencing columns by numbers only for indexes, since table @@ -9010,16 +9044,14 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa } /* Build new tuple. */ - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); if (!newtarget_default) - repl_val[Anum_pg_attribute_attstattarget - 1] = Int16GetDatum(newtarget); + HeapTupleUpdateValue(pg_attribute, attstattarget, Int16GetDatum(newtarget), values, nulls, updated); else - repl_null[Anum_pg_attribute_attstattarget - 1] = true; - repl_repl[Anum_pg_attribute_attstattarget - 1] = true; - newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation), - repl_val, repl_null, repl_repl); - CatalogTupleUpdate(attrelation, &tuple->t_self, newtuple); + HeapTupleUpdateValueNull(pg_attribute, attstattarget, values, nulls, updated); + newtuple = heap_update_tuple(tuple, RelationGetDescr(attrelation), + values, nulls, updated); + CatalogTupleUpdate(attrelation, &tuple->t_self, newtuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -9052,9 +9084,9 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options, newOptions; bool isnull; ObjectAddress address; - Datum repl_val[Natts_pg_attribute]; - bool repl_null[Natts_pg_attribute]; - bool repl_repl[Natts_pg_attribute]; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; attrelation = table_open(AttributeRelationId, RowExclusiveLock); @@ -9084,18 +9116,17 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options, (void) attribute_reloptions(newOptions, true); /* Build new tuple. */ - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); if (newOptions != (Datum) 0) - repl_val[Anum_pg_attribute_attoptions - 1] = newOptions; + HeapTupleUpdateValue(pg_attribute, attoptions, newOptions, values, nulls, updated); else - repl_null[Anum_pg_attribute_attoptions - 1] = true; - repl_repl[Anum_pg_attribute_attoptions - 1] = true; - newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation), - repl_val, repl_null, repl_repl); + HeapTupleUpdateValueNull(pg_attribute, attoptions, values, nulls, updated); + + newtuple = heap_update_tuple(tuple, RelationGetDescr(attrelation), + values, nulls, updated); /* Update system catalog. */ - CatalogTupleUpdate(attrelation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(attrelation, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -9156,19 +9187,21 @@ SetIndexStorageProperties(Relation rel, Relation attrelation, if (HeapTupleIsValid(tuple)) { Form_pg_attribute attrtuple = (Form_pg_attribute) GETSTRUCT(tuple); + Bitmapset *updated = NULL; if (setstorage) - attrtuple->attstorage = newstorage; + HeapTupleUpdateField(pg_attribute, attstorage, newstorage, attrtuple, updated); if (setcompression) - attrtuple->attcompression = newcompression; + HeapTupleUpdateField(pg_attribute, attcompression, newcompression, attrtuple, updated); - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), attrtuple->attnum); + bms_free(updated); heap_freetuple(tuple); } @@ -9189,6 +9222,7 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc Form_pg_attribute attrtuple; AttrNumber attnum; ObjectAddress address; + Bitmapset *updated = NULL; attrelation = table_open(AttributeRelationId, RowExclusiveLock); @@ -9208,9 +9242,9 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc errmsg("cannot alter system column \"%s\"", colName))); - attrtuple->attstorage = GetAttributeStorage(attrtuple->atttypid, strVal(newValue)); + HeapTupleUpdateField(pg_attribute, attstorage, GetAttributeStorage(attrtuple->atttypid, strVal(newValue)), attrtuple, updated); - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -9225,6 +9259,7 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc false, 0, lockmode); + bms_free(updated); heap_freetuple(tuple); table_close(attrelation, RowExclusiveLock); @@ -9418,9 +9453,11 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, else { /* Child column must survive my deletion */ - childatt->attinhcount--; + Bitmapset *updated = NULL; - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attinhcount, childatt->attinhcount - 1, childatt, updated); + CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); /* Make update visible */ CommandCounterIncrement(); @@ -9433,10 +9470,12 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, * we need to mark the inheritors' attributes as locally * defined rather than inherited. */ - childatt->attinhcount--; - childatt->attislocal = true; + Bitmapset *updated = NULL; - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attinhcount, childatt->attinhcount - 1, childatt, updated); + HeapTupleUpdateField(pg_attribute, attislocal, true, childatt, updated); + CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); /* Make update visible */ CommandCounterIncrement(); @@ -12648,16 +12687,22 @@ ATExecAlterConstrInheritability(List **wqueue, ATAlterConstraint *cmdcon, { HeapTuple childtup; Form_pg_constraint childcon; + Bitmapset *updated = NULL; childtup = findNotNullConstraint(childoid, colName); if (!childtup) elog(ERROR, "cache lookup failed for not-null constraint on column \"%s\" of relation %u", colName, childoid); + childcon = (Form_pg_constraint) GETSTRUCT(childtup); Assert(childcon->coninhcount > 0); - childcon->coninhcount--; - childcon->conislocal = true; - CatalogTupleUpdate(conrel, &childtup->t_self, childtup); + + HeapTupleUpdateField(pg_constraint, coninhcount, childcon->coninhcount - 1, childcon, updated); + HeapTupleUpdateField(pg_constraint, conislocal, true, childcon, updated); + + CatalogTupleUpdate(conrel, &childtup->t_self, childtup, updated, NULL); + + bms_free(updated); heap_freetuple(childtup); } else @@ -12702,6 +12747,7 @@ AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel, Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tgtuple); Form_pg_trigger copy_tg; HeapTuple tgCopyTuple; + Bitmapset *updated = NULL; /* * Remember OIDs of other relation(s) involved in FK constraint. @@ -12728,12 +12774,14 @@ AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel, tgCopyTuple = heap_copytuple(tgtuple); copy_tg = (Form_pg_trigger) GETSTRUCT(tgCopyTuple); - copy_tg->tgdeferrable = deferrable; - copy_tg->tginitdeferred = initdeferred; - CatalogTupleUpdate(tgrel, &tgCopyTuple->t_self, tgCopyTuple); + HeapTupleUpdateField(pg_trigger, tgdeferrable, deferrable, copy_tg, updated); + HeapTupleUpdateField(pg_trigger, tginitdeferred, initdeferred, copy_tg, updated); + + CatalogTupleUpdate(tgrel, &tgCopyTuple->t_self, tgCopyTuple, updated, NULL); InvokeObjectPostAlterHook(TriggerRelationId, tgform->oid, 0); + bms_free(updated); heap_freetuple(tgCopyTuple); } @@ -12848,6 +12896,7 @@ AlterConstrUpdateConstraintEntry(ATAlterConstraint *cmdcon, Relation conrel, { HeapTuple copyTuple; Form_pg_constraint copy_con; + Bitmapset *updated = NULL; Assert(cmdcon->alterEnforceability || cmdcon->alterDeferrability || cmdcon->alterInheritability); @@ -12857,7 +12906,7 @@ AlterConstrUpdateConstraintEntry(ATAlterConstraint *cmdcon, Relation conrel, if (cmdcon->alterEnforceability) { - copy_con->conenforced = cmdcon->is_enforced; + HeapTupleUpdateField(pg_constraint, conenforced, cmdcon->is_enforced, copy_con, updated); /* * NB: The convalidated status is irrelevant when the constraint is @@ -12866,22 +12915,26 @@ AlterConstrUpdateConstraintEntry(ATAlterConstraint *cmdcon, Relation conrel, * ENFORCED, validation will be performed during phase 3, so it makes * sense to mark it as valid in that case. */ - copy_con->convalidated = cmdcon->is_enforced; + HeapTupleUpdateField(pg_constraint, convalidated, cmdcon->is_enforced, copy_con, updated); } + if (cmdcon->alterDeferrability) { - copy_con->condeferrable = cmdcon->deferrable; - copy_con->condeferred = cmdcon->initdeferred; + HeapTupleUpdateField(pg_constraint, condeferrable, cmdcon->deferrable, copy_con, updated); + HeapTupleUpdateField(pg_constraint, condeferred, cmdcon->initdeferred, copy_con, updated); } + if (cmdcon->alterInheritability) - copy_con->connoinherit = cmdcon->noinherit; + HeapTupleUpdateField(pg_constraint, connoinherit, cmdcon->noinherit, copy_con, updated); + + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple, updated, NULL); - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); InvokeObjectPostAlterHook(ConstraintRelationId, copy_con->oid, 0); /* Make new constraint flags visible to others */ CacheInvalidateRelcacheByRelid(copy_con->conrelid); + bms_free(updated); heap_freetuple(copyTuple); } @@ -12994,6 +13047,7 @@ QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation fkrel, AlteredTableInfo *tab; HeapTuple copyTuple; Form_pg_constraint copy_con; + Bitmapset *updated = NULL; con = (Form_pg_constraint) GETSTRUCT(contuple); Assert(con->contype == CONSTRAINT_FOREIGN); @@ -13090,11 +13144,14 @@ QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation fkrel, */ copyTuple = heap_copytuple(contuple); copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); - copy_con->convalidated = true; - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); + + HeapTupleUpdateField(pg_constraint, convalidated, true, copy_con, updated); + + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple, updated, NULL); InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); + bms_free(updated); heap_freetuple(copyTuple); } @@ -13120,6 +13177,7 @@ QueueCheckConstraintValidation(List **wqueue, Relation conrel, Relation rel, NewConstraint *newcon; Datum val; char *conbin; + Bitmapset *updated = NULL; con = (Form_pg_constraint) GETSTRUCT(contuple); Assert(con->contype == CONSTRAINT_CHECK); @@ -13193,11 +13251,14 @@ QueueCheckConstraintValidation(List **wqueue, Relation conrel, Relation rel, */ copyTuple = heap_copytuple(contuple); copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); - copy_con->convalidated = true; - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); + + HeapTupleUpdateField(pg_constraint, convalidated, true, copy_con, updated); + + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple, updated, NULL); InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); + bms_free(updated); heap_freetuple(copyTuple); } @@ -13220,6 +13281,7 @@ QueueNNConstraintValidation(List **wqueue, Relation conrel, Relation rel, List *children = NIL; AttrNumber attnum; char *colname; + Bitmapset *updated = NULL; con = (Form_pg_constraint) GETSTRUCT(contuple); Assert(con->contype == CONSTRAINT_NOTNULL); @@ -13296,11 +13358,14 @@ QueueNNConstraintValidation(List **wqueue, Relation conrel, Relation rel, */ copyTuple = heap_copytuple(contuple); copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); - copy_con->convalidated = true; - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); + + HeapTupleUpdateField(pg_constraint, convalidated, true, copy_con, updated); + + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple, updated, NULL); InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); + bms_free(updated); heap_freetuple(copyTuple); } @@ -14175,8 +14240,11 @@ dropconstraint_internal(Relation rel, HeapTuple constraintTup, DropBehavior beha /* All good -- reset attnotnull if needed */ if (attForm->attnotnull) { - attForm->attnotnull = false; - CatalogTupleUpdate(attrel, &atttup->t_self, atttup); + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_attribute, attnotnull, false, attForm, updated); + CatalogTupleUpdate(attrel, &atttup->t_self, atttup, updated, NULL); + bms_free(updated); } table_close(attrel, RowExclusiveLock); @@ -14309,11 +14377,16 @@ dropconstraint_internal(Relation rel, HeapTuple constraintTup, DropBehavior beha else { /* Child constraint must survive my deletion */ - childcon->coninhcount--; - CatalogTupleUpdate(conrel, &tuple->t_self, tuple); + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_constraint, coninhcount, childcon->coninhcount - 1, childcon, updated); + + CatalogTupleUpdate(conrel, &tuple->t_self, tuple, updated, NULL); /* Make update visible */ CommandCounterIncrement(); + + bms_free(updated); } } else @@ -14324,14 +14397,19 @@ dropconstraint_internal(Relation rel, HeapTuple constraintTup, DropBehavior beha * mark the inheritors' constraints as locally defined rather than * inherited. */ - childcon->coninhcount--; + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_constraint, coninhcount, childcon->coninhcount - 1, childcon, updated); + if (childcon->coninhcount == 0) - childcon->conislocal = true; + HeapTupleUpdateField(pg_constraint, conislocal, true, childcon, updated); - CatalogTupleUpdate(conrel, &tuple->t_self, tuple); + CatalogTupleUpdate(conrel, &tuple->t_self, tuple, updated, NULL); /* Make update visible */ CommandCounterIncrement(); + + bms_free(updated); } heap_freetuple(tuple); @@ -14737,6 +14815,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, SysScanDesc scan; HeapTuple depTup; ObjectAddress address; + Bitmapset *updated = NULL; /* * Clear all the missing values if we're rewriting the table, since this @@ -14913,9 +14992,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, int one = 1; bool isNull; - Datum valuesAtt[Natts_pg_attribute] = {0}; - bool nullsAtt[Natts_pg_attribute] = {0}; - bool replacesAtt[Natts_pg_attribute] = {0}; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; HeapTuple newTup; missingval = array_get_element(missingval, @@ -14933,35 +15011,36 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, tform->typbyval, tform->typalign)); - valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval; - replacesAtt[Anum_pg_attribute_attmissingval - 1] = true; - nullsAtt[Anum_pg_attribute_attmissingval - 1] = false; + HeapTupleUpdateValue(pg_attribute, attmissingval, missingval, values, nulls, updated); - newTup = heap_modify_tuple(heapTup, RelationGetDescr(attrelation), - valuesAtt, nullsAtt, replacesAtt); + newTup = heap_update_tuple(heapTup, RelationGetDescr(attrelation), + values, nulls, updated); heap_freetuple(heapTup); + bms_free(updated); + updated = NULL; + heapTup = newTup; attTup = (Form_pg_attribute) GETSTRUCT(heapTup); } } - attTup->atttypid = targettype; - attTup->atttypmod = targettypmod; - attTup->attcollation = targetcollid; + HeapTupleUpdateField(pg_attribute, atttypid, targettype, attTup, updated); + HeapTupleUpdateField(pg_attribute, atttypmod, targettypmod, attTup, updated); + HeapTupleUpdateField(pg_attribute, attcollation, targetcollid, attTup, updated); if (list_length(typeName->arrayBounds) > PG_INT16_MAX) ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many array dimensions")); - attTup->attndims = list_length(typeName->arrayBounds); - attTup->attlen = tform->typlen; - attTup->attbyval = tform->typbyval; - attTup->attalign = tform->typalign; - attTup->attstorage = tform->typstorage; - attTup->attcompression = InvalidCompressionMethod; + HeapTupleUpdateField(pg_attribute, attndims, list_length(typeName->arrayBounds), attTup, updated); + HeapTupleUpdateField(pg_attribute, attlen, tform->typlen, attTup, updated); + HeapTupleUpdateField(pg_attribute, attbyval, tform->typbyval, attTup, updated); + HeapTupleUpdateField(pg_attribute, attalign, tform->typalign, attTup, updated); + HeapTupleUpdateField(pg_attribute, attstorage, tform->typstorage, attTup, updated); + HeapTupleUpdateField(pg_attribute, attcompression, InvalidCompressionMethod, attTup, updated); ReleaseSysCache(typeTuple); - CatalogTupleUpdate(attrelation, &heapTup->t_self, heapTup); + CatalogTupleUpdate(attrelation, &heapTup->t_self, heapTup, updated, NULL); table_close(attrelation, RowExclusiveLock); @@ -15021,6 +15100,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, RelationGetRelid(rel), attnum); /* Cleanup */ + bms_free(updated); heap_freetuple(heapTup); return address; @@ -15956,9 +16036,9 @@ ATExecAlterColumnGenericOptions(Relation rel, HeapTuple tuple; HeapTuple newtuple; bool isnull; - Datum repl_val[Natts_pg_attribute]; - bool repl_null[Natts_pg_attribute]; - bool repl_repl[Natts_pg_attribute]; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; Datum datum; Form_pg_foreign_table fttableform; Form_pg_attribute atttableform; @@ -16000,11 +16080,6 @@ ATExecAlterColumnGenericOptions(Relation rel, errmsg("cannot alter system column \"%s\"", colName))); - /* Initialize buffers for new tuple values */ - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - /* Extract the current options */ datum = SysCacheGetAttr(ATTNAME, tuple, @@ -16020,18 +16095,15 @@ ATExecAlterColumnGenericOptions(Relation rel, fdw->fdwvalidator); if (DatumGetPointer(datum) != NULL) - repl_val[Anum_pg_attribute_attfdwoptions - 1] = datum; + HeapTupleUpdateValue(pg_attribute, attfdwoptions, datum, values, nulls, updated); else - repl_null[Anum_pg_attribute_attfdwoptions - 1] = true; - - repl_repl[Anum_pg_attribute_attfdwoptions - 1] = true; + HeapTupleUpdateValueNull(pg_attribute, attfdwoptions, values, nulls, updated); /* Everything looks good - update the tuple */ + newtuple = heap_update_tuple(tuple, RelationGetDescr(attrel), + values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrel), - repl_val, repl_null, repl_repl); - - CatalogTupleUpdate(attrel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(attrel, &newtuple->t_self, newtuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -16043,6 +16115,7 @@ ATExecAlterColumnGenericOptions(Relation rel, table_close(attrel, RowExclusiveLock); + bms_free(updated); heap_freetuple(newtuple); return address; @@ -16169,13 +16242,13 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock */ if (tuple_class->relowner != newOwnerId) { - Datum repl_val[Natts_pg_class]; - bool repl_null[Natts_pg_class]; - bool repl_repl[Natts_pg_class]; + Datum values[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; Acl *newAcl; Datum aclDatum; bool isNull; HeapTuple newtuple; + Bitmapset *updated = NULL; /* skip permission checks when recursing to index or toast table */ if (!recursing) @@ -16203,11 +16276,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock } } - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_class_relowner - 1] = true; - repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_class, relowner, ObjectIdGetDatum(newOwnerId), values, nulls, updated); /* * Determine the modified ACL for the new owner. This is only @@ -16220,14 +16289,14 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock { newAcl = aclnewowner(DatumGetAclP(aclDatum), tuple_class->relowner, newOwnerId); - repl_repl[Anum_pg_class_relacl - 1] = true; - repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_class, relacl, PointerGetDatum(newAcl), values, nulls, updated); } - newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl); + newtuple = heap_update_tuple(tuple, RelationGetDescr(class_rel), values, nulls, updated); - CatalogTupleUpdate(class_rel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(class_rel, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); heap_freetuple(newtuple); /* @@ -16319,9 +16388,9 @@ change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId) while (HeapTupleIsValid(attributeTuple = systable_getnext(scan))) { Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attributeTuple); - Datum repl_val[Natts_pg_attribute]; - bool repl_null[Natts_pg_attribute]; - bool repl_repl[Natts_pg_attribute]; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; Acl *newAcl; Datum aclDatum; bool isNull; @@ -16339,20 +16408,17 @@ change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId) if (isNull) continue; - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - newAcl = aclnewowner(DatumGetAclP(aclDatum), oldOwnerId, newOwnerId); - repl_repl[Anum_pg_attribute_attacl - 1] = true; - repl_val[Anum_pg_attribute_attacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_attribute, attacl, PointerGetDatum(newAcl), values, nulls, updated); - newtuple = heap_modify_tuple(attributeTuple, + newtuple = heap_update_tuple(attributeTuple, RelationGetDescr(attRelation), - repl_val, repl_null, repl_repl); + values, nulls, updated); - CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); heap_freetuple(newtuple); } systable_endscan(scan); @@ -16521,6 +16587,7 @@ ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId) HeapTuple tuple; Form_pg_class rd_rel; Oid reloid = RelationGetRelid(rel); + Bitmapset *updated = NULL; /* * Shouldn't be called on relations having storage; these are processed in @@ -16538,17 +16605,18 @@ ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId) /* Update the pg_class row. */ oldAccessMethodId = rd_rel->relam; - rd_rel->relam = newAccessMethodId; + HeapTupleUpdateField(pg_class, relam, newAccessMethodId, rd_rel, updated); /* Leave if no update required */ if (rd_rel->relam == oldAccessMethodId) { + bms_free(updated); heap_freetuple(tuple); table_close(pg_class, RowExclusiveLock); return; } - CatalogTupleUpdate(pg_class, &tuple->t_self, tuple); + CatalogTupleUpdate(pg_class, &tuple->t_self, tuple, updated, NULL); /* * Update the dependency on the new access method. No dependency is added @@ -16596,6 +16664,7 @@ ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId) InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0); + bms_free(updated); heap_freetuple(tuple); table_close(pg_class, RowExclusiveLock); } @@ -16643,9 +16712,9 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, HeapTuple newtuple; Datum datum; Datum newOptions; - Datum repl_val[Natts_pg_class]; - bool repl_null[Natts_pg_class]; - bool repl_repl[Natts_pg_class]; + Datum values[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; + Bitmapset *updated = NULL; const char *const validnsps[] = HEAP_RELOPT_NAMESPACES; if (defList == NIL && operation != AT_ReplaceRelOptions) @@ -16747,25 +16816,23 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, * All we need do here is update the pg_class row; the new options will be * propagated into relcaches during post-commit cache inval. */ - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); if (newOptions != (Datum) 0) - repl_val[Anum_pg_class_reloptions - 1] = newOptions; + HeapTupleUpdateValue(pg_class, reloptions, newOptions, values, nulls, updated); else - repl_null[Anum_pg_class_reloptions - 1] = true; + HeapTupleUpdateValueNull(pg_class, reloptions, values, nulls, updated); - repl_repl[Anum_pg_class_reloptions - 1] = true; + newtuple = heap_update_tuple(tuple, RelationGetDescr(pgclass), + values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass), - repl_val, repl_null, repl_repl); + CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple, updated, NULL); - CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple); UnlockTuple(pgclass, &tuple->t_self, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0); + bms_free(updated); + updated = NULL; heap_freetuple(newtuple); ReleaseSysCache(tuple); @@ -16807,26 +16874,25 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, (void) heap_reloptions(RELKIND_TOASTVALUE, newOptions, true); - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); + memset(values, 0, sizeof(values)); + memset(nulls, false, sizeof(nulls)); + Assert(bms_is_empty(updated)); if (newOptions != (Datum) 0) - repl_val[Anum_pg_class_reloptions - 1] = newOptions; + HeapTupleUpdateValue(pg_class, reloptions, newOptions, values, nulls, updated); else - repl_null[Anum_pg_class_reloptions - 1] = true; - - repl_repl[Anum_pg_class_reloptions - 1] = true; + HeapTupleUpdateValueNull(pg_class, reloptions, values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass), - repl_val, repl_null, repl_repl); + newtuple = heap_update_tuple(tuple, RelationGetDescr(pgclass), + values, nulls, updated); - CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple); + CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple, updated, NULL); InvokeObjectPostAlterHookArg(RelationRelationId, RelationGetRelid(toastrel), 0, InvalidOid, true); + bms_free(updated); heap_freetuple(newtuple); ReleaseSysCache(tuple); @@ -17498,6 +17564,7 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart for (AttrNumber parent_attno = 1; parent_attno <= parent_desc->natts; parent_attno++) { Form_pg_attribute parent_att = TupleDescAttr(parent_desc, parent_attno - 1); + Bitmapset *updated = NULL; char *parent_attname = NameStr(parent_att->attname); HeapTuple tuple; @@ -17582,6 +17649,8 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); + HeapTupleMarkColumnUpdated(pg_attribute, attinhcount, updated); + /* * In case of partitions, we must enforce that value of attislocal * is same in all partitions. (Note: there are only inherited @@ -17590,10 +17659,12 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { Assert(child_att->attinhcount == 1); - child_att->attislocal = false; + HeapTupleUpdateField(pg_attribute, attislocal, false, child_att, updated); } - CatalogTupleUpdate(attrrel, &tuple->t_self, tuple); + CatalogTupleUpdate(attrrel, &tuple->t_self, tuple, updated, NULL); + + bms_free(updated); heap_freetuple(tuple); } else @@ -17656,6 +17727,7 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) HeapTuple child_tuple; AttrNumber parent_attno; bool found = false; + Bitmapset *updated = NULL; if (parent_con->contype != CONSTRAINT_CHECK && parent_con->contype != CONSTRAINT_NOTNULL) @@ -17764,6 +17836,8 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); + HeapTupleMarkColumnUpdated(pg_constraint, coninhcount, updated); + /* * In case of partitions, an inherited constraint must be * inherited only once since it cannot have multiple parents and @@ -17772,10 +17846,12 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { Assert(child_con->coninhcount == 1); - child_con->conislocal = false; + HeapTupleUpdateField(pg_constraint, conislocal, false, child_con, updated); } - CatalogTupleUpdate(constraintrel, &child_copy->t_self, child_copy); + CatalogTupleUpdate(constraintrel, &child_copy->t_self, child_copy, updated, NULL); + + bms_free(updated); heap_freetuple(child_copy); found = true; @@ -17879,6 +17955,7 @@ MarkInheritDetached(Relation child_rel, Relation parent_rel) while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan))) { Form_pg_inherits inhForm; + Bitmapset *updated = NULL; inhForm = (Form_pg_inherits) GETSTRUCT(inheritsTuple); if (inhForm->inhdetachpending) @@ -17893,14 +17970,18 @@ MarkInheritDetached(Relation child_rel, Relation parent_rel) if (inhForm->inhrelid == RelationGetRelid(child_rel)) { HeapTuple newtup; + Form_pg_inherits classForm; newtup = heap_copytuple(inheritsTuple); - ((Form_pg_inherits) GETSTRUCT(newtup))->inhdetachpending = true; + classForm = (Form_pg_inherits) GETSTRUCT(newtup); + + HeapTupleUpdateField(pg_inherits, inhdetachpending, true, classForm, updated); + + CatalogTupleUpdate(catalogRelation, &inheritsTuple->t_self, newtup, updated, NULL); - CatalogTupleUpdate(catalogRelation, - &inheritsTuple->t_self, - newtup); found = true; + + bms_free(updated); heap_freetuple(newtup); /* keep looking, to ensure we catch others pending detach */ } @@ -17985,6 +18066,7 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) while (HeapTupleIsValid(attributeTuple = systable_getnext(scan))) { Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attributeTuple); + Bitmapset *updated = NULL; /* Ignore if dropped or not inherited */ if (att->attisdropped) @@ -17999,11 +18081,14 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) HeapTuple copyTuple = heap_copytuple(attributeTuple); Form_pg_attribute copy_att = (Form_pg_attribute) GETSTRUCT(copyTuple); - copy_att->attinhcount--; + HeapTupleUpdateField(pg_attribute, attinhcount, copy_att->attinhcount - 1, copy_att, updated); + if (copy_att->attinhcount == 0) - copy_att->attislocal = true; + HeapTupleUpdateField(pg_attribute, attislocal, true, copy_att, updated); - CatalogTupleUpdate(catalogRelation, ©Tuple->t_self, copyTuple); + CatalogTupleUpdate(catalogRelation, ©Tuple->t_self, copyTuple, updated, NULL); + + bms_free(updated); heap_freetuple(copyTuple); } } @@ -18065,6 +18150,7 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) { Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(constraintTuple); bool match = false; + Bitmapset *updated = NULL; /* * Match CHECK constraints by name, not-null constraints by column @@ -18110,11 +18196,14 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) elog(ERROR, "relation %u has non-inherited constraint \"%s\"", RelationGetRelid(child_rel), NameStr(copy_con->conname)); - copy_con->coninhcount--; + HeapTupleUpdateField(pg_constraint, coninhcount, copy_con->coninhcount - 1, copy_con, updated); + if (copy_con->coninhcount == 0) - copy_con->conislocal = true; + HeapTupleUpdateField(pg_constraint, conislocal, true, copy_con, updated); - CatalogTupleUpdate(catalogRelation, ©Tuple->t_self, copyTuple); + CatalogTupleUpdate(catalogRelation, ©Tuple->t_self, copyTuple, updated, NULL); + + bms_free(updated); heap_freetuple(copyTuple); } } @@ -18220,6 +18309,7 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode) ObjectAddress tableobj, typeobj; HeapTuple classtuple; + Bitmapset *updated = NULL; /* Validate the type. */ typetuple = typenameType(NULL, ofTypename, NULL); @@ -18325,11 +18415,14 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode) classtuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(classtuple)) elog(ERROR, "cache lookup failed for relation %u", relid); - ((Form_pg_class) GETSTRUCT(classtuple))->reloftype = typeid; - CatalogTupleUpdate(relationRelation, &classtuple->t_self, classtuple); + + HeapTupleUpdateField(pg_class, reloftype, typeid, (Form_pg_class) GETSTRUCT(classtuple), updated); + + CatalogTupleUpdate(relationRelation, &classtuple->t_self, classtuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, relid, 0); + bms_free(updated); heap_freetuple(classtuple); table_close(relationRelation, RowExclusiveLock); @@ -18350,6 +18443,7 @@ ATExecDropOf(Relation rel, LOCKMODE lockmode) Oid relid = RelationGetRelid(rel); Relation relationRelation; HeapTuple tuple; + Bitmapset *updated = NULL; if (!OidIsValid(rel->rd_rel->reloftype)) ereport(ERROR, @@ -18370,11 +18464,14 @@ ATExecDropOf(Relation rel, LOCKMODE lockmode) tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", relid); - ((Form_pg_class) GETSTRUCT(tuple))->reloftype = InvalidOid; - CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple); + + HeapTupleUpdateField(pg_class, reloftype, InvalidOid, (Form_pg_class) GETSTRUCT(tuple), updated); + + CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, relid, 0); + bms_free(updated); heap_freetuple(tuple); table_close(relationRelation, RowExclusiveLock); } @@ -18412,8 +18509,11 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, pg_class_form = (Form_pg_class) GETSTRUCT(pg_class_tuple); if (pg_class_form->relreplident != ri_type) { - pg_class_form->relreplident = ri_type; - CatalogTupleUpdate(pg_class, &pg_class_tuple->t_self, pg_class_tuple); + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_class, relreplident, ri_type, pg_class_form, updated); + CatalogTupleUpdate(pg_class, &pg_class_tuple->t_self, pg_class_tuple, updated, NULL); + bms_free(updated); } table_close(pg_class, RowExclusiveLock); heap_freetuple(pg_class_tuple); @@ -18426,6 +18526,7 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, { Oid thisIndexOid = lfirst_oid(index); bool dirty = false; + Bitmapset *updated = NULL; pg_index_tuple = SearchSysCacheCopy1(INDEXRELID, ObjectIdGetDatum(thisIndexOid)); @@ -18439,7 +18540,7 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, if (!pg_index_form->indisreplident) { dirty = true; - pg_index_form->indisreplident = true; + HeapTupleUpdateField(pg_index, indisreplident, true, pg_index_form, updated); } } else @@ -18448,13 +18549,13 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, if (pg_index_form->indisreplident) { dirty = true; - pg_index_form->indisreplident = false; + HeapTupleUpdateField(pg_index, indisreplident, false, pg_index_form, updated); } } if (dirty) { - CatalogTupleUpdate(pg_index, &pg_index_tuple->t_self, pg_index_tuple); + CatalogTupleUpdate(pg_index, &pg_index_tuple->t_self, pg_index_tuple, updated, NULL); InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0, InvalidOid, is_internal); @@ -18467,6 +18568,7 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, */ CacheInvalidateRelcache(rel); } + bms_free(updated); heap_freetuple(pg_index_tuple); } @@ -18596,6 +18698,7 @@ ATExecSetRowSecurity(Relation rel, bool rls) Relation pg_class; Oid relid; HeapTuple tuple; + Bitmapset *updated = NULL; relid = RelationGetRelid(rel); @@ -18607,13 +18710,14 @@ ATExecSetRowSecurity(Relation rel, bool rls) if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", relid); - ((Form_pg_class) GETSTRUCT(tuple))->relrowsecurity = rls; - CatalogTupleUpdate(pg_class, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_class, relrowsecurity, rls, (Form_pg_class) GETSTRUCT(tuple), updated); + CatalogTupleUpdate(pg_class, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0); table_close(pg_class, RowExclusiveLock); + bms_free(updated); heap_freetuple(tuple); } @@ -18626,6 +18730,7 @@ ATExecForceNoForceRowSecurity(Relation rel, bool force_rls) Relation pg_class; Oid relid; HeapTuple tuple; + Bitmapset *updated = NULL; relid = RelationGetRelid(rel); @@ -18636,13 +18741,14 @@ ATExecForceNoForceRowSecurity(Relation rel, bool force_rls) if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", relid); - ((Form_pg_class) GETSTRUCT(tuple))->relforcerowsecurity = force_rls; - CatalogTupleUpdate(pg_class, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_class, relforcerowsecurity, force_rls, (Form_pg_class) GETSTRUCT(tuple), updated); + CatalogTupleUpdate(pg_class, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0); table_close(pg_class, RowExclusiveLock); + bms_free(updated); heap_freetuple(tuple); } @@ -18657,9 +18763,9 @@ ATExecGenericOptions(Relation rel, List *options) ForeignDataWrapper *fdw; HeapTuple tuple; bool isnull; - Datum repl_val[Natts_pg_foreign_table]; - bool repl_null[Natts_pg_foreign_table]; - bool repl_repl[Natts_pg_foreign_table]; + Datum values[Natts_pg_foreign_table] = {0}; + bool nulls[Natts_pg_foreign_table] = {false}; + Bitmapset *updated = NULL; Datum datum; Form_pg_foreign_table tableform; @@ -18679,10 +18785,6 @@ ATExecGenericOptions(Relation rel, List *options) server = GetForeignServer(tableform->ftserver); fdw = GetForeignDataWrapper(server->fdwid); - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - /* Extract the current options */ datum = SysCacheGetAttr(FOREIGNTABLEREL, tuple, @@ -18698,18 +18800,16 @@ ATExecGenericOptions(Relation rel, List *options) fdw->fdwvalidator); if (DatumGetPointer(datum) != NULL) - repl_val[Anum_pg_foreign_table_ftoptions - 1] = datum; + HeapTupleUpdateValue(pg_foreign_table, ftoptions, datum, values, nulls, updated); else - repl_null[Anum_pg_foreign_table_ftoptions - 1] = true; - - repl_repl[Anum_pg_foreign_table_ftoptions - 1] = true; + HeapTupleUpdateValueNull(pg_foreign_table, ftoptions, values, nulls, updated); /* Everything looks good - update the tuple */ - tuple = heap_modify_tuple(tuple, RelationGetDescr(ftrel), - repl_val, repl_null, repl_repl); + tuple = heap_update_tuple(tuple, RelationGetDescr(ftrel), + values, nulls, updated); - CatalogTupleUpdate(ftrel, &tuple->t_self, tuple); + CatalogTupleUpdate(ftrel, &tuple->t_self, tuple, updated, NULL); /* * Invalidate relcache so that all sessions will refresh any cached plans @@ -18722,6 +18822,7 @@ ATExecGenericOptions(Relation rel, List *options) table_close(ftrel, RowExclusiveLock); + bms_free(updated); heap_freetuple(tuple); } @@ -18743,6 +18844,7 @@ ATExecSetCompression(Relation rel, char *compression; char cmethod; ObjectAddress address; + Bitmapset *updated = NULL; compression = strVal(newValue); @@ -18771,8 +18873,8 @@ ATExecSetCompression(Relation rel, cmethod = GetAttributeCompression(atttableform->atttypid, compression); /* update pg_attribute entry */ - atttableform->attcompression = cmethod; - CatalogTupleUpdate(attrel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attcompression, cmethod, atttableform, updated); + CatalogTupleUpdate(attrel, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -18787,6 +18889,7 @@ ATExecSetCompression(Relation rel, true, cmethod, lockmode); + bms_free(updated); heap_freetuple(tuple); table_close(attrel, RowExclusiveLock); @@ -19050,6 +19153,7 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid, Form_pg_class classForm; ObjectAddress thisobj; bool already_done = false; + Bitmapset *updated = NULL; /* no rel lock for relkind=c so use LOCKTAG_TUPLE */ classTup = SearchSysCacheLockedCopy1(RELOID, ObjectIdGetDatum(relOid)); @@ -19083,9 +19187,10 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid, get_namespace_name(newNspOid)))); /* classTup is a copy, so OK to scribble on */ - classForm->relnamespace = newNspOid; + HeapTupleUpdateField(pg_class, relnamespace, newNspOid, classForm, updated); - CatalogTupleUpdate(classRel, &otid, classTup); + CatalogTupleUpdate(classRel, &otid, classTup, updated, NULL); + bms_free(updated); UnlockTuple(classRel, &otid, InplaceUpdateTupleLock); @@ -21077,9 +21182,9 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent, List *fks; ListCell *cell; List *indexes; - Datum new_val[Natts_pg_class]; - bool new_null[Natts_pg_class], - new_repl[Natts_pg_class]; + Datum new_val[Natts_pg_class] = {0}; + bool new_null[Natts_pg_class] = {false}; + Bitmapset *updated = NULL; HeapTuple tuple, newtuple; Relation trigrel = NULL; @@ -21329,17 +21434,13 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent, Assert(((Form_pg_class) GETSTRUCT(tuple))->relispartition); /* Clear relpartbound and reset relispartition */ - memset(new_val, 0, sizeof(new_val)); - memset(new_null, false, sizeof(new_null)); - memset(new_repl, false, sizeof(new_repl)); - new_val[Anum_pg_class_relpartbound - 1] = (Datum) 0; - new_null[Anum_pg_class_relpartbound - 1] = true; - new_repl[Anum_pg_class_relpartbound - 1] = true; - newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel), - new_val, new_null, new_repl); - - ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = false; - CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple); + HeapTupleUpdateValueNull(pg_class, relpartbound, new_val, new_null, updated); + newtuple = heap_update_tuple(tuple, RelationGetDescr(classRel), + new_val, new_null, updated); + + HeapTupleUpdateField(pg_class, relispartition, false, (Form_pg_class) GETSTRUCT(newtuple), updated); + CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); heap_freetuple(newtuple); table_close(classRel, RowExclusiveLock); @@ -21759,6 +21860,7 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl) int tuples = 0; HeapTuple inhTup; bool updated = false; + Bitmapset *updated_cols = NULL; Assert(partedIdx->rd_rel->relkind == RELKIND_PARTITIONED_INDEX); @@ -21811,10 +21913,11 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl) RelationGetRelid(partedIdx)); indexForm = (Form_pg_index) GETSTRUCT(indTup); - indexForm->indisvalid = true; + HeapTupleUpdateField(pg_index, indisvalid, true, indexForm, updated_cols); updated = true; - CatalogTupleUpdate(idxRel, &indTup->t_self, indTup); + CatalogTupleUpdate(idxRel, &indTup->t_self, indTup, updated_cols, NULL); + bms_free(updated_cols); table_close(idxRel, RowExclusiveLock); heap_freetuple(indTup); diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index df31eace47a..5b89be5983c 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -208,8 +208,8 @@ Oid CreateTableSpace(CreateTableSpaceStmt *stmt) { Relation rel; - Datum values[Natts_pg_tablespace]; - bool nulls[Natts_pg_tablespace] = {0}; + Datum values[Natts_pg_tablespace] = {0}; + bool nulls[Natts_pg_tablespace] = {false}; HeapTuple tuple; Oid tablespaceoid; char *location; @@ -325,12 +325,10 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) else tablespaceoid = GetNewOidWithIndex(rel, TablespaceOidIndexId, Anum_pg_tablespace_oid); - values[Anum_pg_tablespace_oid - 1] = ObjectIdGetDatum(tablespaceoid); - values[Anum_pg_tablespace_spcname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename)); - values[Anum_pg_tablespace_spcowner - 1] = - ObjectIdGetDatum(ownerId); - nulls[Anum_pg_tablespace_spcacl - 1] = true; + HeapTupleSetValue(pg_tablespace, oid, ObjectIdGetDatum(tablespaceoid), values); + HeapTupleSetValue(pg_tablespace, spcname, DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename)), values); + HeapTupleSetValue(pg_tablespace, spcowner, ObjectIdGetDatum(ownerId), values); + HeapTupleSetValueNull(pg_tablespace, spcacl, values, nulls); /* Generate new proposed spcoptions (text array) */ newOptions = transformRelOptions((Datum) 0, @@ -338,13 +336,13 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) NULL, NULL, false, false); (void) tablespace_reloptions(newOptions, true); if (newOptions != (Datum) 0) - values[Anum_pg_tablespace_spcoptions - 1] = newOptions; + HeapTupleSetValue(pg_tablespace, spcoptions, newOptions, values); else - nulls[Anum_pg_tablespace_spcoptions - 1] = true; + HeapTupleSetValueNull(pg_tablespace, spcoptions, values, nulls); tuple = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); @@ -937,6 +935,7 @@ RenameTableSpace(const char *oldname, const char *newname) HeapTuple newtuple; Form_pg_tablespace newform; ObjectAddress address; + Bitmapset *updated = NULL; /* Search pg_tablespace */ rel = table_open(TableSpaceRelationId, RowExclusiveLock); @@ -996,14 +995,15 @@ RenameTableSpace(const char *oldname, const char *newname) /* OK, update the entry */ namestrcpy(&(newform->spcname), newname); - - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + HeapTupleMarkColumnUpdated(pg_tablespace, spcname, updated); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); InvokeObjectPostAlterHook(TableSpaceRelationId, tspId, 0); ObjectAddressSet(address, TableSpaceRelationId, tspId); table_close(rel, NoLock); + bms_free(updated); return address; } @@ -1021,10 +1021,10 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt) Oid tablespaceoid; Datum datum; Datum newOptions; - Datum repl_val[Natts_pg_tablespace]; + Datum values[Natts_pg_tablespace] = {0}; + bool nulls[Natts_pg_tablespace] = {false}; + Bitmapset *updated = NULL; bool isnull; - bool repl_null[Natts_pg_tablespace]; - bool repl_repl[Natts_pg_tablespace]; HeapTuple newtuple; /* Search pg_tablespace */ @@ -1058,26 +1058,25 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt) (void) tablespace_reloptions(newOptions, true); /* Build new tuple. */ - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); if (newOptions != (Datum) 0) - repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions; + HeapTupleUpdateValue(pg_tablespace, spcoptions, newOptions, values, nulls, updated); else - repl_null[Anum_pg_tablespace_spcoptions - 1] = true; - repl_repl[Anum_pg_tablespace_spcoptions - 1] = true; - newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, - repl_null, repl_repl); + HeapTupleUpdateValueNull(pg_tablespace, spcoptions, values, nulls, updated); + newtuple = heap_update_tuple(tup, RelationGetDescr(rel), values, + nulls, updated); /* Update system catalog. */ - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); InvokeObjectPostAlterHook(TableSpaceRelationId, tablespaceoid, 0); heap_freetuple(newtuple); + bms_free(updated); /* Conclude heap scan. */ table_endscan(scandesc); table_close(rel, NoLock); + bms_free(updated); return tablespaceoid; } diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 579ac8d76ae..1cd1f3fc478 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -186,8 +186,9 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, int2vector *tgattr; List *whenRtable; char *qual; - Datum values[Natts_pg_trigger]; - bool nulls[Natts_pg_trigger]; + Datum values[Natts_pg_trigger] = {0}; + bool nulls[Natts_pg_trigger] = {false}; + Bitmapset *updated = NULL; Relation rel; AclResult aclresult; Relation tgrel; @@ -751,8 +752,7 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, if (!trigger_exists) { /* Generate the OID for the new trigger. */ - trigoid = GetNewOidWithIndex(tgrel, TriggerOidIndexId, - Anum_pg_trigger_oid); + trigoid = GetNewOidWithIndex(tgrel, TriggerOidIndexId, Anum_pg_trigger_oid); } else { @@ -862,22 +862,19 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, /* * Build the new pg_trigger tuple. */ - memset(nulls, false, sizeof(nulls)); - - values[Anum_pg_trigger_oid - 1] = ObjectIdGetDatum(trigoid); - values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel)); - values[Anum_pg_trigger_tgparentid - 1] = ObjectIdGetDatum(parentTriggerOid); - values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein, - CStringGetDatum(trigname)); - values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid); - values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype); - values[Anum_pg_trigger_tgenabled - 1] = CharGetDatum(trigger_fires_when); - values[Anum_pg_trigger_tgisinternal - 1] = BoolGetDatum(isInternal); - values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid); - values[Anum_pg_trigger_tgconstrindid - 1] = ObjectIdGetDatum(indexOid); - values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid); - values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable); - values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred); + HeapTupleUpdateValue(pg_trigger, oid, ObjectIdGetDatum(trigoid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgrelid, ObjectIdGetDatum(RelationGetRelid(rel)), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgparentid, ObjectIdGetDatum(parentTriggerOid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgname, DirectFunctionCall1(namein, CStringGetDatum(trigname)), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgfoid, ObjectIdGetDatum(funcoid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgtype, Int16GetDatum(tgtype), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgenabled, CharGetDatum(trigger_fires_when), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgisinternal, BoolGetDatum(isInternal), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgconstrrelid, ObjectIdGetDatum(constrrelid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgconstrindid, ObjectIdGetDatum(indexOid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgconstraint, ObjectIdGetDatum(constraintOid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgdeferrable, BoolGetDatum(stmt->deferrable), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tginitdeferred, BoolGetDatum(stmt->initdeferred), values, nulls, updated); if (stmt->args) { @@ -912,15 +909,13 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, } strcpy(d, "\\000"); } - values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs); - values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain, - CStringGetDatum(args)); + HeapTupleUpdateValue(pg_trigger, tgnargs, Int16GetDatum(nargs), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgargs, DirectFunctionCall1(byteain, CStringGetDatum(args)), values, nulls, updated); } else { - values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0); - values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain, - CStringGetDatum("")); + HeapTupleUpdateValue(pg_trigger, tgnargs, Int16GetDatum(0), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgargs, DirectFunctionCall1(byteain, CStringGetDatum("")), values, nulls, updated); } /* build column number array if it's a column-specific trigger */ @@ -961,24 +956,23 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, } } tgattr = buildint2vector(columns, ncolumns); - values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr); + HeapTupleUpdateValue(pg_trigger, tgattr, PointerGetDatum(tgattr), values, nulls, updated); /* set tgqual if trigger has WHEN clause */ if (qual) - values[Anum_pg_trigger_tgqual - 1] = CStringGetTextDatum(qual); + HeapTupleUpdateValue(pg_trigger, tgqual, CStringGetTextDatum(qual), values, nulls, updated); else - nulls[Anum_pg_trigger_tgqual - 1] = true; + HeapTupleUpdateValueNull(pg_trigger, tgqual, values, nulls, updated); if (oldtablename) - values[Anum_pg_trigger_tgoldtable - 1] = DirectFunctionCall1(namein, - CStringGetDatum(oldtablename)); + HeapTupleUpdateValue(pg_trigger, tgoldtable, DirectFunctionCall1(namein, CStringGetDatum(oldtablename)), values, nulls, updated); else - nulls[Anum_pg_trigger_tgoldtable - 1] = true; + HeapTupleUpdateValueNull(pg_trigger, tgoldtable, values, nulls, updated); + if (newtablename) - values[Anum_pg_trigger_tgnewtable - 1] = DirectFunctionCall1(namein, - CStringGetDatum(newtablename)); + HeapTupleUpdateValue(pg_trigger, tgnewtable, DirectFunctionCall1(namein, CStringGetDatum(newtablename)), values, nulls, updated); else - nulls[Anum_pg_trigger_tgnewtable - 1] = true; + HeapTupleUpdateValueNull(pg_trigger, tgnewtable, values, nulls, updated); /* * Insert or replace tuple in pg_trigger. @@ -986,27 +980,29 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, if (!trigger_exists) { tuple = heap_form_tuple(tgrel->rd_att, values, nulls); - CatalogTupleInsert(tgrel, tuple); + CatalogTupleInsert(tgrel, tuple, NULL); } else { HeapTuple newtup; newtup = heap_form_tuple(tgrel->rd_att, values, nulls); - CatalogTupleUpdate(tgrel, &tuple->t_self, newtup); + CatalogTupleUpdate(tgrel, &tuple->t_self, newtup, updated, NULL); heap_freetuple(newtup); } heap_freetuple(tuple); /* free either original or new tuple */ table_close(tgrel, RowExclusiveLock); + bms_free(updated); + updated = NULL; - pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1])); - pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1])); - pfree(DatumGetPointer(values[Anum_pg_trigger_tgattr - 1])); + pfree(DatumGetPointer(HeapTupleValue(pg_trigger, tgname, values))); + pfree(DatumGetPointer(HeapTupleValue(pg_trigger, tgargs, values))); + pfree(DatumGetPointer(HeapTupleValue(pg_trigger, tgattr, values))); if (oldtablename) - pfree(DatumGetPointer(values[Anum_pg_trigger_tgoldtable - 1])); + pfree(DatumGetPointer(HeapTupleValue(pg_trigger, tgoldtable, values))); if (newtablename) - pfree(DatumGetPointer(values[Anum_pg_trigger_tgnewtable - 1])); + pfree(DatumGetPointer(HeapTupleValue(pg_trigger, tgnewtable, values))); /* * Update relation's pg_class entry; if necessary; and if not, send an SI @@ -1020,9 +1016,9 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, RelationGetRelid(rel)); if (!((Form_pg_class) GETSTRUCT(tuple))->relhastriggers) { - ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true; - - CatalogTupleUpdate(pgrel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_class, relhastriggers, true, (Form_pg_class) GETSTRUCT(tuple), updated); + CatalogTupleUpdate(pgrel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); CommandCounterIncrement(); } @@ -1229,6 +1225,7 @@ TriggerSetParentTrigger(Relation trigRel, newtup; ObjectAddress depender; ObjectAddress referenced; + Bitmapset *updated = NULL; /* * Find the trigger to delete. @@ -1253,9 +1250,9 @@ TriggerSetParentTrigger(Relation trigRel, elog(ERROR, "trigger %u already has a parent trigger", childTrigId); - trigForm->tgparentid = parentTrigId; + HeapTupleUpdateField(pg_trigger, tgparentid, parentTrigId, trigForm, updated); - CatalogTupleUpdate(trigRel, &tuple->t_self, newtup); + CatalogTupleUpdate(trigRel, &tuple->t_self, newtup, updated, NULL); ObjectAddressSet(depender, TriggerRelationId, childTrigId); @@ -1267,9 +1264,9 @@ TriggerSetParentTrigger(Relation trigRel, } else { - trigForm->tgparentid = InvalidOid; + HeapTupleUpdateField(pg_trigger, tgparentid, InvalidOid, trigForm, updated); - CatalogTupleUpdate(trigRel, &tuple->t_self, newtup); + CatalogTupleUpdate(trigRel, &tuple->t_self, newtup, updated, NULL); deleteDependencyRecordsForClass(TriggerRelationId, childTrigId, TriggerRelationId, @@ -1281,6 +1278,7 @@ TriggerSetParentTrigger(Relation trigRel, heap_freetuple(newtup); systable_endscan(tgscan); + bms_free(updated); } @@ -1586,6 +1584,7 @@ renametrig_internal(Relation tgrel, Relation targetrel, HeapTuple trigtup, Form_pg_trigger tgform; ScanKeyData key[2]; SysScanDesc tgscan; + Bitmapset *updated = NULL; /* If the trigger already has the new name, nothing to do. */ tgform = (Form_pg_trigger) GETSTRUCT(trigtup); @@ -1633,7 +1632,7 @@ renametrig_internal(Relation tgrel, Relation targetrel, HeapTuple trigtup, namestrcpy(&tgform->tgname, newname); - CatalogTupleUpdate(tgrel, &tuple->t_self, tuple); + CatalogTupleUpdate(tgrel, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(TriggerRelationId, tgform->oid, 0); @@ -1643,6 +1642,7 @@ renametrig_internal(Relation tgrel, Relation targetrel, HeapTuple trigtup, * (Ideally this should happen automatically...) */ CacheInvalidateRelcache(targetrel); + bms_free(updated); } /* @@ -1784,11 +1784,12 @@ EnableDisableTrigger(Relation rel, const char *tgname, Oid tgparent, /* need to change this one ... make a copy to scribble on */ HeapTuple newtup = heap_copytuple(tuple); Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup); + Bitmapset *updated = NULL; - newtrig->tgenabled = fires_when; - - CatalogTupleUpdate(tgrel, &newtup->t_self, newtup); + HeapTupleUpdateField(pg_trigger, tgenabled, fires_when, newtrig, updated); + CatalogTupleUpdate(tgrel, &newtup->t_self, newtup, updated, NULL); + bms_free(updated); heap_freetuple(newtup); changed = true; diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c index dc7df736fb8..eebf05c2d79 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -187,8 +187,8 @@ DefineTSParser(List *names, List *parameters) ListCell *pl; Relation prsRel; HeapTuple tup; - Datum values[Natts_pg_ts_parser]; - bool nulls[Natts_pg_ts_parser]; + Datum values[Natts_pg_ts_parser] = {0}; + bool nulls[Natts_pg_ts_parser] = {false}; NameData pname; Oid prsOid; Oid namespaceoid; @@ -210,10 +210,10 @@ DefineTSParser(List *names, List *parameters) prsOid = GetNewOidWithIndex(prsRel, TSParserOidIndexId, Anum_pg_ts_parser_oid); - values[Anum_pg_ts_parser_oid - 1] = ObjectIdGetDatum(prsOid); + HeapTupleSetValue(pg_ts_parser, oid, ObjectIdGetDatum(prsOid), values); namestrcpy(&pname, prsname); - values[Anum_pg_ts_parser_prsname - 1] = NameGetDatum(&pname); - values[Anum_pg_ts_parser_prsnamespace - 1] = ObjectIdGetDatum(namespaceoid); + HeapTupleSetValue(pg_ts_parser, prsname, NameGetDatum(&pname), values); + HeapTupleSetValue(pg_ts_parser, prsnamespace, ObjectIdGetDatum(namespaceoid), values); /* * loop over the definition list and extract the information we need. @@ -224,28 +224,23 @@ DefineTSParser(List *names, List *parameters) if (strcmp(defel->defname, "start") == 0) { - values[Anum_pg_ts_parser_prsstart - 1] = - get_ts_parser_func(defel, Anum_pg_ts_parser_prsstart); + HeapTupleSetValue(pg_ts_parser, prsstart, get_ts_parser_func(defel, Anum_pg_ts_parser_prsstart), values); } else if (strcmp(defel->defname, "gettoken") == 0) { - values[Anum_pg_ts_parser_prstoken - 1] = - get_ts_parser_func(defel, Anum_pg_ts_parser_prstoken); + HeapTupleSetValue(pg_ts_parser, prstoken, get_ts_parser_func(defel, Anum_pg_ts_parser_prstoken), values); } else if (strcmp(defel->defname, "end") == 0) { - values[Anum_pg_ts_parser_prsend - 1] = - get_ts_parser_func(defel, Anum_pg_ts_parser_prsend); + HeapTupleSetValue(pg_ts_parser, prsend, get_ts_parser_func(defel, Anum_pg_ts_parser_prsend), values); } else if (strcmp(defel->defname, "headline") == 0) { - values[Anum_pg_ts_parser_prsheadline - 1] = - get_ts_parser_func(defel, Anum_pg_ts_parser_prsheadline); + HeapTupleSetValue(pg_ts_parser, prsheadline, get_ts_parser_func(defel, Anum_pg_ts_parser_prsheadline), values); } else if (strcmp(defel->defname, "lextypes") == 0) { - values[Anum_pg_ts_parser_prslextype - 1] = - get_ts_parser_func(defel, Anum_pg_ts_parser_prslextype); + HeapTupleSetValue(pg_ts_parser, prslextype, get_ts_parser_func(defel, Anum_pg_ts_parser_prslextype), values); } else ereport(ERROR, @@ -257,22 +252,22 @@ DefineTSParser(List *names, List *parameters) /* * Validation */ - if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prsstart - 1]))) + if (!OidIsValid(DatumGetObjectId(HeapTupleValue(pg_ts_parser, prsstart, values)))) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("text search parser start method is required"))); - if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prstoken - 1]))) + if (!OidIsValid(DatumGetObjectId(HeapTupleValue(pg_ts_parser, prstoken, values)))) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("text search parser gettoken method is required"))); - if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prsend - 1]))) + if (!OidIsValid(DatumGetObjectId(HeapTupleValue(pg_ts_parser, prsend, values)))) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("text search parser end method is required"))); - if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prslextype - 1]))) + if (!OidIsValid(DatumGetObjectId(HeapTupleValue(pg_ts_parser, prslextype, values)))) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("text search parser lextypes method is required"))); @@ -282,7 +277,7 @@ DefineTSParser(List *names, List *parameters) */ tup = heap_form_tuple(prsRel->rd_att, values, nulls); - CatalogTupleInsert(prsRel, tup); + CatalogTupleInsert(prsRel, tup, NULL); address = makeParserDependencies(tup); @@ -399,8 +394,8 @@ DefineTSDictionary(List *names, List *parameters) ListCell *pl; Relation dictRel; HeapTuple tup; - Datum values[Natts_pg_ts_dict]; - bool nulls[Natts_pg_ts_dict]; + Datum values[Natts_pg_ts_dict] = {0}; + bool nulls[Natts_pg_ts_dict] = {false}; NameData dname; Oid templId = InvalidOid; List *dictoptions = NIL; @@ -458,21 +453,20 @@ DefineTSDictionary(List *names, List *parameters) dictOid = GetNewOidWithIndex(dictRel, TSDictionaryOidIndexId, Anum_pg_ts_dict_oid); - values[Anum_pg_ts_dict_oid - 1] = ObjectIdGetDatum(dictOid); + HeapTupleSetValue(pg_ts_dict, oid, ObjectIdGetDatum(dictOid), values); namestrcpy(&dname, dictname); - values[Anum_pg_ts_dict_dictname - 1] = NameGetDatum(&dname); - values[Anum_pg_ts_dict_dictnamespace - 1] = ObjectIdGetDatum(namespaceoid); - values[Anum_pg_ts_dict_dictowner - 1] = ObjectIdGetDatum(GetUserId()); - values[Anum_pg_ts_dict_dicttemplate - 1] = ObjectIdGetDatum(templId); + HeapTupleSetValue(pg_ts_dict, dictname, NameGetDatum(&dname), values); + HeapTupleSetValue(pg_ts_dict, dictnamespace, ObjectIdGetDatum(namespaceoid), values); + HeapTupleSetValue(pg_ts_dict, dictowner, ObjectIdGetDatum(GetUserId()), values); + HeapTupleSetValue(pg_ts_dict, dicttemplate, ObjectIdGetDatum(templId), values); if (dictoptions) - values[Anum_pg_ts_dict_dictinitoption - 1] = - PointerGetDatum(serialize_deflist(dictoptions)); + HeapTupleSetValue(pg_ts_dict, dictinitoption, PointerGetDatum(serialize_deflist(dictoptions)), values); else - nulls[Anum_pg_ts_dict_dictinitoption - 1] = true; + HeapTupleSetValueNull(pg_ts_dict, dictinitoption, values, nulls); tup = heap_form_tuple(dictRel->rd_att, values, nulls); - CatalogTupleInsert(dictRel, tup); + CatalogTupleInsert(dictRel, tup, NULL); address = makeDictionaryDependencies(tup); @@ -500,9 +494,9 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt) List *dictoptions; Datum opt; bool isnull; - Datum repl_val[Natts_pg_ts_dict]; - bool repl_null[Natts_pg_ts_dict]; - bool repl_repl[Natts_pg_ts_dict]; + Datum values[Natts_pg_ts_dict] = {0}; + bool nulls[Natts_pg_ts_dict] = {false}; + Bitmapset *updated = NULL; ObjectAddress address; dictId = get_ts_dict_oid(stmt->dictname, false); @@ -564,21 +558,15 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt) /* * Looks good, update */ - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - if (dictoptions) - repl_val[Anum_pg_ts_dict_dictinitoption - 1] = - PointerGetDatum(serialize_deflist(dictoptions)); + HeapTupleUpdateValue(pg_ts_dict, dictinitoption, PointerGetDatum(serialize_deflist(dictoptions)), values, nulls, updated); else - repl_null[Anum_pg_ts_dict_dictinitoption - 1] = true; - repl_repl[Anum_pg_ts_dict_dictinitoption - 1] = true; + HeapTupleUpdateValueNull(pg_ts_dict, dictinitoption, values, nulls, updated); - newtup = heap_modify_tuple(tup, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + newtup = heap_update_tuple(tup, RelationGetDescr(rel), + values, nulls, updated); - CatalogTupleUpdate(rel, &newtup->t_self, newtup); + CatalogTupleUpdate(rel, &newtup->t_self, newtup, updated, NULL); InvokeObjectPostAlterHook(TSDictionaryRelationId, dictId, 0); @@ -594,6 +582,7 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt) ReleaseSysCache(tup); table_close(rel, RowExclusiveLock); + bms_free(updated); return address; } @@ -692,8 +681,8 @@ DefineTSTemplate(List *names, List *parameters) ListCell *pl; Relation tmplRel; HeapTuple tup; - Datum values[Natts_pg_ts_template]; - bool nulls[Natts_pg_ts_template]; + Datum values[Natts_pg_ts_template] = {0}; + bool nulls[Natts_pg_ts_template] = {false}; NameData dname; int i; Oid tmplOid; @@ -719,10 +708,10 @@ DefineTSTemplate(List *names, List *parameters) tmplOid = GetNewOidWithIndex(tmplRel, TSTemplateOidIndexId, Anum_pg_ts_dict_oid); - values[Anum_pg_ts_template_oid - 1] = ObjectIdGetDatum(tmplOid); + HeapTupleSetValue(pg_ts_template, oid, ObjectIdGetDatum(tmplOid), values); namestrcpy(&dname, tmplname); - values[Anum_pg_ts_template_tmplname - 1] = NameGetDatum(&dname); - values[Anum_pg_ts_template_tmplnamespace - 1] = ObjectIdGetDatum(namespaceoid); + HeapTupleSetValue(pg_ts_template, tmplname, NameGetDatum(&dname), values); + HeapTupleSetValue(pg_ts_template, tmplnamespace, ObjectIdGetDatum(namespaceoid), values); /* * loop over the definition list and extract the information we need. @@ -733,15 +722,11 @@ DefineTSTemplate(List *names, List *parameters) if (strcmp(defel->defname, "init") == 0) { - values[Anum_pg_ts_template_tmplinit - 1] = - get_ts_template_func(defel, Anum_pg_ts_template_tmplinit); - nulls[Anum_pg_ts_template_tmplinit - 1] = false; + HeapTupleSetValue(pg_ts_template, tmplinit, get_ts_template_func(defel, Anum_pg_ts_template_tmplinit), values); } else if (strcmp(defel->defname, "lexize") == 0) { - values[Anum_pg_ts_template_tmpllexize - 1] = - get_ts_template_func(defel, Anum_pg_ts_template_tmpllexize); - nulls[Anum_pg_ts_template_tmpllexize - 1] = false; + HeapTupleSetValue(pg_ts_template, tmpllexize, get_ts_template_func(defel, Anum_pg_ts_template_tmpllexize), values); } else ereport(ERROR, @@ -753,7 +738,7 @@ DefineTSTemplate(List *names, List *parameters) /* * Validation */ - if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_template_tmpllexize - 1]))) + if (!OidIsValid(DatumGetObjectId(HeapTupleValue(pg_ts_template, tmpllexize, values)))) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("text search template lexize method is required"))); @@ -763,7 +748,7 @@ DefineTSTemplate(List *names, List *parameters) */ tup = heap_form_tuple(tmplRel->rd_att, values, nulls); - CatalogTupleInsert(tmplRel, tup); + CatalogTupleInsert(tmplRel, tup, NULL); address = makeTSTemplateDependencies(tup); @@ -901,8 +886,8 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied) Relation cfgRel; Relation mapRel = NULL; HeapTuple tup; - Datum values[Natts_pg_ts_config]; - bool nulls[Natts_pg_ts_config]; + Datum values[Natts_pg_ts_config] = {0}; + bool nulls[Natts_pg_ts_config] = {false}; AclResult aclresult; Oid namespaceoid; char *cfgname; @@ -991,16 +976,16 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied) cfgOid = GetNewOidWithIndex(cfgRel, TSConfigOidIndexId, Anum_pg_ts_config_oid); - values[Anum_pg_ts_config_oid - 1] = ObjectIdGetDatum(cfgOid); + HeapTupleSetValue(pg_ts_config, oid, ObjectIdGetDatum(cfgOid), values); namestrcpy(&cname, cfgname); - values[Anum_pg_ts_config_cfgname - 1] = NameGetDatum(&cname); - values[Anum_pg_ts_config_cfgnamespace - 1] = ObjectIdGetDatum(namespaceoid); - values[Anum_pg_ts_config_cfgowner - 1] = ObjectIdGetDatum(GetUserId()); - values[Anum_pg_ts_config_cfgparser - 1] = ObjectIdGetDatum(prsOid); + HeapTupleSetValue(pg_ts_config, cfgname, NameGetDatum(&cname), values); + HeapTupleSetValue(pg_ts_config, cfgnamespace, ObjectIdGetDatum(namespaceoid), values); + HeapTupleSetValue(pg_ts_config, cfgowner, ObjectIdGetDatum(GetUserId()), values); + HeapTupleSetValue(pg_ts_config, cfgparser, ObjectIdGetDatum(prsOid), values); tup = heap_form_tuple(cfgRel->rd_att, values, nulls); - CatalogTupleInsert(cfgRel, tup); + CatalogTupleInsert(cfgRel, tup, NULL); if (OidIsValid(sourceOid)) { @@ -1058,10 +1043,10 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied) memset(slot[slot_stored_count]->tts_isnull, false, slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool)); - slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_mapcfg - 1] = ObjectIdGetDatum(cfgOid); - slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_maptokentype - 1] = Int32GetDatum(cfgmap->maptokentype); - slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_mapseqno - 1] = Int32GetDatum(cfgmap->mapseqno); - slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(cfgmap->mapdict); + HeapTupleSetValue(pg_ts_config_map, mapcfg, ObjectIdGetDatum(cfgOid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_ts_config_map, maptokentype, Int32GetDatum(cfgmap->maptokentype), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_ts_config_map, mapseqno, Int32GetDatum(cfgmap->mapseqno), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_ts_config_map, mapdict, ObjectIdGetDatum(cfgmap->mapdict), slot[slot_stored_count]->tts_values); ExecStoreVirtualTuple(slot[slot_stored_count]); slot_stored_count++; @@ -1069,16 +1054,16 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied) /* If slots are full, insert a batch of tuples */ if (slot_stored_count == max_slots) { - CatalogTuplesMultiInsertWithInfo(mapRel, slot, slot_stored_count, - indstate); + CatalogTuplesMultiInsert(mapRel, slot, slot_stored_count, + indstate); slot_stored_count = 0; } } /* Insert any tuples left in the buffer */ if (slot_stored_count > 0) - CatalogTuplesMultiInsertWithInfo(mapRel, slot, slot_stored_count, - indstate); + CatalogTuplesMultiInsert(mapRel, slot, slot_stored_count, + indstate); for (int i = 0; i < slot_init_count; i++) ExecDropSingleTupleTableSlot(slot[i]); @@ -1402,22 +1387,18 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, */ if (cfgmap->mapdict == dictOld) { - Datum repl_val[Natts_pg_ts_config_map]; - bool repl_null[Natts_pg_ts_config_map]; - bool repl_repl[Natts_pg_ts_config_map]; + Datum values[Natts_pg_ts_config_map] = {0}; + bool nulls[Natts_pg_ts_config_map] = {false}; + Bitmapset *updated = NULL; HeapTuple newtup; - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_val[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(dictNew); - repl_repl[Anum_pg_ts_config_map_mapdict - 1] = true; + HeapTupleUpdateValue(pg_ts_config_map, mapdict, ObjectIdGetDatum(dictNew), values, nulls, updated); - newtup = heap_modify_tuple(maptup, + newtup = heap_update_tuple(maptup, RelationGetDescr(relMap), - repl_val, repl_null, repl_repl); - CatalogTupleUpdateWithInfo(relMap, &newtup->t_self, newtup, indstate); + values, nulls, updated); + CatalogTupleUpdate(relMap, &newtup->t_self, newtup, updated, indstate); + bms_free(updated); } } @@ -1451,10 +1432,10 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, memset(slot[slotCount]->tts_isnull, false, slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool)); - slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapcfg - 1] = ObjectIdGetDatum(cfgId); - slot[slotCount]->tts_values[Anum_pg_ts_config_map_maptokentype - 1] = Int32GetDatum(ts->num); - slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapseqno - 1] = Int32GetDatum(j + 1); - slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(dictIds[j]); + HeapTupleSetValue(pg_ts_config_map, mapcfg, ObjectIdGetDatum(cfgId), slot[slotCount]->tts_values); + HeapTupleSetValue(pg_ts_config_map, maptokentype, Int32GetDatum(ts->num), slot[slotCount]->tts_values); + HeapTupleSetValue(pg_ts_config_map, mapseqno, Int32GetDatum(j + 1), slot[slotCount]->tts_values); + HeapTupleSetValue(pg_ts_config_map, mapdict, ObjectIdGetDatum(dictIds[j]), slot[slotCount]->tts_values); ExecStoreVirtualTuple(slot[slotCount]); slotCount++; @@ -1462,8 +1443,8 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, /* If slots are full, insert a batch of tuples */ if (slotCount == nslots) { - CatalogTuplesMultiInsertWithInfo(relMap, slot, slotCount, - indstate); + CatalogTuplesMultiInsert(relMap, slot, slotCount, + indstate); slotCount = 0; } } @@ -1471,8 +1452,8 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, /* Insert any tuples left in the buffer */ if (slotCount > 0) - CatalogTuplesMultiInsertWithInfo(relMap, slot, slotCount, - indstate); + CatalogTuplesMultiInsert(relMap, slot, slotCount, + indstate); for (i = 0; i < nslots; i++) ExecDropSingleTupleTableSlot(slot[i]); diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 5979580139f..d7fa069a17a 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -2620,9 +2620,9 @@ AlterDomainDefault(List *names, Node *defaultRaw) Relation rel; char *defaultValue; Node *defaultExpr = NULL; /* NULL if no default specified */ - Datum new_record[Natts_pg_type] = {0}; - bool new_record_nulls[Natts_pg_type] = {0}; - bool new_record_repl[Natts_pg_type] = {0}; + Datum values[Natts_pg_type] = {0}; + bool nulls[Natts_pg_type] = {false}; + Bitmapset *updated = NULL; HeapTuple newtuple; Form_pg_type typTup; ObjectAddress address; @@ -2670,10 +2670,8 @@ AlterDomainDefault(List *names, Node *defaultRaw) { /* Default is NULL, drop it */ defaultExpr = NULL; - new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true; - new_record_repl[Anum_pg_type_typdefaultbin - 1] = true; - new_record_nulls[Anum_pg_type_typdefault - 1] = true; - new_record_repl[Anum_pg_type_typdefault - 1] = true; + HeapTupleUpdateValueNull(pg_type, typdefaultbin, values, nulls, updated); + HeapTupleUpdateValueNull(pg_type, typdefault, values, nulls, updated); } else { @@ -2688,27 +2686,21 @@ AlterDomainDefault(List *names, Node *defaultRaw) /* * Form an updated tuple with the new default and write it back. */ - new_record[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(nodeToString(defaultExpr)); - - new_record_repl[Anum_pg_type_typdefaultbin - 1] = true; - new_record[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultValue); - new_record_repl[Anum_pg_type_typdefault - 1] = true; + HeapTupleUpdateValue(pg_type, typdefaultbin, CStringGetTextDatum(nodeToString(defaultExpr)), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typdefault, CStringGetTextDatum(defaultValue), values, nulls, updated); } } else { /* ALTER ... DROP DEFAULT */ - new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true; - new_record_repl[Anum_pg_type_typdefaultbin - 1] = true; - new_record_nulls[Anum_pg_type_typdefault - 1] = true; - new_record_repl[Anum_pg_type_typdefault - 1] = true; + HeapTupleUpdateValueNull(pg_type, typdefaultbin, values, nulls, updated); + HeapTupleUpdateValueNull(pg_type, typdefault, values, nulls, updated); } - newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), - new_record, new_record_nulls, - new_record_repl); + newtuple = heap_update_tuple(tup, RelationGetDescr(rel), + values, nulls, updated); - CatalogTupleUpdate(rel, &tup->t_self, newtuple); + CatalogTupleUpdate(rel, &tup->t_self, newtuple, updated, NULL); /* Rebuild dependencies */ GenerateTypeDependencies(newtuple, @@ -2728,6 +2720,7 @@ AlterDomainDefault(List *names, Node *defaultRaw) /* Clean up */ table_close(rel, RowExclusiveLock); heap_freetuple(newtuple); + bms_free(updated); return address; } @@ -2748,6 +2741,7 @@ AlterDomainNotNull(List *names, bool notNull) HeapTuple tup; Form_pg_type typTup; ObjectAddress address = InvalidObjectAddress; + Bitmapset *updated = NULL; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); @@ -2803,9 +2797,9 @@ AlterDomainNotNull(List *names, bool notNull) * Okay to update pg_type row. We can scribble on typTup because it's a * copy. */ - typTup->typnotnull = notNull; + HeapTupleUpdateField(pg_type, typnotnull, notNull, typTup, updated); - CatalogTupleUpdate(typrel, &tup->t_self, tup); + CatalogTupleUpdate(typrel, &tup->t_self, tup, updated, NULL); InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0); @@ -2814,6 +2808,7 @@ AlterDomainNotNull(List *names, bool notNull) /* Clean up */ heap_freetuple(tup); table_close(typrel, RowExclusiveLock); + bms_free(updated); return address; } @@ -2839,6 +2834,7 @@ AlterDomainDropConstraint(List *names, const char *constrName, HeapTuple contup; bool found = false; ObjectAddress address; + Bitmapset *updated = NULL; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); @@ -2882,8 +2878,8 @@ AlterDomainDropConstraint(List *names, const char *constrName, if (construct->contype == CONSTRAINT_NOTNULL) { - ((Form_pg_type) GETSTRUCT(tup))->typnotnull = false; - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleUpdateField(pg_type, typnotnull, false, (Form_pg_type) GETSTRUCT(tup), updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); } conobj.classId = ConstraintRelationId; @@ -2922,6 +2918,7 @@ AlterDomainDropConstraint(List *names, const char *constrName, /* Clean up */ table_close(rel, RowExclusiveLock); + bms_free(updated); return address; } @@ -2943,6 +2940,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint, Constraint *constr; char *ccbin; ObjectAddress address = InvalidObjectAddress; + Bitmapset *updated = NULL; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); @@ -3011,14 +3009,15 @@ AlterDomainAddConstraint(List *names, Node *newConstraint, if (!constr->skip_validation) validateDomainNotNullConstraint(domainoid); - typTup->typnotnull = true; - CatalogTupleUpdate(typrel, &tup->t_self, tup); + HeapTupleUpdateField(pg_type, typnotnull, true, typTup, updated); + CatalogTupleUpdate(typrel, &tup->t_self, tup, updated, NULL); } ObjectAddressSet(address, TypeRelationId, domainoid); /* Clean up */ table_close(typrel, RowExclusiveLock); + bms_free(updated); return address; } @@ -3045,6 +3044,7 @@ AlterDomainValidateConstraint(List *names, const char *constrName) HeapTuple copyTuple; ScanKeyData skey[3]; ObjectAddress address; + Bitmapset *updated = NULL; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); @@ -3110,8 +3110,8 @@ AlterDomainValidateConstraint(List *names, const char *constrName) */ copyTuple = heap_copytuple(tuple); copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); - copy_con->convalidated = true; - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); + HeapTupleUpdateField(pg_constraint, convalidated, true, copy_con, updated); + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple, updated, NULL); InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); @@ -3125,6 +3125,7 @@ AlterDomainValidateConstraint(List *names, const char *constrName) table_close(conrel, RowExclusiveLock); ReleaseSysCache(tup); + bms_free(updated); return address; } @@ -3999,9 +4000,9 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) Relation rel; HeapTuple tup; Form_pg_type typTup; - Datum repl_val[Natts_pg_type]; - bool repl_null[Natts_pg_type]; - bool repl_repl[Natts_pg_type]; + Datum values[Natts_pg_type] = {0}; + bool nulls[Natts_pg_type] = {false}; + Bitmapset *updated = NULL; Acl *newAcl; Datum aclDatum; bool isNull; @@ -4013,11 +4014,7 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) elog(ERROR, "cache lookup failed for type %u", typeOid); typTup = (Form_pg_type) GETSTRUCT(tup); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_type_typowner - 1] = true; - repl_val[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_type, typowner, ObjectIdGetDatum(newOwnerId), values, nulls, updated); aclDatum = heap_getattr(tup, Anum_pg_type_typacl, @@ -4028,14 +4025,12 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) { newAcl = aclnewowner(DatumGetAclP(aclDatum), typTup->typowner, newOwnerId); - repl_repl[Anum_pg_type_typacl - 1] = true; - repl_val[Anum_pg_type_typacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_type, typacl, PointerGetDatum(newAcl), values, nulls, updated); } - tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, - repl_repl); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); /* If it has an array type, update that too */ if (OidIsValid(typTup->typarray)) @@ -4056,6 +4051,7 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) /* Clean up */ table_close(rel, RowExclusiveLock); + bms_free(updated); } /* @@ -4176,6 +4172,7 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, Oid arrayOid; bool isCompositeType; ObjectAddress thisobj; + Bitmapset *updated = NULL; /* * Make sure we haven't moved this object previously. @@ -4241,9 +4238,9 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, /* OK, modify the pg_type row */ /* tup is a copy, so we can scribble directly on it */ - typform->typnamespace = nspOid; + HeapTupleUpdateField(pg_type, typnamespace, nspOid, typform, updated); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); } /* @@ -4307,6 +4304,7 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, true, /* errorOnTableType */ objsMoved); + bms_free(updated); return oldNspOid; } @@ -4574,9 +4572,9 @@ AlterTypeRecurse(Oid typeOid, bool isImplicitArray, HeapTuple tup, Relation catalog, AlterTypeRecurseParams *atparams) { - Datum values[Natts_pg_type]; - bool nulls[Natts_pg_type]; - bool replaces[Natts_pg_type]; + Datum values[Natts_pg_type] = {0}; + bool nulls[Natts_pg_type] = {false}; + Bitmapset *updated = NULL; HeapTuple newtup; SysScanDesc scan; ScanKeyData key[1]; @@ -4586,50 +4584,25 @@ AlterTypeRecurse(Oid typeOid, bool isImplicitArray, check_stack_depth(); /* Update the current type's tuple */ - memset(values, 0, sizeof(values)); - memset(nulls, 0, sizeof(nulls)); - memset(replaces, 0, sizeof(replaces)); - if (atparams->updateStorage) - { - replaces[Anum_pg_type_typstorage - 1] = true; - values[Anum_pg_type_typstorage - 1] = CharGetDatum(atparams->storage); - } + HeapTupleUpdateValue(pg_type, typstorage, CharGetDatum(atparams->storage), values, nulls, updated); if (atparams->updateReceive) - { - replaces[Anum_pg_type_typreceive - 1] = true; - values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(atparams->receiveOid); - } + HeapTupleUpdateValue(pg_type, typreceive, ObjectIdGetDatum(atparams->receiveOid), values, nulls, updated); if (atparams->updateSend) - { - replaces[Anum_pg_type_typsend - 1] = true; - values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(atparams->sendOid); - } + HeapTupleUpdateValue(pg_type, typsend, ObjectIdGetDatum(atparams->sendOid), values, nulls, updated); if (atparams->updateTypmodin) - { - replaces[Anum_pg_type_typmodin - 1] = true; - values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(atparams->typmodinOid); - } + HeapTupleUpdateValue(pg_type, typmodin, ObjectIdGetDatum(atparams->typmodinOid), values, nulls, updated); if (atparams->updateTypmodout) - { - replaces[Anum_pg_type_typmodout - 1] = true; - values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(atparams->typmodoutOid); - } + HeapTupleUpdateValue(pg_type, typmodout, ObjectIdGetDatum(atparams->typmodoutOid), values, nulls, updated); if (atparams->updateAnalyze) - { - replaces[Anum_pg_type_typanalyze - 1] = true; - values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(atparams->analyzeOid); - } + HeapTupleUpdateValue(pg_type, typanalyze, ObjectIdGetDatum(atparams->analyzeOid), values, nulls, updated); if (atparams->updateSubscript) - { - replaces[Anum_pg_type_typsubscript - 1] = true; - values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(atparams->subscriptOid); - } + HeapTupleUpdateValue(pg_type, typsubscript, ObjectIdGetDatum(atparams->subscriptOid), values, nulls, updated); - newtup = heap_modify_tuple(tup, RelationGetDescr(catalog), - values, nulls, replaces); + newtup = heap_update_tuple(tup, RelationGetDescr(catalog), + values, nulls, updated); - CatalogTupleUpdate(catalog, &newtup->t_self, newtup); + CatalogTupleUpdate(catalog, &newtup->t_self, newtup, updated, NULL); /* Rebuild dependencies for this type */ GenerateTypeDependencies(newtup, @@ -4714,4 +4687,5 @@ AlterTypeRecurse(Oid typeOid, bool isImplicitArray, } systable_endscan(scan); + bms_free(updated); } diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 6ae42ea5656..2bcfb7f5bc7 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -134,8 +134,8 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) Relation pg_authid_rel; TupleDesc pg_authid_dsc; HeapTuple tuple; - Datum new_record[Natts_pg_authid] = {0}; - bool new_record_nulls[Natts_pg_authid] = {0}; + Datum values[Natts_pg_authid] = {0}; + bool nulls[Natts_pg_authid] = {false}; Oid currentUserId = GetUserId(); Oid roleid; ListCell *item; @@ -405,15 +405,14 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) /* * Build a tuple to insert */ - new_record[Anum_pg_authid_rolname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->role)); - new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper); - new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit); - new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole); - new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb); - new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin); - new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication); - new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit); + HeapTupleSetValue(pg_authid, rolname, DirectFunctionCall1(namein, CStringGetDatum(stmt->role)), values); + HeapTupleSetValue(pg_authid, rolsuper, BoolGetDatum(issuper), values); + HeapTupleSetValue(pg_authid, rolinherit, BoolGetDatum(inherit), values); + HeapTupleSetValue(pg_authid, rolcreaterole, BoolGetDatum(createrole), values); + HeapTupleSetValue(pg_authid, rolcreatedb, BoolGetDatum(createdb), values); + HeapTupleSetValue(pg_authid, rolcanlogin, BoolGetDatum(canlogin), values); + HeapTupleSetValue(pg_authid, rolreplication, BoolGetDatum(isreplication), values); + HeapTupleSetValue(pg_authid, rolconnlimit, Int32GetDatum(connlimit), values); if (password) { @@ -437,24 +436,24 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) { ereport(NOTICE, (errmsg("empty string is not a valid password, clearing password"))); - new_record_nulls[Anum_pg_authid_rolpassword - 1] = true; + HeapTupleSetValueNull(pg_authid, rolpassword, values, nulls); } else { /* Encrypt the password to the requested format. */ shadow_pass = encrypt_password(Password_encryption, stmt->role, password); - new_record[Anum_pg_authid_rolpassword - 1] = - CStringGetTextDatum(shadow_pass); + HeapTupleSetValue(pg_authid, rolpassword, CStringGetTextDatum(shadow_pass), values); } } else - new_record_nulls[Anum_pg_authid_rolpassword - 1] = true; + HeapTupleSetValueNull(pg_authid, rolpassword, values, nulls); - new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum; - new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null; + HeapTupleSetValue(pg_authid, rolvaliduntil, validUntil_datum, values); + if (validUntil_null) + HeapTupleSetValueNull(pg_authid, rolvaliduntil, values, nulls); - new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls); + HeapTupleSetValue(pg_authid, rolbypassrls, BoolGetDatum(bypassrls), values); /* * pg_largeobject_metadata contains pg_authid.oid's, so we use the @@ -476,14 +475,14 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) Anum_pg_authid_oid); } - new_record[Anum_pg_authid_oid - 1] = ObjectIdGetDatum(roleid); + HeapTupleSetValue(pg_authid, oid, ObjectIdGetDatum(roleid), values); - tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls); + tuple = heap_form_tuple(pg_authid_dsc, values, nulls); /* * Insert new record in the pg_authid table */ - CatalogTupleInsert(pg_authid_rel, tuple); + CatalogTupleInsert(pg_authid_rel, tuple, NULL); /* * Advance command counter so we can see new record; else tests in @@ -618,9 +617,9 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt) { - Datum new_record[Natts_pg_authid] = {0}; - bool new_record_nulls[Natts_pg_authid] = {0}; - bool new_record_repl[Natts_pg_authid] = {0}; + Datum values[Natts_pg_authid] = {0}; + bool nulls[Natts_pg_authid] = {false}; + Bitmapset *updated = NULL; Relation pg_authid_rel; TupleDesc pg_authid_dsc; HeapTuple tuple, @@ -870,45 +869,26 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt) errdetail("The bootstrap superuser must have the %s attribute.", "SUPERUSER"))); - new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(should_be_super); - new_record_repl[Anum_pg_authid_rolsuper - 1] = true; + HeapTupleUpdateValue(pg_authid, rolsuper, BoolGetDatum(should_be_super), values, nulls, updated); } if (dinherit) - { - new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(boolVal(dinherit->arg)); - new_record_repl[Anum_pg_authid_rolinherit - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolinherit, BoolGetDatum(boolVal(dinherit->arg)), values, nulls, updated); if (dcreaterole) - { - new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(boolVal(dcreaterole->arg)); - new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolcreaterole, BoolGetDatum(boolVal(dcreaterole->arg)), values, nulls, updated); if (dcreatedb) - { - new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(boolVal(dcreatedb->arg)); - new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolcreatedb, BoolGetDatum(boolVal(dcreatedb->arg)), values, nulls, updated); if (dcanlogin) - { - new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(boolVal(dcanlogin->arg)); - new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolcanlogin, BoolGetDatum(boolVal(dcanlogin->arg)), values, nulls, updated); if (disreplication) - { - new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(boolVal(disreplication->arg)); - new_record_repl[Anum_pg_authid_rolreplication - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolreplication, BoolGetDatum(boolVal(disreplication->arg)), values, nulls, updated); if (dconnlimit) - { - new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit); - new_record_repl[Anum_pg_authid_rolconnlimit - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolconnlimit, Int32GetDatum(connlimit), values, nulls, updated); /* password */ if (password) @@ -922,40 +902,33 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt) { ereport(NOTICE, (errmsg("empty string is not a valid password, clearing password"))); - new_record_nulls[Anum_pg_authid_rolpassword - 1] = true; + HeapTupleSetValueNull(pg_authid, rolpassword, values, nulls); } else { /* Encrypt the password to the requested format. */ shadow_pass = encrypt_password(Password_encryption, rolename, password); - new_record[Anum_pg_authid_rolpassword - 1] = - CStringGetTextDatum(shadow_pass); + HeapTupleUpdateValue(pg_authid, rolpassword, CStringGetTextDatum(shadow_pass), values, nulls, updated); } - new_record_repl[Anum_pg_authid_rolpassword - 1] = true; } /* unset password */ if (dpassword && dpassword->arg == NULL) - { - new_record_repl[Anum_pg_authid_rolpassword - 1] = true; - new_record_nulls[Anum_pg_authid_rolpassword - 1] = true; - } + HeapTupleUpdateValueNull(pg_authid, rolpassword, values, nulls, updated); /* valid until */ - new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum; - new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null; - new_record_repl[Anum_pg_authid_rolvaliduntil - 1] = true; + HeapTupleUpdateValue(pg_authid, rolvaliduntil, validUntil_datum, values, nulls, updated); + if (validUntil_null) + HeapTupleUpdateValueNull(pg_authid, rolvaliduntil, values, nulls, updated); if (dbypassRLS) - { - new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(boolVal(dbypassRLS->arg)); - new_record_repl[Anum_pg_authid_rolbypassrls - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolbypassrls, BoolGetDatum(boolVal(dbypassRLS->arg)), values, nulls, updated); - new_tuple = heap_modify_tuple(tuple, pg_authid_dsc, new_record, - new_record_nulls, new_record_repl); - CatalogTupleUpdate(pg_authid_rel, &tuple->t_self, new_tuple); + new_tuple = heap_update_tuple(tuple, pg_authid_dsc, values, + nulls, updated); + CatalogTupleUpdate(pg_authid_rel, &tuple->t_self, new_tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0); @@ -1339,10 +1312,9 @@ RenameRole(const char *oldname, const char *newname) Relation rel; Datum datum; bool isnull; - Datum repl_val[Natts_pg_authid]; - bool repl_null[Natts_pg_authid]; - bool repl_repl[Natts_pg_authid]; - int i; + Datum values[Natts_pg_authid] = {0}; + bool nulls[Natts_pg_authid] = {false}; + Bitmapset *updated = NULL; Oid roleid; ObjectAddress address; Form_pg_authid authform; @@ -1433,29 +1405,22 @@ RenameRole(const char *oldname, const char *newname) "CREATEROLE", "ADMIN", NameStr(authform->rolname)))); } - /* OK, construct the modified tuple */ - for (i = 0; i < Natts_pg_authid; i++) - repl_repl[i] = false; - - repl_repl[Anum_pg_authid_rolname - 1] = true; - repl_val[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein, - CStringGetDatum(newname)); - repl_null[Anum_pg_authid_rolname - 1] = false; + HeapTupleUpdateValue(pg_authid, rolname, DirectFunctionCall1(namein, CStringGetDatum(newname)), values, nulls, updated); datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull); if (!isnull && get_password_type(TextDatumGetCString(datum)) == PASSWORD_TYPE_MD5) { /* MD5 uses the username as salt, so just clear it on a rename */ - repl_repl[Anum_pg_authid_rolpassword - 1] = true; - repl_null[Anum_pg_authid_rolpassword - 1] = true; + HeapTupleUpdateValueNull(pg_authid, rolpassword, values, nulls, updated); ereport(NOTICE, (errmsg("MD5 password cleared because of role rename"))); } - newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl); - CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple); + newtuple = heap_update_tuple(oldtuple, dsc, values, nulls, updated); + CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0); @@ -1823,17 +1788,14 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, Oid memberid = lfirst_oid(iditem); HeapTuple authmem_tuple; HeapTuple tuple; - Datum new_record[Natts_pg_auth_members] = {0}; - bool new_record_nulls[Natts_pg_auth_members] = {0}; - bool new_record_repl[Natts_pg_auth_members] = {0}; + Datum values[Natts_pg_auth_members] = {0}; + bool nulls[Natts_pg_auth_members] = {false}; + Bitmapset *updated = NULL; /* Common initialization for possible insert or update */ - new_record[Anum_pg_auth_members_roleid - 1] = - ObjectIdGetDatum(roleid); - new_record[Anum_pg_auth_members_member - 1] = - ObjectIdGetDatum(memberid); - new_record[Anum_pg_auth_members_grantor - 1] = - ObjectIdGetDatum(grantorId); + HeapTupleUpdateValue(pg_auth_members, roleid, ObjectIdGetDatum(roleid), values, nulls, updated); + HeapTupleUpdateValue(pg_auth_members, member, ObjectIdGetDatum(memberid), values, nulls, updated); + HeapTupleUpdateValue(pg_auth_members, grantor, ObjectIdGetDatum(grantorId), values, nulls, updated); /* Find any existing tuple */ authmem_tuple = SearchSysCache3(AUTHMEMROLEMEM, @@ -1857,30 +1819,21 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, if ((popt->specified & GRANT_ROLE_SPECIFIED_ADMIN) != 0 && authmem_form->admin_option != popt->admin) { - new_record[Anum_pg_auth_members_admin_option - 1] = - BoolGetDatum(popt->admin); - new_record_repl[Anum_pg_auth_members_admin_option - 1] = - true; + HeapTupleUpdateValue(pg_auth_members, admin_option, BoolGetDatum(popt->admin), values, nulls, updated); at_least_one_change = true; } if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0 && authmem_form->inherit_option != popt->inherit) { - new_record[Anum_pg_auth_members_inherit_option - 1] = - BoolGetDatum(popt->inherit); - new_record_repl[Anum_pg_auth_members_inherit_option - 1] = - true; + HeapTupleUpdateValue(pg_auth_members, inherit_option, BoolGetDatum(popt->inherit), values, nulls, updated); at_least_one_change = true; } if ((popt->specified & GRANT_ROLE_SPECIFIED_SET) != 0 && authmem_form->set_option != popt->set) { - new_record[Anum_pg_auth_members_set_option - 1] = - BoolGetDatum(popt->set); - new_record_repl[Anum_pg_auth_members_set_option - 1] = - true; + HeapTupleUpdateValue(pg_auth_members, set_option, BoolGetDatum(popt->set), values, nulls, updated); at_least_one_change = true; } @@ -1894,10 +1847,8 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, continue; } - tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc, - new_record, - new_record_nulls, new_record_repl); - CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple); + tuple = heap_update_tuple(authmem_tuple, pg_authmem_dsc, values, nulls, updated); + CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple, updated, NULL); ReleaseSysCache(authmem_tuple); } @@ -1911,10 +1862,8 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, * Either they were specified, or the defaults as set by * InitGrantRoleOptions are correct. */ - new_record[Anum_pg_auth_members_admin_option - 1] = - BoolGetDatum(popt->admin); - new_record[Anum_pg_auth_members_set_option - 1] = - BoolGetDatum(popt->set); + HeapTupleSetValue(pg_auth_members, admin_option, BoolGetDatum(popt->admin), values); + HeapTupleSetValue(pg_auth_members, set_option, BoolGetDatum(popt->set), values); /* * If the user specified a value for the inherit option, use @@ -1922,8 +1871,7 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, * on the role-level property. */ if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0) - new_record[Anum_pg_auth_members_inherit_option - 1] = - BoolGetDatum(popt->inherit); + HeapTupleSetValue(pg_auth_members, inherit_option, BoolGetDatum(popt->inherit), values); else { HeapTuple mrtup; @@ -1933,18 +1881,16 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, if (!HeapTupleIsValid(mrtup)) elog(ERROR, "cache lookup failed for role %u", memberid); mrform = (Form_pg_authid) GETSTRUCT(mrtup); - new_record[Anum_pg_auth_members_inherit_option - 1] = - BoolGetDatum(mrform->rolinherit); + HeapTupleSetValue(pg_auth_members, inherit_option, BoolGetDatum(mrform->rolinherit), values); ReleaseSysCache(mrtup); } /* get an OID for the new row and insert it */ objectId = GetNewOidWithIndex(pg_authmem_rel, AuthMemOidIndexId, Anum_pg_auth_members_oid); - new_record[Anum_pg_auth_members_oid - 1] = ObjectIdGetDatum(objectId); - tuple = heap_form_tuple(pg_authmem_dsc, - new_record, new_record_nulls); - CatalogTupleInsert(pg_authmem_rel, tuple); + HeapTupleSetValue(pg_auth_members, oid, ObjectIdGetDatum(objectId), values); + tuple = heap_form_tuple(pg_authmem_dsc, values, nulls); + CatalogTupleInsert(pg_authmem_rel, tuple, NULL); /* updateAclDependencies wants to pfree array inputs */ newmembers[0] = grantorId; @@ -1954,6 +1900,8 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, 1, newmembers); } + bms_free(updated); + /* CCI after each change, in case there are duplicates in list */ CommandCounterIncrement(); } @@ -1986,7 +1934,6 @@ DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid, ListCell *iditem; CatCList *memlist; RevokeRoleGrantAction *actions; - int i; Assert(list_length(memberSpecs) == list_length(memberIds)); @@ -2034,7 +1981,7 @@ DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid, * left alone, deleted, or just have the admin_option flag cleared. * Perform the appropriate action in each case. */ - for (i = 0; i < memlist->n_members; ++i) + for (int i = 0; i < memlist->n_members; ++i) { HeapTuple authmem_tuple; Form_pg_auth_members authmem_form; @@ -2059,39 +2006,24 @@ DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid, { /* Just turn off the specified option */ HeapTuple tuple; - Datum new_record[Natts_pg_auth_members] = {0}; - bool new_record_nulls[Natts_pg_auth_members] = {0}; - bool new_record_repl[Natts_pg_auth_members] = {0}; + Datum values[Natts_pg_auth_members] = {0}; + bool nulls[Natts_pg_auth_members] = {false}; + Bitmapset *updated = NULL; /* Build a tuple to update with */ if (actions[i] == RRG_REMOVE_ADMIN_OPTION) - { - new_record[Anum_pg_auth_members_admin_option - 1] = - BoolGetDatum(false); - new_record_repl[Anum_pg_auth_members_admin_option - 1] = - true; - } + HeapTupleUpdateValue(pg_auth_members, admin_option, BoolGetDatum(false), values, nulls, updated); else if (actions[i] == RRG_REMOVE_INHERIT_OPTION) - { - new_record[Anum_pg_auth_members_inherit_option - 1] = - BoolGetDatum(false); - new_record_repl[Anum_pg_auth_members_inherit_option - 1] = - true; - } + HeapTupleUpdateValue(pg_auth_members, inherit_option, BoolGetDatum(false), values, nulls, updated); else if (actions[i] == RRG_REMOVE_SET_OPTION) - { - new_record[Anum_pg_auth_members_set_option - 1] = - BoolGetDatum(false); - new_record_repl[Anum_pg_auth_members_set_option - 1] = - true; - } + HeapTupleUpdateValue(pg_auth_members, set_option, BoolGetDatum(false), values, nulls, updated); else elog(ERROR, "unknown role revoke action"); - tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc, - new_record, - new_record_nulls, new_record_repl); - CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple); + tuple = heap_update_tuple(authmem_tuple, pg_authmem_dsc, + values, nulls, updated); + CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); } } diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 4632aa8115d..8b077b7b43f 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -312,8 +312,8 @@ replorigin_create(const char *roname) for (roident = InvalidOid + 1; roident < PG_UINT16_MAX; roident++) { - bool nulls[Natts_pg_replication_origin]; - Datum values[Natts_pg_replication_origin]; + Datum values[Natts_pg_replication_origin] = {0}; + bool nulls[Natts_pg_replication_origin] = {false}; bool collides; CHECK_FOR_INTERRUPTS(); @@ -340,11 +340,11 @@ replorigin_create(const char *roname) */ memset(&nulls, 0, sizeof(nulls)); - values[Anum_pg_replication_origin_roident - 1] = ObjectIdGetDatum(roident); - values[Anum_pg_replication_origin_roname - 1] = roname_d; + HeapTupleSetValue(pg_replication_origin, roident, ObjectIdGetDatum(roident), values); + HeapTupleSetValue(pg_replication_origin, roname, roname_d, values); tuple = heap_form_tuple(RelationGetDescr(rel), values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); CommandCounterIncrement(); break; } diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c index dcc6124cc73..6ca50840e47 100644 --- a/src/backend/replication/logical/tablesync.c +++ b/src/backend/replication/logical/tablesync.c @@ -1651,9 +1651,9 @@ UpdateTwoPhaseState(Oid suboid, char new_state) { Relation rel; HeapTuple tup; - bool nulls[Natts_pg_subscription]; - bool replaces[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; + Datum values[Natts_pg_subscription] = {0}; + bool nulls[Natts_pg_subscription] = {false}; + Bitmapset *updated = NULL; Assert(new_state == LOGICALREP_TWOPHASE_STATE_DISABLED || new_state == LOGICALREP_TWOPHASE_STATE_PENDING || @@ -1666,19 +1666,13 @@ UpdateTwoPhaseState(Oid suboid, char new_state) "cache lookup failed for subscription oid %u", suboid); - /* Form a new tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - /* And update/set two_phase state */ - values[Anum_pg_subscription_subtwophasestate - 1] = CharGetDatum(new_state); - replaces[Anum_pg_subscription_subtwophasestate - 1] = true; + HeapTupleUpdateValue(pg_subscription, subtwophasestate, CharGetDatum(new_state), values, nulls, updated); - tup = heap_modify_tuple(tup, RelationGetDescr(rel), - values, nulls, replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); - heap_freetuple(tup); table_close(rel, RowExclusiveLock); + bms_free(updated); + heap_freetuple(tup); } diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index 93970c6af29..8551609c977 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -6121,21 +6121,12 @@ clear_subscription_skip_lsn(XLogRecPtr finish_lsn) */ if (subform->subskiplsn == myskiplsn) { - bool nulls[Natts_pg_subscription]; - bool replaces[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; - - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); + Bitmapset *updated = NULL; /* reset subskiplsn */ - values[Anum_pg_subscription_subskiplsn - 1] = LSNGetDatum(InvalidXLogRecPtr); - replaces[Anum_pg_subscription_subskiplsn - 1] = true; - - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleUpdateField(pg_subscription, subskiplsn, LSNGetDatum(InvalidXLogRecPtr), subform, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + bms_free(updated); if (myskiplsn != finish_lsn) ereport(WARNING, diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index a96fbdc1ddd..92f82081d25 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -59,8 +59,8 @@ InsertRule(const char *rulname, { char *evqual = nodeToString(event_qual); char *actiontree = nodeToString((Node *) action); - Datum values[Natts_pg_rewrite]; - bool nulls[Natts_pg_rewrite] = {0}; + Datum values[Natts_pg_rewrite] = {0}; + bool nulls[Natts_pg_rewrite] = {false}; NameData rname; Relation pg_rewrite_desc; HeapTuple tup, @@ -69,18 +69,19 @@ InsertRule(const char *rulname, ObjectAddress myself, referenced; bool is_update = false; + Bitmapset *updated = NULL; /* * Set up *nulls and *values arrays */ namestrcpy(&rname, rulname); - values[Anum_pg_rewrite_rulename - 1] = NameGetDatum(&rname); - values[Anum_pg_rewrite_ev_class - 1] = ObjectIdGetDatum(eventrel_oid); - values[Anum_pg_rewrite_ev_type - 1] = CharGetDatum(evtype + '0'); - values[Anum_pg_rewrite_ev_enabled - 1] = CharGetDatum(RULE_FIRES_ON_ORIGIN); - values[Anum_pg_rewrite_is_instead - 1] = BoolGetDatum(evinstead); - values[Anum_pg_rewrite_ev_qual - 1] = CStringGetTextDatum(evqual); - values[Anum_pg_rewrite_ev_action - 1] = CStringGetTextDatum(actiontree); + HeapTupleUpdateValue(pg_rewrite, rulename, NameGetDatum(&rname), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_class, ObjectIdGetDatum(eventrel_oid), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_type, CharGetDatum(evtype + '0'), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_enabled, CharGetDatum(RULE_FIRES_ON_ORIGIN), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, is_instead, BoolGetDatum(evinstead), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_qual, CStringGetTextDatum(evqual), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_action, CStringGetTextDatum(actiontree), values, nulls, updated); /* * Ready to store new pg_rewrite tuple @@ -96,8 +97,6 @@ InsertRule(const char *rulname, if (HeapTupleIsValid(oldtup)) { - bool replaces[Natts_pg_rewrite] = {0}; - if (!replace) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), @@ -107,16 +106,14 @@ InsertRule(const char *rulname, /* * When replacing, we don't need to replace every attribute */ - replaces[Anum_pg_rewrite_ev_type - 1] = true; - replaces[Anum_pg_rewrite_is_instead - 1] = true; - replaces[Anum_pg_rewrite_ev_qual - 1] = true; - replaces[Anum_pg_rewrite_ev_action - 1] = true; - - tup = heap_modify_tuple(oldtup, RelationGetDescr(pg_rewrite_desc), - values, nulls, replaces); - - CatalogTupleUpdate(pg_rewrite_desc, &tup->t_self, tup); - + HeapTupleUpdateValue(pg_rewrite, ev_type, CharGetDatum(evtype + '0'), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, is_instead, BoolGetDatum(evinstead), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_qual, CStringGetTextDatum(evqual), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_action, CStringGetTextDatum(actiontree), values, nulls, updated); + + tup = heap_update_tuple(oldtup, RelationGetDescr(pg_rewrite_desc), + values, nulls, updated); + CatalogTupleUpdate(pg_rewrite_desc, &tup->t_self, tup, updated, NULL); ReleaseSysCache(oldtup); rewriteObjectId = ((Form_pg_rewrite) GETSTRUCT(tup))->oid; @@ -127,14 +124,12 @@ InsertRule(const char *rulname, rewriteObjectId = GetNewOidWithIndex(pg_rewrite_desc, RewriteOidIndexId, Anum_pg_rewrite_oid); - values[Anum_pg_rewrite_oid - 1] = ObjectIdGetDatum(rewriteObjectId); - + HeapTupleUpdateValue(pg_rewrite, oid, ObjectIdGetDatum(rewriteObjectId), values, nulls, updated); tup = heap_form_tuple(pg_rewrite_desc->rd_att, values, nulls); - - CatalogTupleInsert(pg_rewrite_desc, tup); + CatalogTupleInsert(pg_rewrite_desc, tup, NULL); } - + bms_free(updated); heap_freetuple(tup); /* If replacing, get rid of old dependencies and make new ones */ @@ -727,8 +722,11 @@ EnableDisableRule(Relation rel, const char *rulename, */ if (ruleform->ev_enabled != fires_when) { - ruleform->ev_enabled = fires_when; - CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup); + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_rewrite, ev_enabled, fires_when, ruleform, updated); + CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup, updated, NULL); + bms_free(updated); changed = true; } @@ -799,6 +797,7 @@ RenameRewriteRule(RangeVar *relation, const char *oldName, Form_pg_rewrite ruleform; Oid ruleOid; ObjectAddress address; + Bitmapset *updated = NULL; /* * Look up name, check permissions, and acquire lock (which we will NOT @@ -845,8 +844,8 @@ RenameRewriteRule(RangeVar *relation, const char *oldName, /* OK, do the update */ namestrcpy(&(ruleform->rulename), newName); - - CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup); + CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RewriteRelationId, ruleOid, 0); diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c index e401c195949..4d82c0c8e16 100644 --- a/src/backend/rewrite/rewriteSupport.c +++ b/src/backend/rewrite/rewriteSupport.c @@ -18,6 +18,7 @@ #include "access/table.h" #include "catalog/indexing.h" #include "catalog/pg_class.h" +#include "nodes/bitmapset.h" #include "catalog/pg_rewrite.h" #include "rewrite/rewriteSupport.h" #include "utils/inval.h" @@ -68,9 +69,12 @@ SetRelationRuleStatus(Oid relationId, bool relHasRules) if (classForm->relhasrules != relHasRules) { /* Do the update */ + Bitmapset *updated = NULL; + classForm->relhasrules = relHasRules; + updated = bms_add_member(updated, Anum_pg_class_relhasrules - FirstLowInvalidHeapAttributeNumber); - CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple); + CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple, updated, NULL); } else { diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index 3c3d2d315c6..7a6e6a2787b 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -762,20 +762,14 @@ statext_store(Oid statOid, bool inh, { Relation pg_stextdata; HeapTuple stup; - Datum values[Natts_pg_statistic_ext_data]; - bool nulls[Natts_pg_statistic_ext_data]; + Datum values[Natts_pg_statistic_ext_data] = {0}; + bool nulls[Natts_pg_statistic_ext_data] = {false}; pg_stextdata = table_open(StatisticExtDataRelationId, RowExclusiveLock); - memset(nulls, true, sizeof(nulls)); - memset(values, 0, sizeof(values)); - /* basic info */ - values[Anum_pg_statistic_ext_data_stxoid - 1] = ObjectIdGetDatum(statOid); - nulls[Anum_pg_statistic_ext_data_stxoid - 1] = false; - - values[Anum_pg_statistic_ext_data_stxdinherit - 1] = BoolGetDatum(inh); - nulls[Anum_pg_statistic_ext_data_stxdinherit - 1] = false; + HeapTupleSetValue(pg_statistic_ext_data, stxoid, ObjectIdGetDatum(statOid), values); + HeapTupleSetValue(pg_statistic_ext_data, stxdinherit, BoolGetDatum(inh), values); /* * Construct a new pg_statistic_ext_data tuple, replacing the calculated @@ -785,29 +779,42 @@ statext_store(Oid statOid, bool inh, { bytea *data = statext_ndistinct_serialize(ndistinct); - nulls[Anum_pg_statistic_ext_data_stxdndistinct - 1] = (data == NULL); - values[Anum_pg_statistic_ext_data_stxdndistinct - 1] = PointerGetDatum(data); + if (data == NULL) + HeapTupleSetValueNull(pg_statistic_ext_data, stxdndistinct, values, nulls); + else + HeapTupleSetValue(pg_statistic_ext_data, stxdndistinct, PointerGetDatum(data), values); } + else + HeapTupleSetValueNull(pg_statistic_ext_data, stxdndistinct, values, nulls); if (dependencies != NULL) { bytea *data = statext_dependencies_serialize(dependencies); - nulls[Anum_pg_statistic_ext_data_stxddependencies - 1] = (data == NULL); - values[Anum_pg_statistic_ext_data_stxddependencies - 1] = PointerGetDatum(data); + if (data == NULL) + HeapTupleSetValueNull(pg_statistic_ext_data, stxddependencies, values, nulls); + else + HeapTupleSetValue(pg_statistic_ext_data, stxddependencies, PointerGetDatum(data), values); } + else + HeapTupleSetValueNull(pg_statistic_ext_data, stxddependencies, values, nulls); + if (mcv != NULL) { bytea *data = statext_mcv_serialize(mcv, stats); - nulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = (data == NULL); - values[Anum_pg_statistic_ext_data_stxdmcv - 1] = PointerGetDatum(data); + if (data == NULL) + HeapTupleSetValueNull(pg_statistic_ext_data, stxdmcv, values, nulls); + else + HeapTupleSetValue(pg_statistic_ext_data, stxdmcv, PointerGetDatum(data), values); } + else + HeapTupleSetValueNull(pg_statistic_ext_data, stxdmcv, values, nulls); + if (exprs != (Datum) 0) - { - nulls[Anum_pg_statistic_ext_data_stxdexpr - 1] = false; - values[Anum_pg_statistic_ext_data_stxdexpr - 1] = exprs; - } + HeapTupleSetValue(pg_statistic_ext_data, stxdexpr, exprs, values); + else + HeapTupleSetValueNull(pg_statistic_ext_data, stxdexpr, values, nulls); /* * Delete the old tuple if it exists, and insert a new one. It's easier @@ -817,7 +824,7 @@ statext_store(Oid statOid, bool inh, /* form and insert a new tuple */ stup = heap_form_tuple(RelationGetDescr(pg_stextdata), values, nulls); - CatalogTupleInsert(pg_stextdata, stup); + CatalogTupleInsert(pg_stextdata, stup, NULL); heap_freetuple(stup); @@ -2293,8 +2300,8 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs) k; VacAttrStats *stats = exprdata[exprno].vacattrstat; - Datum values[Natts_pg_statistic]; - bool nulls[Natts_pg_statistic]; + Datum values[Natts_pg_statistic] = {0}; + bool nulls[Natts_pg_statistic] = {false}; HeapTuple stup; if (!stats->stats_valid) @@ -2315,12 +2322,12 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs) nulls[i] = false; } - values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(InvalidAttrNumber); - values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(false); - values[Anum_pg_statistic_stanullfrac - 1] = Float4GetDatum(stats->stanullfrac); - values[Anum_pg_statistic_stawidth - 1] = Int32GetDatum(stats->stawidth); - values[Anum_pg_statistic_stadistinct - 1] = Float4GetDatum(stats->stadistinct); + HeapTupleSetValue(pg_statistic, starelid, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_statistic, staattnum, Int16GetDatum(InvalidAttrNumber), values); + HeapTupleSetValue(pg_statistic, stainherit, BoolGetDatum(false), values); + HeapTupleSetValue(pg_statistic, stanullfrac, Float4GetDatum(stats->stanullfrac), values); + HeapTupleSetValue(pg_statistic, stawidth, Int32GetDatum(stats->stawidth), values); + HeapTupleSetValue(pg_statistic, stadistinct, Float4GetDatum(stats->stadistinct), values); i = Anum_pg_statistic_stakind1 - 1; for (k = 0; k < STATISTIC_NUM_SLOTS; k++) { diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c index 174da7d93a5..790391b573d 100644 --- a/src/backend/statistics/relation_stats.c +++ b/src/backend/statistics/relation_stats.c @@ -18,6 +18,7 @@ #include "postgres.h" #include "access/heapam.h" +#include "access/htup.h" #include "catalog/indexing.h" #include "catalog/namespace.h" #include "nodes/makefuncs.h" @@ -79,10 +80,9 @@ relation_statistics_update(FunctionCallInfo fcinfo) bool update_relallfrozen = false; HeapTuple ctup; Form_pg_class pgcform; - int replaces[4] = {0}; - Datum values[4] = {0}; - bool nulls[4] = {0}; - int nreplaces = 0; + Datum values[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; + Bitmapset *updated = NULL; Oid locked_table = InvalidOid; stats_check_required_arg(fcinfo, relarginfo, RELSCHEMA_ARG); @@ -146,42 +146,26 @@ relation_statistics_update(FunctionCallInfo fcinfo) pgcform = (Form_pg_class) GETSTRUCT(ctup); if (update_relpages && relpages != pgcform->relpages) - { - replaces[nreplaces] = Anum_pg_class_relpages; - values[nreplaces] = UInt32GetDatum(relpages); - nreplaces++; - } + HeapTupleUpdateValue(pg_class, relpages, UInt32GetDatum(relpages), values, nulls, updated); if (update_reltuples && reltuples != pgcform->reltuples) - { - replaces[nreplaces] = Anum_pg_class_reltuples; - values[nreplaces] = Float4GetDatum(reltuples); - nreplaces++; - } + HeapTupleUpdateValue(pg_class, reltuples, Float4GetDatum(reltuples), values, nulls, updated); if (update_relallvisible && relallvisible != pgcform->relallvisible) - { - replaces[nreplaces] = Anum_pg_class_relallvisible; - values[nreplaces] = UInt32GetDatum(relallvisible); - nreplaces++; - } + HeapTupleUpdateValue(pg_class, relallvisible, UInt32GetDatum(relallvisible), values, nulls, updated); if (update_relallfrozen && relallfrozen != pgcform->relallfrozen) - { - replaces[nreplaces] = Anum_pg_class_relallfrozen; - values[nreplaces] = UInt32GetDatum(relallfrozen); - nreplaces++; - } + HeapTupleUpdateValue(pg_class, relallfrozen, UInt32GetDatum(relallfrozen), values, nulls, updated); - if (nreplaces > 0) + if (!bms_is_empty(updated)) { TupleDesc tupdesc = RelationGetDescr(crel); HeapTuple newtup; - newtup = heap_modify_tuple_by_cols(ctup, tupdesc, nreplaces, - replaces, values, nulls); - CatalogTupleUpdate(crel, &newtup->t_self, newtup); + newtup = heap_update_tuple(ctup, tupdesc, values, nulls, updated); + CatalogTupleUpdate(crel, &newtup->t_self, newtup, updated, NULL); heap_freetuple(newtup); + bms_free(updated); } ReleaseSysCache(ctup); diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index f6d2f9dba13..163c77e4927 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -564,9 +564,8 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) } workbuf = {0}; char *workb = VARDATA(&workbuf.hdr); HeapTuple newtup; - Datum values[Natts_pg_largeobject]; - bool nulls[Natts_pg_largeobject]; - bool replace[Natts_pg_largeobject]; + Datum values[Natts_pg_largeobject] = {0}; + bool nulls[Natts_pg_largeobject] = {false}; CatalogIndexState indstate; Assert(obj_desc); @@ -612,6 +611,8 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) while (nwritten < nbytes) { + Bitmapset *updated = NULL; + /* * If possible, get next pre-existing page of the LO. We expect the * indexscan will deliver these in order --- but there may be holes. @@ -667,16 +668,11 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) /* * Form and insert updated tuple */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replace, false, sizeof(replace)); - values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf); - replace[Anum_pg_largeobject_data - 1] = true; - newtup = heap_modify_tuple(oldtuple, RelationGetDescr(lo_heap_r), - values, nulls, replace); - CatalogTupleUpdateWithInfo(lo_heap_r, &newtup->t_self, newtup, - indstate); + HeapTupleUpdateValue(pg_largeobject, data, PointerGetDatum(&workbuf), values, nulls, updated); + newtup = heap_update_tuple(oldtuple, RelationGetDescr(lo_heap_r), values, nulls, updated); + CatalogTupleUpdate(lo_heap_r, &newtup->t_self, newtup, updated, indstate); heap_freetuple(newtup); + bms_free(updated); /* * We're done with this old page. @@ -713,11 +709,11 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) */ memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id); - values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno); - values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf); + HeapTupleSetValue(pg_largeobject, loid, ObjectIdGetDatum(obj_desc->id), values); + HeapTupleSetValue(pg_largeobject, pageno, Int32GetDatum(pageno), values); + HeapTupleSetValue(pg_largeobject, data, PointerGetDatum(&workbuf), values); newtup = heap_form_tuple(lo_heap_r->rd_att, values, nulls); - CatalogTupleInsertWithInfo(lo_heap_r, newtup, indstate); + CatalogTupleInsert(lo_heap_r, newtup, indstate); heap_freetuple(newtup); } pageno++; @@ -755,9 +751,9 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len) } workbuf = {0}; char *workb = VARDATA(&workbuf.hdr); HeapTuple newtup; - Datum values[Natts_pg_largeobject]; - bool nulls[Natts_pg_largeobject]; - bool replace[Natts_pg_largeobject]; + Datum values[Natts_pg_largeobject] = {0}; + bool nulls[Natts_pg_largeobject] = {false}; + Bitmapset *updated = NULL; CatalogIndexState indstate; Assert(obj_desc); @@ -844,14 +840,11 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len) */ memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - memset(replace, false, sizeof(replace)); - values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf); - replace[Anum_pg_largeobject_data - 1] = true; - newtup = heap_modify_tuple(oldtuple, RelationGetDescr(lo_heap_r), - values, nulls, replace); - CatalogTupleUpdateWithInfo(lo_heap_r, &newtup->t_self, newtup, - indstate); + HeapTupleUpdateValue(pg_largeobject, data, PointerGetDatum(&workbuf), values, nulls, updated); + newtup = heap_update_tuple(oldtuple, RelationGetDescr(lo_heap_r), values, nulls, updated); + CatalogTupleUpdate(lo_heap_r, &newtup->t_self, newtup, updated, indstate); heap_freetuple(newtup); + bms_free(updated); } else { @@ -883,11 +876,11 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len) */ memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id); - values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno); - values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf); + HeapTupleSetValue(pg_largeobject, loid, ObjectIdGetDatum(obj_desc->id), values); + HeapTupleSetValue(pg_largeobject, pageno, Int32GetDatum(pageno), values); + HeapTupleSetValue(pg_largeobject, data, PointerGetDatum(&workbuf), values); newtup = heap_form_tuple(lo_heap_r->rd_att, values, nulls); - CatalogTupleInsertWithInfo(lo_heap_r, newtup, indstate); + CatalogTupleInsert(lo_heap_r, newtup, indstate); heap_freetuple(newtup); } diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 915d0bc9084..61d3b760e15 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -3780,6 +3780,7 @@ RelationSetNewRelfilenumber(Relation relation, char persistence) MultiXactId minmulti = InvalidMultiXactId; TransactionId freezeXid = InvalidTransactionId; RelFileLocator newrlocator; + Bitmapset *updated = NULL; if (!IsBinaryUpgrade) { @@ -3929,21 +3930,21 @@ RelationSetNewRelfilenumber(Relation relation, char persistence) else { /* Normal case, update the pg_class entry */ - classform->relfilenode = newrelfilenumber; + HeapTupleUpdateField(pg_class, relfilenode, newrelfilenumber, classform, updated); /* relpages etc. never change for sequences */ if (relation->rd_rel->relkind != RELKIND_SEQUENCE) { - classform->relpages = 0; /* it's empty until further notice */ - classform->reltuples = -1; - classform->relallvisible = 0; - classform->relallfrozen = 0; + HeapTupleUpdateField(pg_class, relpages, 0, classform, updated); + HeapTupleUpdateField(pg_class, reltuples, -1, classform, updated); + HeapTupleUpdateField(pg_class, relallvisible, 0, classform, updated); + HeapTupleUpdateField(pg_class, relallfrozen, 0, classform, updated); } - classform->relfrozenxid = freezeXid; - classform->relminmxid = minmulti; - classform->relpersistence = persistence; + HeapTupleUpdateField(pg_class, relfrozenxid, freezeXid, classform, updated); + HeapTupleUpdateField(pg_class, relminmxid, minmulti, classform, updated); + HeapTupleUpdateField(pg_class, relpersistence, persistence, classform, updated); - CatalogTupleUpdate(pg_class, &otid, tuple); + CatalogTupleUpdate(pg_class, &otid, tuple, updated, NULL); } UnlockTuple(pg_class, &otid, InplaceUpdateTupleLock); @@ -3958,6 +3959,7 @@ RelationSetNewRelfilenumber(Relation relation, char persistence) CommandCounterIncrement(); RelationAssumeNewRelfilelocator(relation); + bms_free(updated); } /* -- 2.49.0