Refactor how we form HeapTuples for CatalogTuple(Insert|Update)
Hello,
I've been working on expanding HOT updates [1]/messages/by-id/78574B24-BE0A-42C5-8075-3FA9FA63B8FC@amazon.com and have recently had
some success (will be posted soon to the thread) moving the work done
within HeapDetermineColumnsInfo() into the executor. I found that
heap_update() is used in two paths: heap_tuple_update() and
simple_tuple_update(), both call into heap_update() which then uses
HeapDetermineColumnsInfo() to find the set of indexed attributes that
have been modified during the update. This makes sense on the normal
path from the executor, but the simple_tuple_update() path is only
called from CatalogTupleUpdate() and when I looked at how catalog tuples
were formed/mutated on that path I discovered something that I had to fix.
Catalog tuples have knowledge of what attributes are mutated implicitly,
but they don't preserve that information and so
HeapDetermineColumnsInfo() has to re-discover that later on (while the
page is locked). While on the surface this isn't such a big deal, it's
been that way and worked well for years I have other motivations (see
[1]: /messages/by-id/78574B24-BE0A-42C5-8075-3FA9FA63B8FC@amazon.com
So, I set about to create a way to retain the knowledge of what was
modified while mutating catalog tuples and pass that information on to
CatalogTupleUpdate() as a Bitmapset. That is the underlying goal of
this patch set. To make no behavioral changes, only syntactic ones, and
end up with something better overall.
That turned out to be a bit of a challenge as we have a lot of places
where catalog information is updated. We also have two different
methods for updating said information. And we intermix them. At times
we hack our way to a solution and ignore convention. I went down the
rabbit hole on this one, but I'm back up for a cup of tea because what
I've done seems materially better to me and I've accomplished the goal
(and can eventually make use of the result in [1]/messages/by-id/78574B24-BE0A-42C5-8075-3FA9FA63B8FC@amazon.com). Is this patch
useful even without that other work? I think so, just on the basis of
cleanup. Let me explain.
Historically there have been two methods for modifying heap tuples
destined for the catalog; Form/GETSTRUCT, and values/nulls/replaces.
This new method provides a more intuitive and less error-prone approach
without changing the fundamentals of the process. In addition, it is
now possible to retain knowledge of the set of mutated attributes when
working with catalog tuples. This isn't used in practice (yet [1]/messages/by-id/78574B24-BE0A-42C5-8075-3FA9FA63B8FC@amazon.com), but
could be a way to avoid the overhead of HeapDetermineColumnsInfo() in
heap_update() where (while holding a lock) we re-discover that set by
comparing old/new HeapTuple datums when trying to find what indexed
attributes have new values and prevent HOT updates.
Method 1: Form/GETSTRUCT
The "Form/GETSTRUCT" model allows for direct access to the tuple data
that is then modified, copied, and then updated via CatalogTupleUpdate().
Old:
Form_pg_index relform = (Form_pg_index) GETSTRUCT(tuple);
relform->inisclustered = false;
CatalogTupleUpdate(pg_index, &tuple->t_self, tuple);
New:
Bitmapset *updated = NULL;
Form_pg_index relform = (Form_pg_index) GETSTRUCT(tuple);
HeapTupleUpdateField(pg_index, indisclustered, false, indexForm, updated);
CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL);
bms_free(updated);
Method 2: values/nulls/replaces
The "values/nulls/replaces" model collects the necessary information to
either update or create a heap tuple using heap_modify_tuple() or
heap_form_tuple() or sometimes heap_modify_tuple_by_cols(). While all
those functions remain unchanged now the prefered function for catalog
tuple modification is heap_update_tuple().
Old:
bool nulls[Natts_pg_type];
bool replaces[Natts_pg_type];
Datum values[Natts_pg_type];
values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType);
nulls[Anum_pg_type_typdefaultbin - 1] = true;
replaces[Anum_pg_type_oid - 1] = false;
tuple = heap_modify_tuple(tuple, desc, values, nulls, replaces);
CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
New:
Datum values[Natts_pg_type] = {0};
bool nulls[Natts_pg_type] = {false};
Bitmapset *updated = NULL;
HeapTupleUpdateValue(pg_type, typtype, CharGetDatum(typeType), values,
nulls, updated);
HeapTupleUpdateValueNull(pg_type, typdefaultbin, values, nulls, updated);
HeapTupleSetColumnNotUpdated(pg_type, oid, updated);
tuple = heap_update_tuple(tuple, desc, values, nulls, updated);
CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple, updated, NULL);
In addition CatalogTupleUpdate and CatalogTupleInsert now have an
optional argument for the CatalogIndexState, when not provided it is
created and then released for the caller. This eliminates the need for
their "WithInfo" companion functions.
heap_update_tuple() is functionally equivalent to heap_modify_tuple(),
but takes a Bitmapset called "updated" rather than an array of bool
(generally) called "replaces" as a method for indicating what was
modified. Additionally, this new function tries to balance the
trade-offs of calling heap_getattr() versus heap_deform_tuple() based on
the ratio of attributes updated and their known runtime complexities.
Both paths are functionally equivalent.
The changes also include initialization of the values/nulls arrays
rather than loops or memset(). Some effort was also given to unify
naming of these variables and their order so as to lower cognitive
overhead.
So, let me dive into the attached patches. On advice from my mentor
Noah Misch I've divided the changes in two. The first patch contains
all the infrastructure and the set of files where applying the changes
got "interesting" and should be highlighted. The second is the
mechanical changes to the remaining files, and it's HUGE, apologies for
the blast radius here but it couldn't be helped.
0001 - Refactor how we form HeapTuples for CatalogTuple(Insert|Update)
htup.h: is where you'll find the new macros. There is a "getter" called
HeapTupleValue() to find the field in the values array and not worry
about "-1". After that, they break down into a two cases, insert and
update, with forms addressing method 1 (Form/GETSTRUCT) and method 2 (values/nulls/updated).
Insert macros take the form "HeapTupleSet...()" as in
"HeapTupleSetField(...)" or "HeapTupleSetValue(...)". There is the
assignment to NULL which is "HeapTupleSetFieldNull(...)" and
"HeapTupleSetValueNull(...)" as well.
Arguments to these macros are:
table_name, field, value, (nulls), (form_ptr)
These macros simply translate back to the forms that we use now and in
some cases combine work or ensure correctness.
Update macros follow a similar pattern "HeapTupleUpdate...()" and then
have "HeapTupleUpdateField..." and "HeapTupleUpdateValue..." cases to
cover the two methods we use.
Arguments are again uniform:
table_name, field, value, values, nulls, updated
There are additional macros for a few update-related special cases as well:
* HeapTupleMarkColumnUpdated() - not something you'll normally use as
the update methods all capture this information already, but there are
occasions where this is useful.
* HeapTupleUpdateSetAllColumnsUpdated() - 99.9% of the time we have
historically started off with a "replaces" array where every value in
that array is "false", but there are a few places where we had occasion
to do the opposite, start with the assumption that all attributes were
modified. This covers that case setting all the bits in the "updated"
Bitmapset correctly.
heaptuple.c: you'll find here my new heap_update_tuple() function. This
one is interesting as it tries to balance out the cost of heap_getattr()
vs heap_deform_tuple(). Why did I bother? Read the comment on
heap_modify_tuple(), and I was there... so why not? You may disagree
with my approach, here's a portion of the comment that explains it:
* Performance strategy:
* - If updating many attributes (> 2*natts/3), use heap_getattr() to extract
* only the few non-updated attributes. This is O(k*n) where k is the number
* of non-updated attributes, which is small when updating many.
* - If updating few attributes (<= 2*natts/3), use heap_deform_tuple() to
* extract all attributes at once (O(n)), then replace the updated ones.
* This avoids the O(n^2) cost of many heap_getattr() calls.
*
* The threshold of 2*natts/3 balances the fixed O(n) cost of heap_deform_tuple
* against the variable O(k*n) cost of heap_getattr, where k = natts - num_updated.
indexing.c: has the change to CatalogTupleUpdate/Insert and removal of
their "WithInfo" companions. If that second part is controversial then
I don't mind reverting it, but IMO this is cleaner and might either
inspire more call sites to create and reuse CatalogIndexState or for
someone (me?) to address the comment that pre-dates my work:
* XXX: At some point we might cache the CatalogIndexState data
somewhere (perhaps
* in the relcache) so that callers needn't trouble over this.
The remaining files in this patch (we're still on 0001) are in the
category of *interesting* or non-obvious changes I ran into that were
"fun" to fix...
pg_aggregate.c: in AggregateCreate() we run into a "compromise" pattern
where the code code either update or insert. In such cases hackers
should use the macros for update, not insert, everywhere. This records
the additional information for the update path and doesn't burden the
insert path with much more than a Bitmapset to free.
This reminds me, there is also the case where a function is looping and
updating a number of catalog tuples. Care must be taken to scope the
Bitmapset and free it every iteration as in:
while( doing all the things )
{
Bitmapset updated = NULL;
... update a tuple
CatalogTupleUpdate();
bms_free(updated);
}
This also comes up when a function has multiple updates not in a loop.
Don't reuse the Bitmapset, just scope it. If you do reuse it then:
bms_free(updated);
updated = NULL;
and later... when you start using it again:
Assert(bms_is_empty(updated));
pg_constraint.c: brings us to namestrcpy(), take a look at
RenameConstraintById(). When you run into namestrcpy() you've likely
just done the mutation to the form directly but you'll want to mark that
field as updated, as in:
namestrcpy(&(con->conname), newname);
HeapTupleMarkColumnUpdated(pg_constraint, conname, updated);
This pattern is also needed after functions like pg_add_s32_overflow(),
just HeapTupleMarkColumnUpdated() and you're fine. I used the regex:
"namestrcpy|pg_.*_.*flow" to find these cases, YMMV.
alter.c: take a look at AlterObjectRename_internal() which uses
get_object_attnum_name() to get the AttrNumber that is to be altered.
This is fine, but it's not something we can just plug into a macro and
get the proper name expansion. So, we do it the manual way and add a comment:
/*
* NOTE: We can't use the HeapTupleMarkColumnUpdated() macro here because
* 'Anum_name' isn't a table/column name, it's a index for the relation
* passed into the function as an argument.
*/
namestrcpy(&nameattrdata, new_name);
values[Anum_name - 1] = NameGetDatum(&nameattrdata);
updated = bms_add_member(updated, Anum_name - FirstLowInvalidHeapAttributeNumber);
analyze.c: uses the HeapTupleSetAllColumnsUpdated() at the start of the
update_attstats() function to match the replaced code. Later there's
another interesting deviation from the normal pattern in that function
where we want to update the nth stakind/opt/coll this was frustrating at
first until I found that this worked:
HeapTupleSetValue(pg_statistic, stakind1 + k,
Int16GetDatum(stats->stakind[k]), values);
I'll be "cpp", here's what that turns into:
(values)[Anum_pg_statistic_stakind1 + k - 1] = (Int16GetDatum(stats->stakind[k]));
So, we're taking the attribute number adding "k" then subtracting 1, and
voila "Bob's your uncle." While a bit unconventional, I think the
resulting form is understandable, much more than before which was:
i = Anum_pg_statistic_stakind1 - 1;
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
values[i++] = Int16GetDatum(stats->stakind[k]); /* stakindN */
attribute_stats.c: take a look at set_stats_slot() where I have a
comment explaining this "field + n" method adding a "Don't Panic" might
help too. Here's that comment:
/*
* NOTE: This might seem odd, to be adding 'i' to the name of the field on
* these macros, but that's what we need to do here to find the proper
* slot offset and record the proper value into the updated bitmap.
*
* Example: HeapTupleValue(pg_statistic, stakind1 + i, values);
*
* Becomes: values[Anum_pg_statistic_stakind1 + i - 1];
*
* The result is you're indexing the i'th value, exactly what we needed.
*/
The really amazing and valuable piece here is how that plays out in the following:
HeapTupleUpdateValue(pg_statistic, stakind1 + i, Int16GetDatum(stakind),
values, nulls, updated);
Playing the role of "cpp" again we get:
do { \
(values)[Anum_statistic_stakind1 + i - 1] = (Datum)
(Int16GetDatum(stakind)); \
(nulls)[Anum_statistic_stakind1 + i - 1] = false; \
Anum_statistic_stakind1 - (-7))
} while(0);
The result is that we've set the value/isnull at the correct position in
both the values and nulls arrays and then added the correct attribute
number into the Bitmapset (drops the mic).
Okay, and that about does it for "0001" with the foundation and then the
odd cases.
0002 - Update the remainder of catalog updates using the new APIs
This is a lot of applying the pattern over and over until it all works.
That's it. Nothing much more interesting here.
This is a lot of change, I get that, I think there's value in change
when the result is cleaner and more maintainable. The one place I'll
agree up front where this might case problems is back-patching fixes.
That'll have to have the new approach in some branches and the old
approach in others. It's a 5-year commitment, I don't take that lightly.
If you made it this far, I owe you a beer/coffee/token-of-appreciation.
Without this patch my [1]/messages/by-id/78574B24-BE0A-42C5-8075-3FA9FA63B8FC@amazon.com will have an ugly wart
(HeapDetermineColumnsInfo()) for the CatalogTupleUpdate path only. I
can live with that, I'd rather not.
best,
-greg
[1]: /messages/by-id/78574B24-BE0A-42C5-8075-3FA9FA63B8FC@amazon.com
Attachments:
v1-0001-Refactor-how-we-form-HeapTuples-for-CatalogTuple-.patchapplication/octet-streamDownload
From aecb434bf9bc0ce1f4871122d5ab55d3db0957f5 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
Date: Fri, 14 Nov 2025 08:02:31 -0500
Subject: [PATCH v1 1/2] Refactor how we form HeapTuples for
CatalogTuple(Insert|Update)
This commit provides a set of macros that should be used when inserting
or updating tuples before calling CatalogTupleUpdate() or
CatalogTupleInsert(). Historically there have been two methods for
accomplishing this task; Form/GETSTRUCT, and values/nulls/replaces.
This new method provides a more intuitive and less error-prone approach
without changing the fundamentals of the process. In addition, it is
now possible to retain knowledge of the set of mutated attributes when
working with catalog tuples. This isn't used in practice (yet), but
could be a way to avoid the overhead of HeapDetermineColumnsInfo() in
heap_update() where (while holding a lock) we re-discover that set by
comparing old/new HeapTuple datums when trying to find what indexed
attributes have new values and prevent HOT updates.
The "Form/GETSTRUCT" model allows for direct access to the tuple data
that is then modified, copied, and then updated via
CatalogTupleUpdate().
Old:
Form_pg_index relform = (Form_pg_index) GETSTRUCT(tuple);
relform->inisclustered = false;
CatalogTupleUpdate(pg_index, &tuple->t_self, tuple);
New:
Bitmapset *updated = NULL;
Form_pg_index relform = (Form_pg_index) GETSTRUCT(tuple);
HeapTupleUpdateField(pg_index, indisclustered, false, indexForm, updated);
CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL);
bms_free(updated);
The "values/nulls/replaces" model collects the necessary information to
either update or create a heap tuple using heap_modify_tuple() or
heap_form_tuple() or sometimes heap_modify_tuple_by_cols(). While all
those functions remain unchanged now the prefered function for catalog
tuple modification is heap_update_tuple().
Old:
bool nulls[Natts_pg_type];
bool replaces[Natts_pg_type];
Datum values[Natts_pg_type];
values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType);
nulls[Anum_pg_type_typdefaultbin - 1] = true;
replaces[Anum_pg_type_oid - 1] = false;
tup = heap_modify_tuple(tuple, desc, values, nulls, replaces);
CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
New:
Datum values[Natts_pg_type] = {0};
bool nulls[Natts_pg_type] = {false};
Bitmapset *updated = NULL;
HeapTupleUpdateValue(pg_type, typtype, CharGetDatum(typeType), values, nulls, updated);
HeapTupleUpdateValueNull(pg_type, typdefaultbin, values, nulls, updated);
HeapTupleSetColumnNotUpdated(pg_type, oid, updated);
tup = heap_update_tuple(tuple, desc, values, nulls, updated);
CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple, updated, NULL);
In addition CatalogTupleUpdate and CatalogTupleInsert now have an
optional argument for the CatalogIndexState, when not provided it is
created and then released for the caller.
The heap_update_tuple() function is functionally equivalent to
heap_modify_tuple(), but takes a Bitmapset called "updated" rather than
an array of bool generally called "replaces" as a method for indicating
what was modified. Additionally, this new function tries to balance the
tradeoffs of calling heap_getattr() versus heap_deform_tuple() based
on the ratio of attributes updated and their known runtime complexities.
Both paths are functionally equivalent.
The changes also include initialization of the values/nulls arrays
rather than loops or memset(). Some effort was also given to unify
naming of these variables and their order so as to lower cognitive
overhead.
There is no impact to non-catalog related paths.
---
src/backend/access/common/heaptuple.c | 119 +++++++++++
src/backend/catalog/indexing.c | 138 ++++++-------
src/backend/catalog/pg_aggregate.c | 74 +++----
src/backend/catalog/pg_constraint.c | 131 ++++++------
src/backend/commands/alter.c | 60 +++---
src/backend/commands/analyze.c | 74 +++----
src/backend/statistics/attribute_stats.c | 241 +++++++++++------------
src/include/access/htup.h | 61 ++++++
src/include/access/htup_details.h | 8 +
src/include/catalog/indexing.h | 17 +-
10 files changed, 550 insertions(+), 373 deletions(-)
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 74a52d87067..364f03b043e 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -1325,6 +1325,125 @@ heap_modify_tuple_by_cols(HeapTuple tuple,
return newTuple;
}
+/*
+ * heap_update_tuple
+ * Form a new tuple from an old tuple and a set of replacement values.
+ *
+ * Creates a new HeapTuple by selectively replacing attributes from the original
+ * tuple with new values. The 'updated' Bitmapset specifies which attributes
+ * (by attribute number, 1-based adjusted by FirstLowInvalidHeapAttributeNumber)
+ * should be replaced with corresponding entries from new_values and new_isnull
+ * arrays (0-based indices).
+ *
+ * Performance strategy:
+ * - If updating many attributes (> 2*natts/3), use heap_getattr() to extract
+ * only the few non-updated attributes. This is O(k*n) where k is the number
+ * of non-updated attributes, which is small when updating many.
+ * - If updating few attributes (<= 2*natts/3), use heap_deform_tuple() to
+ * extract all attributes at once (O(n)), then replace the updated ones.
+ * This avoids the O(n^2) cost of many heap_getattr() calls.
+ *
+ * The threshold of 2*natts/3 balances the fixed O(n) cost of heap_deform_tuple
+ * against the variable O(k*n) cost of heap_getattr, where k = natts - num_updated.
+ */
+HeapTuple
+heap_update_tuple(HeapTuple tuple,
+ TupleDesc desc,
+ const Datum *new_values,
+ const bool *new_nulls,
+ const Bitmapset *updated)
+{
+ int natts = desc->natts;
+ int num_updated;
+ Datum *values;
+ bool *nulls;
+ HeapTuple new_tuple;
+
+ Assert(!bms_is_empty(updated));
+
+ num_updated = bms_num_members(updated);
+ Assert(num_updated <= natts);
+
+ values = (Datum *) palloc0(natts * sizeof(Datum));
+ nulls = (bool *) palloc0(natts * sizeof(bool));
+
+ /*
+ * Choose strategy based on update density. When updating most attributes,
+ * it's cheaper to extract the few unchanged ones individually.
+ */
+ if (num_updated > (2 * natts) / 3)
+ {
+ /* Updating many: use heap_getattr for the few non-updated attributes */
+ for (int i = 0; i < natts; i++)
+ {
+ /*
+ * Convert array index to attribute number, then to bitmapset
+ * member. Array index i (0-based) -> attnum (1-based) -> bms
+ * member.
+ */
+ AttrNumber attnum = i + 1;
+ int member = attnum - FirstLowInvalidHeapAttributeNumber;
+
+ if (bms_is_member(member, updated))
+ {
+ /* Use replacement value */
+ if (unlikely(!new_values || !new_nulls))
+ values[i] = heap_getattr(tuple, attnum, desc, &nulls[i]);
+
+ if (likely(new_values))
+ values[i] = new_values[i];
+
+ if (likely(new_nulls))
+ nulls[i] = new_nulls[i];
+ }
+ else
+ {
+ /* Extract original value using heap_getattr (1-based) */
+ values[i] = heap_getattr(tuple, attnum, desc, &nulls[i]);
+ }
+ }
+ }
+ else
+ {
+ int member = -1;
+
+ /* Updating few: deform entire tuple, then replace updated attributes */
+ heap_deform_tuple(tuple, desc, values, nulls);
+
+ while ((member = bms_next_member(updated, member)) >= 0)
+ {
+ /*
+ * Convert bitmapset member to attribute number, then to array
+ * index. bms_member -> attnum (1-based) -> array index i
+ * (0-based).
+ */
+ AttrNumber attnum = member + FirstLowInvalidHeapAttributeNumber;
+ int i = attnum - 1;
+
+ Assert(i >= 0 && i < natts);
+
+ if (likely(new_values))
+ values[i] = new_values[i];
+
+ if (likely(new_nulls))
+ nulls[i] = new_nulls[i];
+ }
+ }
+
+ /* Create the new tuple */
+ new_tuple = heap_form_tuple(desc, values, nulls);
+
+ pfree(values);
+ pfree(nulls);
+
+ /* Preserve tuple identity and location information from the original */
+ new_tuple->t_data->t_ctid = tuple->t_data->t_ctid;
+ new_tuple->t_self = tuple->t_self;
+ new_tuple->t_tableOid = tuple->t_tableOid;
+
+ return new_tuple;
+}
+
/*
* heap_deform_tuple
* Given a tuple, extract data into values/isnull arrays; this is
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 004c5121000..f35c1b6cd88 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -225,58 +225,67 @@ CatalogTupleCheckConstraints(Relation heapRel, HeapTuple tup)
*
* This is a convenience routine for the common case of inserting a single
* tuple in a system catalog; it inserts a new heap tuple, keeping indexes
- * current. Avoid using it for multiple tuples, since opening the indexes
- * and building the index info structures is moderately expensive.
- * (Use CatalogTupleInsertWithInfo in such cases.)
+ * current.
+ *
+ * If 'indstate' is NULL, the function opens and closes the indexes internally.
+ * This is convenient for single-tuple updates but has overhead from opening the
+ * indexes and building index info structures.
+ *
+ * If 'indstate' is provided (non-NULL), it is used directly without opening or
+ * closing indexes. This allows callers to amortize index management costs across
+ * multiple tuple updates. Callers must use CatalogOpenIndexes() before the first
+ * update and CatalogCloseIndexes() after the last update.
+ *
+ * XXX: At some point we might cache the CatalogIndexState data somewhere (perhaps
+ * in the relcache) so that callers needn't trouble over this.
*/
void
-CatalogTupleInsert(Relation heapRel, HeapTuple tup)
+CatalogTupleInsert(Relation heapRel, HeapTuple tup,
+ CatalogIndexState indstate)
{
- CatalogIndexState indstate;
-
- CatalogTupleCheckConstraints(heapRel, tup);
-
- indstate = CatalogOpenIndexes(heapRel);
+ bool close_indexes = false;
- simple_heap_insert(heapRel, tup);
-
- CatalogIndexInsert(indstate, tup, TU_All);
- CatalogCloseIndexes(indstate);
-}
+ /* Open indexes if not provided by caller */
+ if (indstate == NULL)
+ {
+ indstate = CatalogOpenIndexes(heapRel);
+ close_indexes = true;
+ }
-/*
- * CatalogTupleInsertWithInfo - as above, but with caller-supplied index info
- *
- * This should be used when it's important to amortize CatalogOpenIndexes/
- * CatalogCloseIndexes work across multiple insertions. At some point we
- * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
- * so that callers needn't trouble over this ... but we don't do so today.
- */
-void
-CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
- CatalogIndexState indstate)
-{
CatalogTupleCheckConstraints(heapRel, tup);
simple_heap_insert(heapRel, tup);
CatalogIndexInsert(indstate, tup, TU_All);
+
+ /* Close indexes only if we opened them ourselves */
+ if (close_indexes)
+ CatalogCloseIndexes(indstate);
}
/*
- * CatalogTuplesMultiInsertWithInfo - as above, but for multiple tuples
+ * CatalogTuplesMultiInsert - as above, but for multiple tuples
*
* Insert multiple tuples into the given catalog relation at once, with an
* amortized cost of CatalogOpenIndexes.
*/
void
-CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot,
- int ntuples, CatalogIndexState indstate)
+CatalogTuplesMultiInsert(Relation heapRel, TupleTableSlot **slot,
+ int ntuples, CatalogIndexState indstate)
{
+ bool close_indexes = false;
+
/* Nothing to do */
if (ntuples <= 0)
return;
+ /* Open indexes if not provided by caller */
+ if (indstate == NULL)
+ {
+ indstate = CatalogOpenIndexes(heapRel);
+ close_indexes = true;
+ }
+
heap_multi_insert(heapRel, slot, ntuples,
GetCurrentCommandId(true), 0, NULL);
@@ -296,6 +305,10 @@ CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot,
if (should_free)
heap_freetuple(tuple);
}
+
+ /* Close indexes only if we opened them ourselves */
+ if (close_indexes)
+ CatalogCloseIndexes(indstate);
}
/*
@@ -303,47 +316,45 @@ CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot,
*
* Update the tuple identified by "otid", replacing it with the data in "tup".
*
- * This is a convenience routine for the common case of updating a single
- * tuple in a system catalog; it updates one heap tuple, keeping indexes
- * current. Avoid using it for multiple tuples, since opening the indexes
- * and building the index info structures is moderately expensive.
- * (Use CatalogTupleUpdateWithInfo in such cases.)
+ * This function updates a heap tuple in a system catalog and keeps its indexes
+ * current. The 'updated' bitmapset specifies which columns were modified, using
+ * the same encoding as HeapDetermineColumnsInfo().
+ *
+ * If 'indstate' is NULL, the function opens and closes the indexes internally.
+ * This is convenient for single-tuple updates but has overhead from opening the
+ * indexes and building index info structures.
+ *
+ * If 'indstate' is provided (non-NULL), it is used directly without opening or
+ * closing indexes. This allows callers to amortize index management costs across
+ * multiple tuple updates. Callers must use CatalogOpenIndexes() before the first
+ * update and CatalogCloseIndexes() after the last update.
+ *
+ * XXX: At some point we might cache the CatalogIndexState data somewhere (perhaps
+ * in the relcache) so that callers needn't trouble over this.
*/
void
-CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
+CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tuple,
+ const Bitmapset *updated, CatalogIndexState indstate)
{
- CatalogIndexState indstate;
TU_UpdateIndexes updateIndexes = TU_All;
+ bool close_indexes = false;
- CatalogTupleCheckConstraints(heapRel, tup);
-
- indstate = CatalogOpenIndexes(heapRel);
-
- simple_heap_update(heapRel, otid, tup, &updateIndexes);
-
- CatalogIndexInsert(indstate, tup, updateIndexes);
- CatalogCloseIndexes(indstate);
-}
+ CatalogTupleCheckConstraints(heapRel, tuple);
-/*
- * CatalogTupleUpdateWithInfo - as above, but with caller-supplied index info
- *
- * This should be used when it's important to amortize CatalogOpenIndexes/
- * CatalogCloseIndexes work across multiple updates. At some point we
- * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
- * so that callers needn't trouble over this ... but we don't do so today.
- */
-void
-CatalogTupleUpdateWithInfo(Relation heapRel, const ItemPointerData *otid, HeapTuple tup,
- CatalogIndexState indstate)
-{
- TU_UpdateIndexes updateIndexes = TU_All;
+ /* Open indexes if not provided by caller */
+ if (indstate == NULL)
+ {
+ indstate = CatalogOpenIndexes(heapRel);
+ close_indexes = true;
+ }
- CatalogTupleCheckConstraints(heapRel, tup);
+ simple_heap_update(heapRel, otid, tuple, &updateIndexes);
- simple_heap_update(heapRel, otid, tup, &updateIndexes);
+ CatalogIndexInsert(indstate, tuple, updateIndexes);
- CatalogIndexInsert(indstate, tup, updateIndexes);
+ /* Close indexes only if we opened them ourselves */
+ if (close_indexes)
+ CatalogCloseIndexes(indstate);
}
/*
@@ -355,11 +366,6 @@ CatalogTupleUpdateWithInfo(Relation heapRel, const ItemPointerData *otid, HeapTu
* cleanup will be done later by VACUUM. However, callers of this function
* shouldn't have to know that; we'd like a uniform abstraction for all
* catalog tuple changes. Hence, provide this currently-trivial wrapper.
- *
- * The abstraction is a bit leaky in that we don't provide an optimized
- * CatalogTupleDeleteWithInfo version, because there is currently nothing to
- * optimize. If we ever need that, rather than touching a lot of call sites,
- * it might be better to do something about caching CatalogIndexState.
*/
void
CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index a1cb5719a0c..ddfa94b3aba 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -79,9 +79,9 @@ AggregateCreate(const char *aggName,
Relation aggdesc;
HeapTuple tup;
HeapTuple oldtup;
- bool nulls[Natts_pg_aggregate];
- Datum values[Natts_pg_aggregate];
- bool replaces[Natts_pg_aggregate];
+ bool nulls[Natts_pg_aggregate] = {false};
+ Datum values[Natts_pg_aggregate] = {0};
+ Bitmapset *updated = NULL;
Form_pg_proc proc;
Oid transfn;
Oid finalfn = InvalidOid; /* can be omitted */
@@ -102,7 +102,6 @@ AggregateCreate(const char *aggName,
Oid procOid;
TupleDesc tupDesc;
char *detailmsg;
- int i;
ObjectAddress myself,
referenced;
ObjectAddresses *addrs;
@@ -584,7 +583,7 @@ AggregateCreate(const char *aggName,
/*
* permission checks on used types
*/
- for (i = 0; i < numArgs; i++)
+ for (int i = 0; i < numArgs; i++)
{
aclresult = object_aclcheck(TypeRelationId, aggArgTypes[i], GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK)
@@ -651,40 +650,34 @@ AggregateCreate(const char *aggName,
tupDesc = aggdesc->rd_att;
/* initialize nulls and values */
- for (i = 0; i < Natts_pg_aggregate; i++)
- {
- nulls[i] = false;
- values[i] = (Datum) 0;
- replaces[i] = true;
- }
- values[Anum_pg_aggregate_aggfnoid - 1] = ObjectIdGetDatum(procOid);
- values[Anum_pg_aggregate_aggkind - 1] = CharGetDatum(aggKind);
- values[Anum_pg_aggregate_aggnumdirectargs - 1] = Int16GetDatum(numDirectArgs);
- values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn);
- values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn);
- values[Anum_pg_aggregate_aggcombinefn - 1] = ObjectIdGetDatum(combinefn);
- values[Anum_pg_aggregate_aggserialfn - 1] = ObjectIdGetDatum(serialfn);
- values[Anum_pg_aggregate_aggdeserialfn - 1] = ObjectIdGetDatum(deserialfn);
- values[Anum_pg_aggregate_aggmtransfn - 1] = ObjectIdGetDatum(mtransfn);
- values[Anum_pg_aggregate_aggminvtransfn - 1] = ObjectIdGetDatum(minvtransfn);
- values[Anum_pg_aggregate_aggmfinalfn - 1] = ObjectIdGetDatum(mfinalfn);
- values[Anum_pg_aggregate_aggfinalextra - 1] = BoolGetDatum(finalfnExtraArgs);
- values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs);
- values[Anum_pg_aggregate_aggfinalmodify - 1] = CharGetDatum(finalfnModify);
- values[Anum_pg_aggregate_aggmfinalmodify - 1] = CharGetDatum(mfinalfnModify);
- values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
- values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
- values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace);
- values[Anum_pg_aggregate_aggmtranstype - 1] = ObjectIdGetDatum(aggmTransType);
- values[Anum_pg_aggregate_aggmtransspace - 1] = Int32GetDatum(aggmTransSpace);
+ HeapTupleUpdateValue(pg_aggregate, aggfnoid, ObjectIdGetDatum(procOid), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggkind, CharGetDatum(aggKind), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggnumdirectargs, Int16GetDatum(numDirectArgs), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggtransfn, ObjectIdGetDatum(transfn), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggfinalfn, ObjectIdGetDatum(finalfn), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggcombinefn, ObjectIdGetDatum(combinefn), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggserialfn, ObjectIdGetDatum(serialfn), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggdeserialfn, ObjectIdGetDatum(deserialfn), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggmtransfn, ObjectIdGetDatum(mtransfn), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggminvtransfn, ObjectIdGetDatum(minvtransfn), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggmfinalfn, ObjectIdGetDatum(mfinalfn), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggfinalextra, BoolGetDatum(finalfnExtraArgs), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggmfinalextra, BoolGetDatum(mfinalfnExtraArgs), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggfinalmodify, CharGetDatum(finalfnModify), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggmfinalmodify, CharGetDatum(mfinalfnModify), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggsortop, ObjectIdGetDatum(sortop), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggtranstype, ObjectIdGetDatum(aggTransType), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggtransspace, Int32GetDatum(aggTransSpace), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggmtranstype, ObjectIdGetDatum(aggmTransType), values, nulls, updated);
+ HeapTupleUpdateValue(pg_aggregate, aggmtransspace, Int32GetDatum(aggmTransSpace), values, nulls, updated);
if (agginitval)
- values[Anum_pg_aggregate_agginitval - 1] = CStringGetTextDatum(agginitval);
+ HeapTupleUpdateValue(pg_aggregate, agginitval, CStringGetTextDatum(agginitval), values, nulls, updated);
else
- nulls[Anum_pg_aggregate_agginitval - 1] = true;
+ HeapTupleUpdateValueNull(pg_aggregate, agginitval, values, nulls, updated);
if (aggminitval)
- values[Anum_pg_aggregate_aggminitval - 1] = CStringGetTextDatum(aggminitval);
+ HeapTupleUpdateValue(pg_aggregate, aggminitval, CStringGetTextDatum(aggminitval), values, nulls, updated);
else
- nulls[Anum_pg_aggregate_aggminitval - 1] = true;
+ HeapTupleUpdateValueNull(pg_aggregate, aggminitval, values, nulls, updated);
if (replace)
oldtup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(procOid));
@@ -717,20 +710,17 @@ AggregateCreate(const char *aggName,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot change number of direct arguments of an aggregate function")));
- replaces[Anum_pg_aggregate_aggfnoid - 1] = false;
- replaces[Anum_pg_aggregate_aggkind - 1] = false;
- replaces[Anum_pg_aggregate_aggnumdirectargs - 1] = false;
-
- tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
- CatalogTupleUpdate(aggdesc, &tup->t_self, tup);
+ tup = heap_update_tuple(oldtup, tupDesc, values, nulls, updated);
+ CatalogTupleUpdate(aggdesc, &tup->t_self, tup, updated, NULL);
ReleaseSysCache(oldtup);
}
else
{
tup = heap_form_tuple(tupDesc, values, nulls);
- CatalogTupleInsert(aggdesc, tup);
+ CatalogTupleInsert(aggdesc, tup, NULL);
}
+ bms_free(updated);
table_close(aggdesc, RowExclusiveLock);
/*
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 9944e4bd2d1..855bdf46015 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -85,8 +85,8 @@ CreateConstraintEntry(const char *constraintName,
Relation conDesc;
Oid conOid;
HeapTuple tup;
- bool nulls[Natts_pg_constraint];
- Datum values[Natts_pg_constraint];
+ Datum values[Natts_pg_constraint] = {0};
+ bool nulls[Natts_pg_constraint] = {false};
ArrayType *conkeyArray;
ArrayType *confkeyArray;
ArrayType *conpfeqopArray;
@@ -184,70 +184,70 @@ CreateConstraintEntry(const char *constraintName,
conOid = GetNewOidWithIndex(conDesc, ConstraintOidIndexId,
Anum_pg_constraint_oid);
- values[Anum_pg_constraint_oid - 1] = ObjectIdGetDatum(conOid);
- values[Anum_pg_constraint_conname - 1] = NameGetDatum(&cname);
- values[Anum_pg_constraint_connamespace - 1] = ObjectIdGetDatum(constraintNamespace);
- values[Anum_pg_constraint_contype - 1] = CharGetDatum(constraintType);
- values[Anum_pg_constraint_condeferrable - 1] = BoolGetDatum(isDeferrable);
- values[Anum_pg_constraint_condeferred - 1] = BoolGetDatum(isDeferred);
- values[Anum_pg_constraint_conenforced - 1] = BoolGetDatum(isEnforced);
- values[Anum_pg_constraint_convalidated - 1] = BoolGetDatum(isValidated);
- values[Anum_pg_constraint_conrelid - 1] = ObjectIdGetDatum(relId);
- values[Anum_pg_constraint_contypid - 1] = ObjectIdGetDatum(domainId);
- values[Anum_pg_constraint_conindid - 1] = ObjectIdGetDatum(indexRelId);
- values[Anum_pg_constraint_conparentid - 1] = ObjectIdGetDatum(parentConstrId);
- values[Anum_pg_constraint_confrelid - 1] = ObjectIdGetDatum(foreignRelId);
- values[Anum_pg_constraint_confupdtype - 1] = CharGetDatum(foreignUpdateType);
- values[Anum_pg_constraint_confdeltype - 1] = CharGetDatum(foreignDeleteType);
- values[Anum_pg_constraint_confmatchtype - 1] = CharGetDatum(foreignMatchType);
- values[Anum_pg_constraint_conislocal - 1] = BoolGetDatum(conIsLocal);
- values[Anum_pg_constraint_coninhcount - 1] = Int16GetDatum(conInhCount);
- values[Anum_pg_constraint_connoinherit - 1] = BoolGetDatum(conNoInherit);
- values[Anum_pg_constraint_conperiod - 1] = BoolGetDatum(conPeriod);
+ HeapTupleSetValue(pg_constraint, oid, ObjectIdGetDatum(conOid), values);
+ HeapTupleSetValue(pg_constraint, conname, NameGetDatum(&cname), values);
+ HeapTupleSetValue(pg_constraint, connamespace, ObjectIdGetDatum(constraintNamespace), values);
+ HeapTupleSetValue(pg_constraint, contype, CharGetDatum(constraintType), values);
+ HeapTupleSetValue(pg_constraint, condeferrable, BoolGetDatum(isDeferrable), values);
+ HeapTupleSetValue(pg_constraint, condeferred, BoolGetDatum(isDeferred), values);
+ HeapTupleSetValue(pg_constraint, conenforced, BoolGetDatum(isEnforced), values);
+ HeapTupleSetValue(pg_constraint, convalidated, BoolGetDatum(isValidated), values);
+ HeapTupleSetValue(pg_constraint, conrelid, ObjectIdGetDatum(relId), values);
+ HeapTupleSetValue(pg_constraint, contypid, ObjectIdGetDatum(domainId), values);
+ HeapTupleSetValue(pg_constraint, conindid, ObjectIdGetDatum(indexRelId), values);
+ HeapTupleSetValue(pg_constraint, conparentid, ObjectIdGetDatum(parentConstrId), values);
+ HeapTupleSetValue(pg_constraint, confrelid, ObjectIdGetDatum(foreignRelId), values);
+ HeapTupleSetValue(pg_constraint, confupdtype, CharGetDatum(foreignUpdateType), values);
+ HeapTupleSetValue(pg_constraint, confdeltype, CharGetDatum(foreignDeleteType), values);
+ HeapTupleSetValue(pg_constraint, confmatchtype, CharGetDatum(foreignMatchType), values);
+ HeapTupleSetValue(pg_constraint, conislocal, BoolGetDatum(conIsLocal), values);
+ HeapTupleSetValue(pg_constraint, coninhcount, Int16GetDatum(conInhCount), values);
+ HeapTupleSetValue(pg_constraint, connoinherit, BoolGetDatum(conNoInherit), values);
+ HeapTupleSetValue(pg_constraint, conperiod, BoolGetDatum(conPeriod), values);
if (conkeyArray)
- values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray);
+ HeapTupleSetValue(pg_constraint, conkey, PointerGetDatum(conkeyArray), values);
else
- nulls[Anum_pg_constraint_conkey - 1] = true;
+ HeapTupleSetValueNull(pg_constraint, conkey, values, nulls);
if (confkeyArray)
- values[Anum_pg_constraint_confkey - 1] = PointerGetDatum(confkeyArray);
+ HeapTupleSetValue(pg_constraint, confkey, PointerGetDatum(confkeyArray), values);
else
- nulls[Anum_pg_constraint_confkey - 1] = true;
+ HeapTupleSetValueNull(pg_constraint, confkey, values, nulls);
if (conpfeqopArray)
- values[Anum_pg_constraint_conpfeqop - 1] = PointerGetDatum(conpfeqopArray);
+ HeapTupleSetValue(pg_constraint, conpfeqop, PointerGetDatum(conpfeqopArray), values);
else
- nulls[Anum_pg_constraint_conpfeqop - 1] = true;
+ HeapTupleSetValueNull(pg_constraint, conpfeqop, values, nulls);
if (conppeqopArray)
- values[Anum_pg_constraint_conppeqop - 1] = PointerGetDatum(conppeqopArray);
+ HeapTupleSetValue(pg_constraint, conppeqop, PointerGetDatum(conppeqopArray), values);
else
- nulls[Anum_pg_constraint_conppeqop - 1] = true;
+ HeapTupleSetValueNull(pg_constraint, conppeqop, values, nulls);
if (conffeqopArray)
- values[Anum_pg_constraint_conffeqop - 1] = PointerGetDatum(conffeqopArray);
+ HeapTupleSetValue(pg_constraint, conffeqop, PointerGetDatum(conffeqopArray), values);
else
- nulls[Anum_pg_constraint_conffeqop - 1] = true;
+ HeapTupleSetValueNull(pg_constraint, conffeqop, values, nulls);
if (confdelsetcolsArray)
- values[Anum_pg_constraint_confdelsetcols - 1] = PointerGetDatum(confdelsetcolsArray);
+ HeapTupleSetValue(pg_constraint, confdelsetcols, PointerGetDatum(confdelsetcolsArray), values);
else
- nulls[Anum_pg_constraint_confdelsetcols - 1] = true;
+ HeapTupleSetValueNull(pg_constraint, confdelsetcols, values, nulls);
if (conexclopArray)
- values[Anum_pg_constraint_conexclop - 1] = PointerGetDatum(conexclopArray);
+ HeapTupleSetValue(pg_constraint, conexclop, PointerGetDatum(conexclopArray), values);
else
- nulls[Anum_pg_constraint_conexclop - 1] = true;
+ HeapTupleSetValueNull(pg_constraint, conexclop, values, nulls);
if (conBin)
- values[Anum_pg_constraint_conbin - 1] = CStringGetTextDatum(conBin);
+ HeapTupleSetValue(pg_constraint, conbin, CStringGetTextDatum(conBin), values);
else
- nulls[Anum_pg_constraint_conbin - 1] = true;
+ HeapTupleSetValueNull(pg_constraint, conbin, values, nulls);
tup = heap_form_tuple(RelationGetDescr(conDesc), values, nulls);
- CatalogTupleInsert(conDesc, tup);
+ CatalogTupleInsert(conDesc, tup, NULL);
ObjectAddressSet(conobject, ConstraintRelationId, conOid);
@@ -748,7 +748,7 @@ AdjustNotNullInheritance(Oid relid, AttrNumber attnum,
{
Relation pg_constraint;
Form_pg_constraint conform;
- bool changed = false;
+ Bitmapset *updated = NULL;
pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock);
conform = (Form_pg_constraint) GETSTRUCT(tup);
@@ -784,19 +784,21 @@ AdjustNotNullInheritance(Oid relid, AttrNumber attnum,
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
- changed = true;
+ HeapTupleMarkColumnUpdated(pg_constraint, coninhcount, updated);
}
else if (!conform->conislocal)
{
- conform->conislocal = true;
- changed = true;
+ HeapTupleUpdateField(pg_constraint, conislocal, true, conform, updated);
}
- if (changed)
- CatalogTupleUpdate(pg_constraint, &tup->t_self, tup);
+ if (!bms_is_empty(updated))
+ {
+ CatalogTupleUpdate(pg_constraint, &tup->t_self, tup, updated, NULL);
+ }
table_close(pg_constraint, RowExclusiveLock);
+ bms_free(updated);
return true;
}
@@ -928,6 +930,7 @@ RemoveConstraintById(Oid conId)
Relation pgrel;
HeapTuple relTup;
Form_pg_class classForm;
+ Bitmapset *updated = NULL;
pgrel = table_open(RelationRelationId, RowExclusiveLock);
relTup = SearchSysCacheCopy1(RELOID,
@@ -938,14 +941,14 @@ RemoveConstraintById(Oid conId)
classForm = (Form_pg_class) GETSTRUCT(relTup);
if (classForm->relchecks > 0)
- classForm->relchecks--;
+ HeapTupleUpdateField(pg_class, relchecks, classForm->relchecks - 1, classForm, updated);
else
/* should not happen */
elog(WARNING, "relation \"%s\" has relchecks = %d",
RelationGetRelationName(rel), classForm->relchecks);
- CatalogTupleUpdate(pgrel, &relTup->t_self, relTup);
-
+ CatalogTupleUpdate(pgrel, &relTup->t_self, relTup, updated, NULL);
+ bms_free(updated);
heap_freetuple(relTup);
table_close(pgrel, RowExclusiveLock);
@@ -990,6 +993,7 @@ RenameConstraintById(Oid conId, const char *newname)
Relation conDesc;
HeapTuple tuple;
Form_pg_constraint con;
+ Bitmapset *updated = NULL;
conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
@@ -1020,11 +1024,13 @@ RenameConstraintById(Oid conId, const char *newname)
/* OK, do the rename --- tuple is a copy, so OK to scribble on it */
namestrcpy(&(con->conname), newname);
+ HeapTupleMarkColumnUpdated(pg_constraint, conname, updated);
- CatalogTupleUpdate(conDesc, &tuple->t_self, tuple);
+ CatalogTupleUpdate(conDesc, &tuple->t_self, tuple, updated, NULL);
InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
+ bms_free(updated);
heap_freetuple(tuple);
table_close(conDesc, RowExclusiveLock);
}
@@ -1072,15 +1078,17 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
/* Don't update if the object is already part of the namespace */
if (conform->connamespace == oldNspId && oldNspId != newNspId)
{
+ Bitmapset *updated = NULL;
+
tup = heap_copytuple(tup);
conform = (Form_pg_constraint) GETSTRUCT(tup);
- conform->connamespace = newNspId;
-
- CatalogTupleUpdate(conRel, &tup->t_self, tup);
+ HeapTupleUpdateField(pg_constraint, connamespace, newNspId, conform, updated);
+ CatalogTupleUpdate(conRel, &tup->t_self, tup, updated, NULL);
+ bms_free(updated);
/*
- * Note: currently, the constraint will not have its own
+ * NOTE: currently, the constraint will not have its own
* dependency on the namespace, so we don't need to do
* changeDependencyFor().
*/
@@ -1116,6 +1124,7 @@ ConstraintSetParentConstraint(Oid childConstrId,
newtup;
ObjectAddress depender;
ObjectAddress referenced;
+ Bitmapset *updated = NULL;
constrRel = table_open(ConstraintRelationId, RowExclusiveLock);
tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(childConstrId));
@@ -1131,16 +1140,17 @@ ConstraintSetParentConstraint(Oid childConstrId,
elog(ERROR, "constraint %u already has a parent constraint",
childConstrId);
- constrForm->conislocal = false;
+ HeapTupleUpdateField(pg_constraint, conislocal, false, constrForm, updated);
if (pg_add_s16_overflow(constrForm->coninhcount, 1,
&constrForm->coninhcount))
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
- constrForm->conparentid = parentConstrId;
+ HeapTupleMarkColumnUpdated(pg_constraint, coninhcount, updated);
+ HeapTupleUpdateField(pg_constraint, conparentid, parentConstrId, constrForm, updated);
- CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
+ CatalogTupleUpdate(constrRel, &tuple->t_self, newtup, updated, NULL);
ObjectAddressSet(depender, ConstraintRelationId, childConstrId);
@@ -1152,14 +1162,14 @@ ConstraintSetParentConstraint(Oid childConstrId,
}
else
{
- constrForm->coninhcount--;
- constrForm->conislocal = true;
- constrForm->conparentid = InvalidOid;
+ HeapTupleUpdateField(pg_constraint, coninhcount, constrForm->coninhcount - 1, constrForm, updated);
+ HeapTupleUpdateField(pg_constraint, conislocal, true, constrForm, updated);
+ HeapTupleUpdateField(pg_constraint, conparentid, InvalidOid, constrForm, updated);
/* Make sure there's no further inheritance. */
Assert(constrForm->coninhcount == 0);
- CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
+ CatalogTupleUpdate(constrRel, &tuple->t_self, newtup, updated, NULL);
deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
ConstraintRelationId,
@@ -1169,6 +1179,7 @@ ConstraintSetParentConstraint(Oid childConstrId,
DEPENDENCY_PARTITION_SEC);
}
+ bms_free(updated);
ReleaseSysCache(tuple);
table_close(constrRel, RowExclusiveLock);
}
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index cb75e11fced..f5f8ec791c3 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -180,7 +180,7 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
AclResult aclresult;
Datum *values;
bool *nulls;
- bool *replaces;
+ Bitmapset *updated = NULL;
NameData nameattrdata;
oldtup = SearchSysCache1(oidCacheId, ObjectIdGetDatum(objectId));
@@ -326,15 +326,21 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
/* Build modified tuple */
values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
- replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
+
+ /*
+ * NOTE: We can't use the HeapTupleMarkColumnUpdated() macro here because
+ * 'Anum_name' isn't a table/column name, it's a index for the relation
+ * passed into the function as an argument.
+ */
namestrcpy(&nameattrdata, new_name);
values[Anum_name - 1] = NameGetDatum(&nameattrdata);
- replaces[Anum_name - 1] = true;
- newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
- values, nulls, replaces);
+ updated = bms_add_member(updated, Anum_name - FirstLowInvalidHeapAttributeNumber);
+
+ newtup = heap_update_tuple(oldtup, RelationGetDescr(rel),
+ values, nulls, updated);
/* Perform actual update */
- CatalogTupleUpdate(rel, &oldtup->t_self, newtup);
+ CatalogTupleUpdate(rel, &oldtup->t_self, newtup, updated, NULL);
InvokeObjectPostAlterHook(classId, objectId, 0);
@@ -357,7 +363,7 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
/* Release memory */
pfree(values);
pfree(nulls);
- pfree(replaces);
+ bms_free(updated);
heap_freetuple(newtup);
ReleaseSysCache(oldtup);
@@ -705,7 +711,7 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
newtup;
Datum *values;
bool *nulls;
- bool *replaces;
+ Bitmapset *updated = NULL;
tup = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objid));
if (!HeapTupleIsValid(tup)) /* should not happen */
@@ -804,19 +810,21 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
/* Build modified tuple */
values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
- replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
+
+ /* NOTE: Don't use the HeapTupleMarkColumnUpdated() macro here either. */
values[Anum_namespace - 1] = ObjectIdGetDatum(nspOid);
- replaces[Anum_namespace - 1] = true;
- newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
- values, nulls, replaces);
+ updated = bms_add_member(updated, Anum_namespace - FirstLowInvalidHeapAttributeNumber);
+
+ newtup = heap_update_tuple(tup, RelationGetDescr(rel),
+ values, nulls, updated);
/* Perform actual update */
- CatalogTupleUpdate(rel, &tup->t_self, newtup);
+ CatalogTupleUpdate(rel, &tup->t_self, newtup, updated, NULL);
/* Release memory */
pfree(values);
pfree(nulls);
- pfree(replaces);
+ bms_free(updated);
/* update dependency to point to the new schema */
if (changeDependencyFor(classId, objid,
@@ -967,7 +975,7 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
HeapTuple newtup;
Datum *values;
bool *nulls;
- bool *replaces;
+ Bitmapset *updated = NULL;
/* Superusers can bypass permission checks */
if (!superuser())
@@ -1014,9 +1022,12 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
nattrs = RelationGetNumberOfAttributes(rel);
values = palloc0(nattrs * sizeof(Datum));
nulls = palloc0(nattrs * sizeof(bool));
- replaces = palloc0(nattrs * sizeof(bool));
+
+ /*
+ * NOTE: Don't use the HeapTupleMarkColumnUpdated() macro here either.
+ */
values[Anum_owner - 1] = ObjectIdGetDatum(new_ownerId);
- replaces[Anum_owner - 1] = true;
+ updated = bms_add_member(updated, Anum_owner - FirstLowInvalidHeapAttributeNumber);
/*
* Determine the modified ACL for the new owner. This is only
@@ -1032,16 +1043,21 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
newAcl = aclnewowner(DatumGetAclP(datum),
old_ownerId, new_ownerId);
+
+ /*
+ * NOTE: Don't use the HeapTupleMarkColumnUpdated() macro here
+ * either.
+ */
values[Anum_acl - 1] = PointerGetDatum(newAcl);
- replaces[Anum_acl - 1] = true;
+ updated = bms_add_member(updated, Anum_acl - FirstLowInvalidHeapAttributeNumber);
}
}
- newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
- values, nulls, replaces);
+ newtup = heap_update_tuple(oldtup, RelationGetDescr(rel),
+ values, nulls, updated);
/* Perform actual update */
- CatalogTupleUpdate(rel, &newtup->t_self, newtup);
+ CatalogTupleUpdate(rel, &newtup->t_self, newtup, updated, NULL);
UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock);
@@ -1051,7 +1067,7 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
/* Release memory */
pfree(values);
pfree(nulls);
- pfree(replaces);
+ bms_free(updated);
}
else
UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock);
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 25089fae3e0..514742195b8 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -12,6 +12,7 @@
*
*-------------------------------------------------------------------------
*/
+#include "catalog/pg_statistic_d.h"
#include "postgres.h"
#include <math.h>
@@ -1668,48 +1669,34 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
VacAttrStats *stats = vacattrstats[attno];
HeapTuple stup,
oldtup;
- int i,
- k,
+ int k,
n;
- Datum values[Natts_pg_statistic];
- bool nulls[Natts_pg_statistic];
- bool replaces[Natts_pg_statistic];
+ Datum values[Natts_pg_statistic] = {0};
+ bool nulls[Natts_pg_statistic] = {false};
+ Bitmapset *updated = NULL;
/* Ignore attr if we weren't able to collect stats */
if (!stats->stats_valid)
continue;
- /*
- * Construct a new pg_statistic tuple
- */
- for (i = 0; i < Natts_pg_statistic; ++i)
- {
- nulls[i] = false;
- replaces[i] = true;
- }
+ /* Construct a new pg_statistic tuple */
+ HeapTupleUpdateSetAllColumnsUpdated(pg_statistic, updated);
+ HeapTupleSetValue(pg_statistic, starelid, ObjectIdGetDatum(relid), values);
+ HeapTupleSetValue(pg_statistic, staattnum, Int16GetDatum(stats->tupattnum), values);
+ HeapTupleSetValue(pg_statistic, stainherit, BoolGetDatum(inh), 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);
- values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(relid);
- values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(stats->tupattnum);
- values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(inh);
- 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);
- i = Anum_pg_statistic_stakind1 - 1;
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
- {
- values[i++] = Int16GetDatum(stats->stakind[k]); /* stakindN */
- }
- i = Anum_pg_statistic_staop1 - 1;
+ HeapTupleSetValue(pg_statistic, stakind1 + k, Int16GetDatum(stats->stakind[k]), values);
+
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
- {
- values[i++] = ObjectIdGetDatum(stats->staop[k]); /* staopN */
- }
- i = Anum_pg_statistic_stacoll1 - 1;
+ HeapTupleSetValue(pg_statistic, staop1 + k, ObjectIdGetDatum(stats->staop[k]), values);
+
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
- {
- values[i++] = ObjectIdGetDatum(stats->stacoll[k]); /* stacollN */
- }
- i = Anum_pg_statistic_stanumbers1 - 1;
+ HeapTupleSetValue(pg_statistic, stacoll1 + k, ObjectIdGetDatum(stats->stacoll[k]), values);
+
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
{
if (stats->stanumbers[k] != NULL)
@@ -1721,15 +1708,12 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
for (n = 0; n < nnum; n++)
numdatums[n] = Float4GetDatum(stats->stanumbers[k][n]);
arry = construct_array_builtin(numdatums, nnum, FLOAT4OID);
- values[i++] = PointerGetDatum(arry); /* stanumbersN */
+ HeapTupleSetValue(pg_statistic, stanumbers1 + k, PointerGetDatum(arry), values);
}
else
- {
- nulls[i] = true;
- values[i++] = (Datum) 0;
- }
+ HeapTupleSetFieldNull(pg_statistic, stanumbers1 + k, nulls);
}
- i = Anum_pg_statistic_stavalues1 - 1;
+
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
{
if (stats->stavalues[k] != NULL)
@@ -1742,12 +1726,11 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
stats->statyplen[k],
stats->statypbyval[k],
stats->statypalign[k]);
- values[i++] = PointerGetDatum(arry); /* stavaluesN */
+ HeapTupleSetValue(pg_statistic, stavalues1 + k, PointerGetDatum(arry), values);
}
else
{
- nulls[i] = true;
- values[i++] = (Datum) 0;
+ HeapTupleSetFieldNull(pg_statistic, stavalues1 + k, nulls);
}
}
@@ -1764,22 +1747,23 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
if (HeapTupleIsValid(oldtup))
{
/* Yes, replace it */
- stup = heap_modify_tuple(oldtup,
+ stup = heap_update_tuple(oldtup,
RelationGetDescr(sd),
values,
nulls,
- replaces);
+ updated);
ReleaseSysCache(oldtup);
- CatalogTupleUpdateWithInfo(sd, &stup->t_self, stup, indstate);
+ CatalogTupleUpdate(sd, &stup->t_self, stup, updated, indstate);
}
else
{
/* No, insert new tuple */
stup = heap_form_tuple(RelationGetDescr(sd), values, nulls);
- CatalogTupleInsertWithInfo(sd, stup, indstate);
+ CatalogTupleInsert(sd, stup, NULL);
}
heap_freetuple(stup);
+ bms_free(updated);
}
if (indstate != NULL)
diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c
index ef4d768feab..817db4cdefb 100644
--- a/src/backend/statistics/attribute_stats.c
+++ b/src/backend/statistics/attribute_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 "catalog/pg_collation.h"
@@ -120,15 +121,15 @@ static bool get_elem_stat_type(Oid atttypid, char atttyptype,
Oid *elemtypid, Oid *elem_eq_opr);
static Datum text_to_stavalues(const char *staname, FmgrInfo *array_in, Datum d,
Oid typid, int32 typmod, bool *ok);
-static void set_stats_slot(Datum *values, bool *nulls, bool *replaces,
- int16 stakind, Oid staop, Oid stacoll,
- Datum stanumbers, bool stanumbers_isnull,
- Datum stavalues, bool stavalues_isnull);
+static Bitmapset *set_stats_slot(Datum *values, bool *nulls, Bitmapset *updated,
+ int16 stakind, Oid staop, Oid stacoll,
+ Datum stanumbers, bool stanumbers_isnull,
+ Datum stavalues, bool stavalues_isnull);
static void upsert_pg_statistic(Relation starel, HeapTuple oldtup,
- const Datum *values, const bool *nulls, const bool *replaces);
+ const Datum *values, const bool *nulls, const Bitmapset *updated);
static bool delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit);
-static void init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited,
- Datum *values, bool *nulls, bool *replaces);
+static Bitmapset *init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited,
+ Datum *values, bool *nulls, Bitmapset *updated);
/*
* Insert or Update Attribute Statistics
@@ -184,9 +185,8 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
!PG_ARGISNULL(RANGE_EMPTY_FRAC_ARG);
Datum values[Natts_pg_statistic] = {0};
- bool nulls[Natts_pg_statistic] = {0};
- bool replaces[Natts_pg_statistic] = {0};
-
+ bool nulls[Natts_pg_statistic] = {false};
+ Bitmapset *updated = NULL;
bool result = true;
stats_check_required_arg(fcinfo, attarginfo, ATTRELSCHEMA_ARG);
@@ -361,25 +361,17 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (HeapTupleIsValid(statup))
heap_deform_tuple(statup, RelationGetDescr(starel), values, nulls);
else
- init_empty_stats_tuple(reloid, attnum, inherited, values, nulls,
- replaces);
+ updated = init_empty_stats_tuple(reloid, attnum, inherited, values, nulls, updated);
/* if specified, set to argument values */
if (!PG_ARGISNULL(NULL_FRAC_ARG))
- {
- values[Anum_pg_statistic_stanullfrac - 1] = PG_GETARG_DATUM(NULL_FRAC_ARG);
- replaces[Anum_pg_statistic_stanullfrac - 1] = true;
- }
+ HeapTupleUpdateValue(pg_statistic, stanullfrac, PG_GETARG_DATUM(NULL_FRAC_ARG), values, nulls, updated);
+
if (!PG_ARGISNULL(AVG_WIDTH_ARG))
- {
- values[Anum_pg_statistic_stawidth - 1] = PG_GETARG_DATUM(AVG_WIDTH_ARG);
- replaces[Anum_pg_statistic_stawidth - 1] = true;
- }
+ HeapTupleUpdateValue(pg_statistic, stawidth, PG_GETARG_DATUM(AVG_WIDTH_ARG), values, nulls, updated);
+
if (!PG_ARGISNULL(N_DISTINCT_ARG))
- {
- values[Anum_pg_statistic_stadistinct - 1] = PG_GETARG_DATUM(N_DISTINCT_ARG);
- replaces[Anum_pg_statistic_stadistinct - 1] = true;
- }
+ HeapTupleUpdateValue(pg_statistic, stadistinct, PG_GETARG_DATUM(N_DISTINCT_ARG), values, nulls, updated);
/* STATISTIC_KIND_MCV */
if (do_mcv)
@@ -394,10 +386,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (converted)
{
- set_stats_slot(values, nulls, replaces,
- STATISTIC_KIND_MCV,
- eq_opr, atttypcoll,
- stanumbers, false, stavalues, false);
+ updated = set_stats_slot(values, nulls, updated,
+ STATISTIC_KIND_MCV,
+ eq_opr, atttypcoll,
+ stanumbers, false, stavalues, false);
}
else
result = false;
@@ -417,10 +409,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (converted)
{
- set_stats_slot(values, nulls, replaces,
- STATISTIC_KIND_HISTOGRAM,
- lt_opr, atttypcoll,
- 0, true, stavalues, false);
+ updated = set_stats_slot(values, nulls, updated,
+ STATISTIC_KIND_HISTOGRAM,
+ lt_opr, atttypcoll,
+ 0, true, stavalues, false);
}
else
result = false;
@@ -433,10 +425,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
ArrayType *arry = construct_array_builtin(elems, 1, FLOAT4OID);
Datum stanumbers = PointerGetDatum(arry);
- set_stats_slot(values, nulls, replaces,
- STATISTIC_KIND_CORRELATION,
- lt_opr, atttypcoll,
- stanumbers, false, 0, true);
+ updated = set_stats_slot(values, nulls, updated,
+ STATISTIC_KIND_CORRELATION,
+ lt_opr, atttypcoll,
+ stanumbers, false, 0, true);
}
/* STATISTIC_KIND_MCELEM */
@@ -454,10 +446,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (converted)
{
- set_stats_slot(values, nulls, replaces,
- STATISTIC_KIND_MCELEM,
- elem_eq_opr, atttypcoll,
- stanumbers, false, stavalues, false);
+ updated = set_stats_slot(values, nulls, updated,
+ STATISTIC_KIND_MCELEM,
+ elem_eq_opr, atttypcoll,
+ stanumbers, false, stavalues, false);
}
else
result = false;
@@ -468,10 +460,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
{
Datum stanumbers = PG_GETARG_DATUM(ELEM_COUNT_HISTOGRAM_ARG);
- set_stats_slot(values, nulls, replaces,
- STATISTIC_KIND_DECHIST,
- elem_eq_opr, atttypcoll,
- stanumbers, false, 0, true);
+ updated = set_stats_slot(values, nulls, updated,
+ STATISTIC_KIND_DECHIST,
+ elem_eq_opr, atttypcoll,
+ stanumbers, false, 0, true);
}
/*
@@ -494,10 +486,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (converted)
{
- set_stats_slot(values, nulls, replaces,
- STATISTIC_KIND_BOUNDS_HISTOGRAM,
- InvalidOid, InvalidOid,
- 0, true, stavalues, false);
+ updated = set_stats_slot(values, nulls, updated,
+ STATISTIC_KIND_BOUNDS_HISTOGRAM,
+ InvalidOid, InvalidOid,
+ 0, true, stavalues, false);
}
else
result = false;
@@ -521,20 +513,21 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (converted)
{
- set_stats_slot(values, nulls, replaces,
- STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM,
- Float8LessOperator, InvalidOid,
- stanumbers, false, stavalues, false);
+ updated = set_stats_slot(values, nulls, updated,
+ STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM,
+ Float8LessOperator, InvalidOid,
+ stanumbers, false, stavalues, false);
}
else
result = false;
}
- upsert_pg_statistic(starel, statup, values, nulls, replaces);
+ upsert_pg_statistic(starel, statup, values, nulls, updated);
if (HeapTupleIsValid(statup))
ReleaseSysCache(statup);
table_close(starel, RowExclusiveLock);
+ bms_free(updated);
return result;
}
@@ -759,69 +752,63 @@ text_to_stavalues(const char *staname, FmgrInfo *array_in, Datum d, Oid typid,
* Find and update the slot with the given stakind, or use the first empty
* slot.
*/
-static void
-set_stats_slot(Datum *values, bool *nulls, bool *replaces,
+static Bitmapset *
+set_stats_slot(Datum *values, bool *nulls, Bitmapset *updated,
int16 stakind, Oid staop, Oid stacoll,
Datum stanumbers, bool stanumbers_isnull,
Datum stavalues, bool stavalues_isnull)
{
- int slotidx;
+ int i = 0;
int first_empty = -1;
- AttrNumber stakind_attnum;
- AttrNumber staop_attnum;
- AttrNumber stacoll_attnum;
- /* find existing slot with given stakind */
- for (slotidx = 0; slotidx < STATISTIC_NUM_SLOTS; slotidx++)
+ /*
+ * NOTE: This might seem odd, to be adding 'i' to the name of the field on
+ * these macros, but that's what we need to do here to find the proper
+ * slot offset and record the proper value into the updated bitmap.
+ *
+ * Example: HeapTupleValue(pg_statistic, stakind1 + i, values);
+ *
+ * Becomes: values[Anum_pg_statistic_stakind1 + i - 1];
+ *
+ * The result is you're indexing the i'th value, exactly what we needed.
+ */
+
+ /* Find existing slot with given stakind */
+ for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
{
- stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx;
+ Datum d = HeapTupleValue(pg_statistic, stakind1 + i, values);
+ int16 v = DatumGetInt16(d);
+
+ if (first_empty < 0 && v == 0)
+ first_empty = i;
- if (first_empty < 0 &&
- DatumGetInt16(values[stakind_attnum]) == 0)
- first_empty = slotidx;
- if (DatumGetInt16(values[stakind_attnum]) == stakind)
+ if (v == stakind)
break;
}
- if (slotidx >= STATISTIC_NUM_SLOTS && first_empty >= 0)
- slotidx = first_empty;
+ if (i >= STATISTIC_NUM_SLOTS && first_empty >= 0)
+ i = first_empty;
- if (slotidx >= STATISTIC_NUM_SLOTS)
+ if (i >= STATISTIC_NUM_SLOTS)
ereport(ERROR,
- (errmsg("maximum number of statistics slots exceeded: %d",
- slotidx + 1)));
+ (errmsg("maximum number of statistics slots exceeded: %d", i + 1)));
- stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx;
- staop_attnum = Anum_pg_statistic_staop1 - 1 + slotidx;
- stacoll_attnum = Anum_pg_statistic_stacoll1 - 1 + slotidx;
+ if (DatumGetInt16(HeapTupleValue(pg_statistic, stakind1 + i, values)) != stakind)
+ HeapTupleUpdateValue(pg_statistic, stakind1 + i, Int16GetDatum(stakind), values, nulls, updated);
+
+ if (DatumGetInt16(HeapTupleValue(pg_statistic, staop1 + i, values)) != staop)
+ HeapTupleUpdateValue(pg_statistic, staop1 + i, ObjectIdGetDatum(staop), values, nulls, updated);
+
+ if (DatumGetInt16(HeapTupleValue(pg_statistic, stacoll1 + i, values + i)) != stacoll)
+ HeapTupleUpdateValue(pg_statistic, stacoll1 + i, ObjectIdGetDatum(stacoll), values, nulls, updated);
- if (DatumGetInt16(values[stakind_attnum]) != stakind)
- {
- values[stakind_attnum] = Int16GetDatum(stakind);
- replaces[stakind_attnum] = true;
- }
- if (DatumGetObjectId(values[staop_attnum]) != staop)
- {
- values[staop_attnum] = ObjectIdGetDatum(staop);
- replaces[staop_attnum] = true;
- }
- if (DatumGetObjectId(values[stacoll_attnum]) != stacoll)
- {
- values[stacoll_attnum] = ObjectIdGetDatum(stacoll);
- replaces[stacoll_attnum] = true;
- }
if (!stanumbers_isnull)
- {
- values[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = stanumbers;
- nulls[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = false;
- replaces[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = true;
- }
+ HeapTupleUpdateValue(pg_statistic, stanumbers1 + i, stanumbers, values, nulls, updated);
+
if (!stavalues_isnull)
- {
- values[Anum_pg_statistic_stavalues1 - 1 + slotidx] = stavalues;
- nulls[Anum_pg_statistic_stavalues1 - 1 + slotidx] = false;
- replaces[Anum_pg_statistic_stavalues1 - 1 + slotidx] = true;
- }
+ HeapTupleUpdateValue(pg_statistic, stavalues1 + i, stavalues, values, nulls, updated);
+
+ return updated;
}
/*
@@ -829,20 +816,21 @@ set_stats_slot(Datum *values, bool *nulls, bool *replaces,
*/
static void
upsert_pg_statistic(Relation starel, HeapTuple oldtup,
- const Datum *values, const bool *nulls, const bool *replaces)
+ const Datum *values, const bool *nulls, const Bitmapset *updated)
{
HeapTuple newtup;
if (HeapTupleIsValid(oldtup))
{
- newtup = heap_modify_tuple(oldtup, RelationGetDescr(starel),
- values, nulls, replaces);
- CatalogTupleUpdate(starel, &newtup->t_self, newtup);
+ TupleDesc tupdesc = RelationGetDescr(starel);
+
+ newtup = heap_update_tuple(oldtup, tupdesc, values, nulls, updated);
+ CatalogTupleUpdate(starel, &newtup->t_self, newtup, updated, NULL);
}
else
{
newtup = heap_form_tuple(RelationGetDescr(starel), values, nulls);
- CatalogTupleInsert(starel, newtup);
+ CatalogTupleInsert(starel, newtup, NULL);
}
heap_freetuple(newtup);
@@ -883,39 +871,38 @@ delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit)
/*
* Initialize values and nulls for a new stats tuple.
*/
-static void
+static Bitmapset *
init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited,
- Datum *values, bool *nulls, bool *replaces)
+ Datum *values, bool *nulls, Bitmapset *updated)
{
+ /*
+ * NOTE: It is customary to initialize the "nulls" array to all false (0)
+ * and later, when some field transitions from a value to NULL to mark
+ * that transition using the proper macro which will set the array
+ * position to true (1). Here we start with the assumption that all
+ * values will be set to NULL.
+ */
+ HeapTupleUpdateSetAllColumnsUpdated(pg_statistic, updated);
memset(nulls, true, sizeof(bool) * Natts_pg_statistic);
- memset(replaces, true, sizeof(bool) * Natts_pg_statistic);
/* must initialize non-NULL attributes */
+ HeapTupleUpdateValue(pg_statistic, starelid, ObjectIdGetDatum(reloid), values, nulls, updated);
+ HeapTupleUpdateValue(pg_statistic, staattnum, Int16GetDatum(attnum), values, nulls, updated);
+ HeapTupleUpdateValue(pg_statistic, stainherit, BoolGetDatum(inherited), values, nulls, updated);
- values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(reloid);
- nulls[Anum_pg_statistic_starelid - 1] = false;
- values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(attnum);
- nulls[Anum_pg_statistic_staattnum - 1] = false;
- values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(inherited);
- nulls[Anum_pg_statistic_stainherit - 1] = false;
-
- values[Anum_pg_statistic_stanullfrac - 1] = DEFAULT_NULL_FRAC;
- nulls[Anum_pg_statistic_stanullfrac - 1] = false;
- values[Anum_pg_statistic_stawidth - 1] = DEFAULT_AVG_WIDTH;
- nulls[Anum_pg_statistic_stawidth - 1] = false;
- values[Anum_pg_statistic_stadistinct - 1] = DEFAULT_N_DISTINCT;
- nulls[Anum_pg_statistic_stadistinct - 1] = false;
+ HeapTupleUpdateValue(pg_statistic, stanullfrac, DEFAULT_NULL_FRAC, values, nulls, updated);
+ HeapTupleUpdateValue(pg_statistic, stawidth, DEFAULT_AVG_WIDTH, values, nulls, updated);
+ HeapTupleUpdateValue(pg_statistic, stadistinct, DEFAULT_N_DISTINCT, values, nulls, updated);
/* initialize stakind, staop, and stacoll slots */
- for (int slotnum = 0; slotnum < STATISTIC_NUM_SLOTS; slotnum++)
+ for (int i = 0; i < STATISTIC_NUM_SLOTS; i++)
{
- values[Anum_pg_statistic_stakind1 + slotnum - 1] = (Datum) 0;
- nulls[Anum_pg_statistic_stakind1 + slotnum - 1] = false;
- values[Anum_pg_statistic_staop1 + slotnum - 1] = ObjectIdGetDatum(InvalidOid);
- nulls[Anum_pg_statistic_staop1 + slotnum - 1] = false;
- values[Anum_pg_statistic_stacoll1 + slotnum - 1] = ObjectIdGetDatum(InvalidOid);
- nulls[Anum_pg_statistic_stacoll1 + slotnum - 1] = false;
+ HeapTupleUpdateValue(pg_statistic, stakind1 + i, (Datum) 0, values, nulls, updated);
+ HeapTupleUpdateValue(pg_statistic, staop1 + i, ObjectIdGetDatum(InvalidOid), values, nulls, updated);
+ HeapTupleUpdateValue(pg_statistic, stacoll1 + i, ObjectIdGetDatum(InvalidOid), values, nulls, updated);
}
+
+ return updated;
}
/*
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
index f6b766697e2..e67bb718efa 100644
--- a/src/include/access/htup.h
+++ b/src/include/access/htup.h
@@ -14,6 +14,7 @@
#ifndef HTUP_H
#define HTUP_H
+#include "catalog/pg_aggregate_d.h"
#include "storage/itemptr.h"
/* typedefs and forward declarations for structs defined in htup_details.h */
@@ -77,6 +78,66 @@ typedef HeapTupleData *HeapTuple;
*/
#define HeapTupleIsValid(tuple) ((tuple) != NULL)
+#define HeapTupleValue(table_name, field, values) \
+ (values)[Anum_##table_name##_##field - 1]
+
+/*
+ * These are useful when forming tuples for CatalogTupleInsert()
+ */
+
+#define HeapTupleSetField(table_name, field, value, form_ptr) \
+ (form_ptr)->field = (value)
+
+#define HeapTupleSetFieldNull(table_name, field, nulls) \
+ (nulls)[Anum_##table_name##_##field - 1] = true
+
+#define HeapTupleSetValue(table_name, field, value, values) \
+ (values)[Anum_##table_name##_##field - 1] = (value)
+
+#define HeapTupleSetValueNull(table_name, field, values, nulls) \
+ do { \
+ (values)[Anum_##table_name##_##field - 1] = (Datum) 0; \
+ (nulls)[Anum_##table_name##_##field - 1] = true; \
+ } while(0)
+
+/*
+ * These are useful when forming tuples for CatalogTupleUpdate()
+ *
+ * Updated catalog tuples need to track which fields were changed when
+ * calling heap_update_tuple(), so we use a bitmap to keep track of that.
+ */
+#define HeapTupleMarkColumnUpdated(table_name, field, updated) \
+ (updated) = bms_add_member((updated), \
+ Anum_##table_name##_##field - FirstLowInvalidHeapAttributeNumber)
+
+#define HeapTupleUpdateSetAllColumnsUpdated(table_name, updated) \
+ (updated) = bms_add_range((updated), 1 - FirstLowInvalidHeapAttributeNumber, \
+ Natts_##table_name - FirstLowInvalidHeapAttributeNumber)
+
+#define HeapTupleSetColumnNotUpdated(table_name, field, updated) \
+ (updated) = bms_del_member((updated), \
+ Anum_##table_name##_##field - FirstLowInvalidHeapAttributeNumber)
+
+#define HeapTupleUpdateField(table_name, field, value, form_ptr, updated) \
+ do { \
+ (form_ptr)->field = (value); \
+ HeapTupleMarkColumnUpdated(table_name, field, updated); \
+ } while(0)
+
+#define HeapTupleUpdateValue(table_name, field, value, values, nulls, updated) \
+ do { \
+ (values)[Anum_##table_name##_##field - 1] = (Datum) (value); \
+ (nulls)[Anum_##table_name##_##field - 1] = false; \
+ HeapTupleMarkColumnUpdated(table_name, field, updated); \
+ } while(0)
+
+#define HeapTupleUpdateValueNull(table_name, field, values, nulls, updated) \
+ do { \
+ (values)[Anum_##table_name##_##field - 1] = (Datum) 0; \
+ (nulls)[Anum_##table_name##_##field - 1] = true; \
+ HeapTupleMarkColumnUpdated(table_name, field, updated); \
+ } while(0)
+
/* HeapTupleHeader functions implemented in utils/time/combocid.c */
extern CommandId HeapTupleHeaderGetCmin(const HeapTupleHeaderData *tup);
extern CommandId HeapTupleHeaderGetCmax(const HeapTupleHeaderData *tup);
diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h
index f3593acc8c2..814d764ee97 100644
--- a/src/include/access/htup_details.h
+++ b/src/include/access/htup_details.h
@@ -21,6 +21,9 @@
#include "storage/bufpage.h"
#include "varatt.h"
+/* Forward declarations */
+typedef struct Bitmapset Bitmapset;
+
/*
* MaxTupleAttributeNumber limits the number of (user) columns in a tuple.
* The key limit on this value is that the size of the fixed overhead for
@@ -835,6 +838,11 @@ extern HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple,
const int *replCols,
const Datum *replValues,
const bool *replIsnull);
+extern HeapTuple heap_update_tuple(HeapTuple tuple,
+ TupleDesc tupleDesc,
+ const Datum *replValues,
+ const bool *replIsnull,
+ const Bitmapset *replaces);
extern void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
Datum *values, bool *isnull);
extern void heap_freetuple(HeapTuple htup);
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 77c17d3fb7a..685ff3d2bd1 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -37,18 +37,13 @@ typedef struct ResultRelInfo *CatalogIndexState;
*/
extern CatalogIndexState CatalogOpenIndexes(Relation heapRel);
extern void CatalogCloseIndexes(CatalogIndexState indstate);
-extern void CatalogTupleInsert(Relation heapRel, HeapTuple tup);
-extern void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
- CatalogIndexState indstate);
-extern void CatalogTuplesMultiInsertWithInfo(Relation heapRel,
- TupleTableSlot **slot,
- int ntuples,
- CatalogIndexState indstate);
+extern void CatalogTupleInsert(Relation heapRel, HeapTuple tup,
+ CatalogIndexState indstate);
+extern void CatalogTuplesMultiInsert(Relation heapRel, TupleTableSlot **slot,
+ int ntuples, CatalogIndexState indstate);
extern void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid,
- HeapTuple tup);
-extern void CatalogTupleUpdateWithInfo(Relation heapRel,
- const ItemPointerData *otid, HeapTuple tup,
- CatalogIndexState indstate);
+ HeapTuple tuple, const struct Bitmapset *updated,
+ CatalogIndexState indstate);
extern void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid);
#endif /* INDEXING_H */
--
2.49.0
v1-0002-Update-the-remainder-of-catalog-updates-using-the.patchapplication/octet-streamDownload
From 0f83f789a1a605464d33d6a8f3856655b80efec9 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
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
On Fri, Nov 14, 2025 at 10:31:28AM -0500, Greg Burd wrote:
Catalog tuples have knowledge of what attributes are mutated implicitly,
but they don't preserve that information and so
HeapDetermineColumnsInfo() has to re-discover that later on (while the
page is locked). While on the surface this isn't such a big deal, it's
been that way and worked well for years I have other motivations (see
[1] again) for improving this.
Yeah, I've heard that this has been also discussed at the New York
pgconf, where designs were mentioned so as we do not execute
expressions while locking pages. One issue is that this could easily
deadlock if an expression has the idea to re-read the same page we are
locking. So I have a summary of what you have been doing in mind, a
very rough one I suspect.
That turned out to be a bit of a challenge as we have a lot of places
where catalog information is updated. We also have two different
methods for updating said information. And we intermix them. At times
we hack our way to a solution and ignore convention. I went down the
rabbit hole on this one, but I'm back up for a cup of tea because what
I've done seems materially better to me and I've accomplished the goal
(and can eventually make use of the result in [1]). Is this patch
useful even without that other work? I think so, just on the basis of
cleanup. Let me explain.
It's a mix of historical and individual commit style, so having things
slightly different depending on the catalog code path is not a
surprise, at least here.
[... Two methods for heap tuple updates ... ]
tuple = heap_modify_tuple(tuple, desc, values, nulls, replaces);
CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
As far as I can see after applying 0002, 90%-ish of the existing
callers of heap_modify_tuple() are updated to use heap_update_tuple().
That's interesting to see.
heap_update_tuple() is functionally equivalent to heap_modify_tuple(),
but takes a Bitmapset called "updated" rather than an array of bool
(generally) called "replaces" as a method for indicating what was
modified. Additionally, this new function tries to balance the
trade-offs of calling heap_getattr() versus heap_deform_tuple() based on
the ratio of attributes updated and their known runtime complexities.
Both paths are functionally equivalent.
I don't think that we can completely remove heap_update_tuple() as
code path used for the catalogs updates, but we can get very close to
that. Perhaps we should document at the top of heap_update_tuple()
that developers should not use this API for catalog changes, switching
to the bitmap interface instead in priority?
* Performance strategy:
* - If updating many attributes (> 2*natts/3), use heap_getattr() to extract
* only the few non-updated attributes. This is O(k*n) where k is the number
* of non-updated attributes, which is small when updating many.
* - If updating few attributes (<= 2*natts/3), use heap_deform_tuple() to
* extract all attributes at once (O(n)), then replace the updated ones.
* This avoids the O(n^2) cost of many heap_getattr() calls.
*
* The threshold of 2*natts/3 balances the fixed O(n) cost of heap_deform_tuple
* against the variable O(k*n) cost of heap_getattr, where k = natts - num_updated.
This change has been puzzling me quite a bit. Why this choice of
formula with 2/3 of arguments? The maximum number of arguments is
1400 by design, so would one choice matter more than the other in most
cases? Catalogs don't have that many arguments either, so I am not
sure if we need to care with this amount of tuning, TBH, but I am OK
to be wrong.
indexing.c: has the change to CatalogTupleUpdate/Insert and removal of
their "WithInfo" companions. If that second part is controversial then
I don't mind reverting it, but IMO this is cleaner and might either
inspire more call sites to create and reuse CatalogIndexState or for
someone (me?) to address the comment that pre-dates my work:
I'm OK with the simplification on this one, but let's make that a
separate patch extracted from 0001. The changes with
CatalogTupleUpdate() and CatalogTupleInsert() don't have to be
included with the changes that introduce a bitmap integration to track
the attributes that are updated. This is pointing to the fact that
there are not that many callers of the WithInfo() flavors in the tree,
compared to the non-info ones (24 AFAIK, vs 160-ish for the Insert
path it seems, for example).
pg_aggregate.c: in AggregateCreate() we run into a "compromise" pattern
where the code code either update or insert. In such cases hackers
should use the macros for update, not insert, everywhere. This records
the additional information for the update path and doesn't burden the
insert path with much more than a Bitmapset to free.
Hmm. Fine by me. The bitmap is not used for an INSERT path, so it's
a bit of a waste, but I can see why you have done so to satisfy the
"replace" case, from CREATE OR REPLACE (never liked this kind of
grammar as it can be impredictible implementation-wise with syscache
lookups required, just a personal rant).
Another thing that you could do here is enforce a check in a couple of
places where CatalogTupleInsert() is called for the "updated" bitmap:
all the bits in the map should be set, like in OperatorCreate(). That
may catch bugs at runtime perhaps when adding fields when dealing with
an insert instead of an update?
pg_constraint.c: brings us to namestrcpy(), take a look at
RenameConstraintById(). When you run into namestrcpy() you've likely
just done the mutation to the form directly but you'll want to mark that
field as updated, as in:alter.c: take a look at AlterObjectRename_internal() which uses
get_object_attnum_name() to get the AttrNumber that is to be altered.
This is fine, but it's not something we can just plug into a macro and
get the proper name expansion. So, we do it the manual way and add a comment:
Not surprising to have exceptions like that. This is a global path
used for the renames of a bunch of objects. This makes me wonder if
we really have to absolutely change all the code paths that currently
use heap_modify_tuple(). Like this one in alter.c for renames, the
change is not an improvement in readability. Same for
AlterObjectNamespace_internal(). These would live better if still
based on heap_modify_tuple(), because of the fact that they can be fed
several object types.
analyze.c: uses the HeapTupleSetAllColumnsUpdated() at the start of the
update_attstats() function to match the replaced code. Later there's
another interesting deviation from the normal pattern in that function
where we want to update the nth stakind/opt/coll this was frustrating at
first until I found that this worked:HeapTupleSetValue(pg_statistic, stakind1 + k,
Int16GetDatum(stats->stakind[k]), values);
I'm getting concerned about HeapTupleSetAllColumnsUpdated() while
reaching this part of your message, FWIW.
So, we're taking the attribute number adding "k" then subtracting 1, and
voila "Bob's your uncle." While a bit unconventional, I think the
resulting form is understandable, much more than before which was:i = Anum_pg_statistic_stakind1 - 1;
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
values[i++] = Int16GetDatum(stats->stakind[k]); /* stakindN */
And more concerns. This change makes me question how wise it is to
have HeapTupleUpdateSetAllColumnsUpdated(), actually. Couldn't this
encourage bugs if somebody forgets to update some of the fields in the
new tuple, still the bitmap has been updated with a range to mark all
the attributes as updated. Having HeapTupleUpdateField() do an update
of the bitmap makes sure that the bitmap and the fields updated are
never out-of-sync. I'm OK with marking the individual attributes as
updated. Having a more aggressive API that marks all of them as
updated sounds dangerous to me.
0002 - Update the remainder of catalog updates using the new APIs
This is a lot of applying the pattern over and over until it all works.
That's it. Nothing much more interesting here.This is a lot of change, I get that, I think there's value in change
when the result is cleaner and more maintainable. The one place I'll
agree up front where this might case problems is back-patching fixes.
That'll have to have the new approach in some branches and the old
approach in others. It's a 5-year commitment, I don't take that lightly.
Backpatches imply catalog tuple manipulations from time to time, so
that would create noise, yes.
If you made it this far, I owe you a beer/coffee/token-of-appreciation.
Sentence noted.
Without this patch my [1] will have an ugly wart
(HeapDetermineColumnsInfo()) for the CatalogTupleUpdate path only. I
can live with that, I'd rather not.
It seems to me that this answer is better answered as "rather not",
especially if this improves the code maintenance in the long-term.
Patch 0001 could be split into more pieces, particularly regarding the
argument it makes about the fact that there are few callers of
CatalogTuplesMultiInsertWithInfo(), CatalogTupleInsertWithInfo() and
CatalogTupleUpdateWithInfo(), where we can just plug NULL for the
index state. I'd suggest to make these routines leaner in a first
patch.
/* No, insert new tuple */
stup = heap_form_tuple(RelationGetDescr(sd), values, nulls);
- CatalogTupleInsertWithInfo(sd, stup, indstate);
+ CatalogTupleInsert(sd, stup, NULL);
}
This one in update_attstats() looks wrong. Why are you passing NULL
instead of an opened index state? We keep track of indstate for all
the pg_statistic tuples updated.
HeapTupleSetField() is used nowhere. Do we really need it?
--
Michael
On Dec 2 2025, at 2:09 am, Michael Paquier <michael@paquier.xyz> wrote:
On Fri, Nov 14, 2025 at 10:31:28AM -0500, Greg Burd wrote:
Catalog tuples have knowledge of what attributes are mutated implicitly,
but they don't preserve that information and so
HeapDetermineColumnsInfo() has to re-discover that later on (while the
page is locked). While on the surface this isn't such a big deal, it's
been that way and worked well for years I have other motivations (see
[1] again) for improving this.Yeah, I've heard that this has been also discussed at the New York
pgconf, where designs were mentioned so as we do not execute
expressions while locking pages. One issue is that this could easily
deadlock if an expression has the idea to re-read the same page we are
locking. So I have a summary of what you have been doing in mind, a
very rough one I suspect.
Hi Michael,
Thanks for taking the time to review this chunky patch. I've been
quietly reworking it a bit, I'll go over that in a bit because I'd
appreciate opinions before I'm too far into the changes.
Yes, the motivation for this patch started off as a secondary effect of
the other work I've mentioned. It's morphing a bit given some feedback
off-list. There are a few reasons to standardize catalog modification
code and move it away from direct Form/GETSTRUCT or
values/nulls/replaces-style access. First, these current methods can be
error prone and require attention to a variety of details that can
easily be overlooked. Second, at present while we know what fields are
modified we don't preserve that information and pass it on to the
heap_update() code. Third, I understand that at some point we'll need
in-memory representations completely decoupled from the disk to support
upgradeable catalogs. I started off just trying to make
HeapDetermineColumnsInfo() go away, these seem like good goals as well
and touch the same area of code. I think, if possible, it would make
sense to ensure that a large-ish change like this doesn't need to be
undone/redone to accomplish these other goals.
That turned out to be a bit of a challenge as we have a lot of places
where catalog information is updated. We also have two different
methods for updating said information. And we intermix them. At times
we hack our way to a solution and ignore convention. I went down the
rabbit hole on this one, but I'm back up for a cup of tea because what
I've done seems materially better to me and I've accomplished the goal
(and can eventually make use of the result in [1]). Is this patch
useful even without that other work? I think so, just on the basis of
cleanup. Let me explain.It's a mix of historical and individual commit style, so having things
slightly different depending on the catalog code path is not a
surprise, at least here.
Got it, I don't begrudge anyone's style or how it's done now. I just
want to address the goals I've laid out and hopefully make things a bit
better along the way.
[... Two methods for heap tuple updates ... ]
tuple = heap_modify_tuple(tuple, desc, values, nulls, replaces);
CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);As far as I can see after applying 0002, 90%-ish of the existing
callers of heap_modify_tuple() are updated to use heap_update_tuple().
That's interesting to see.
Yes, that was intentional.
heap_update_tuple() is functionally equivalent to heap_modify_tuple(),
but takes a Bitmapset called "updated" rather than an array of bool
(generally) called "replaces" as a method for indicating what was
modified. Additionally, this new function tries to balance the
trade-offs of calling heap_getattr() versus heap_deform_tuple() based on
the ratio of attributes updated and their known runtime complexities.
Both paths are functionally equivalent.
[NOTE: below I think you meant to say "heap_modify_tuple()", so I
correct it]
I don't think that we can completely remove heap_modify_tuple() as
code path used for the catalogs updates, but we can get very close to
that. Perhaps we should document at the top of heap_modify_tuple()
that developers should not use this API for catalog changes, switching
to the bitmap interface instead in priority?
I agree that it's hard to remove heap_modify_tuple() function straight
away which is why I kept it in and created a new function
heap_update_tuple(). I agree, comments are needed to explain why and
point out the preferred way.
* Performance strategy:
* - If updating many attributes (> 2*natts/3), use heap_getattr() to extract
* only the few non-updated attributes. This is O(k*n) where k is
the number
* of non-updated attributes, which is small when updating many.
* - If updating few attributes (<= 2*natts/3), use
heap_deform_tuple() to
* extract all attributes at once (O(n)), then replace the updated ones.
* This avoids the O(n^2) cost of many heap_getattr() calls.
*
* The threshold of 2*natts/3 balances the fixed O(n) cost of heap_deform_tuple
* against the variable O(k*n) cost of heap_getattr, where k = natts
- num_updated.This change has been puzzling me quite a bit. Why this choice of
formula with 2/3 of arguments? The maximum number of arguments is
1400 by design, so would one choice matter more than the other in most
cases? Catalogs don't have that many arguments either, so I am not
sure if we need to care with this amount of tuning, TBH, but I am OK
to be wrong.
Good points, I saw the comment about optimizing it and I took a swing.
There are two categories for catalog updates, changing a few or setting
them all. My hope was to choose the less computationally onerous path
based on the ratio of the amount updated vs the number in the relation.
indexing.c: has the change to CatalogTupleUpdate/Insert and removal of
their "WithInfo" companions. If that second part is controversial then
I don't mind reverting it, but IMO this is cleaner and might either
inspire more call sites to create and reuse CatalogIndexState or for
someone (me?) to address the comment that pre-dates my work:I'm OK with the simplification on this one, but let's make that a
separate patch extracted from 0001. The changes with
CatalogTupleUpdate() and CatalogTupleInsert() don't have to be
included with the changes that introduce a bitmap integration to track
the attributes that are updated. This is pointing to the fact that
there are not that many callers of the WithInfo() flavors in the tree,
compared to the non-info ones (24 AFAIK, vs 160-ish for the Insert
path it seems, for example).
That makes sense, but another approach is to do the work mentioned in
the comment and somehow cache the CatalogIndexState (which is a somewhat
redacted ResultRelInfo by another name) somewhere.
pg_aggregate.c: in AggregateCreate() we run into a "compromise" pattern
where the code code either update or insert. In such cases hackers
should use the macros for update, not insert, everywhere. This records
the additional information for the update path and doesn't burden the
insert path with much more than a Bitmapset to free.Hmm. Fine by me. The bitmap is not used for an INSERT path, so it's
a bit of a waste, but I can see why you have done so to satisfy the
"replace" case, from CREATE OR REPLACE (never liked this kind of
grammar as it can be impredictible implementation-wise with syscache
lookups required, just a personal rant).
Right, this isn't ideal. The "waste" of alloc/free of a Bitmapset is
real, and different people will have different views on that, but IMO
it's worth it. That said, I did rethink this a bit more.
Another thing that you could do here is enforce a check in a couple of
places where CatalogTupleInsert() is called for the "updated" bitmap:
all the bits in the map should be set, like in OperatorCreate(). That
may catch bugs at runtime perhaps when adding fields when dealing with
an insert instead of an update?
That's not a bad idea, catching bugs early is a good outcome.
pg_constraint.c: brings us to namestrcpy(), take a look at
RenameConstraintById(). When you run into namestrcpy() you've likely
just done the mutation to the form directly but you'll want to mark that
field as updated, as in:alter.c: take a look at AlterObjectRename_internal() which uses
get_object_attnum_name() to get the AttrNumber that is to be altered.
This is fine, but it's not something we can just plug into a macro and
get the proper name expansion. So, we do it the manual way and add a comment:Not surprising to have exceptions like that. This is a global path
used for the renames of a bunch of objects. This makes me wonder if
we really have to absolutely change all the code paths that currently
use heap_modify_tuple(). Like this one in alter.c for renames, the
change is not an improvement in readability. Same for
AlterObjectNamespace_internal(). These would live better if still
based on heap_modify_tuple(), because of the fact that they can be fed
several object types.
I'd agree except that the paths using heap_update_tuple() won't benefit
from HOT updates.
I think readability is debatable, but I am playing games with macros
which at times makes me feel a bit dirty.
analyze.c: uses the HeapTupleSetAllColumnsUpdated() at the start of the
update_attstats() function to match the replaced code. Later there's
another interesting deviation from the normal pattern in that function
where we want to update the nth stakind/opt/coll this was frustrating at
first until I found that this worked:HeapTupleSetValue(pg_statistic, stakind1 + k,
Int16GetDatum(stats->stakind[k]), values);I'm getting concerned about HeapTupleSetAllColumnsUpdated() while
reaching this part of your message, FWIW.
The reason for HeapTupleSetAllColumnsUpdated() was to mimic existing
logic and change as little as possible by simply adding a layer of
friendly macros into the mix.
So, we're taking the attribute number adding "k" then subtracting 1, and
voila "Bob's your uncle." While a bit unconventional, I think the
resulting form is understandable, much more than before which was:i = Anum_pg_statistic_stakind1 - 1;
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
values[i++] = Int16GetDatum(stats->stakind[k]); /* stakindN */And more concerns. This change makes me question how wise it is to
have HeapTupleUpdateSetAllColumnsUpdated(), actually. Couldn't this
encourage bugs if somebody forgets to update some of the fields in the
new tuple, still the bitmap has been updated with a range to mark all
the attributes as updated. Having HeapTupleUpdateField() do an update
of the bitmap makes sure that the bitmap and the fields updated are
never out-of-sync. I'm OK with marking the individual attributes as
updated. Having a more aggressive API that marks all of them as
updated sounds dangerous to me.
Well, sure I suppose so but again this was simply a replacement for the
existing code which initialized the "replaces" array to all true rather
than the normal case of all false.
0002 - Update the remainder of catalog updates using the new APIs
This is a lot of applying the pattern over and over until it all
works.
That's it. Nothing much more interesting here.This is a lot of change, I get that, I think there's value in change
when the result is cleaner and more maintainable. The one place I'll
agree up front where this might case problems is back-patching fixes.
That'll have to have the new approach in some branches and the old
approach in others. It's a 5-year commitment, I don't take that lightly.Backpatches imply catalog tuple manipulations from time to time, so
that would create noise, yes.If you made it this far, I owe you a
beer/coffee/token-of-appreciation.Sentence noted.
Excellent!
Without this patch my [1] will have an ugly wart
(HeapDetermineColumnsInfo()) for the CatalogTupleUpdate path only. I
can live with that, I'd rather not.It seems to me that this answer is better answered as "rather not",
especially if this improves the code maintenance in the long-term.Patch 0001 could be split into more pieces, particularly regarding the
argument it makes about the fact that there are few callers of
CatalogTuplesMultiInsertWithInfo(), CatalogTupleInsertWithInfo() and
CatalogTupleUpdateWithInfo(), where we can just plug NULL for the
index state. I'd suggest to make these routines leaner in a first
patch./* No, insert new tuple */ stup = heap_form_tuple(RelationGetDescr(sd), values, nulls); - CatalogTupleInsertWithInfo(sd, stup, indstate); + CatalogTupleInsert(sd, stup, NULL); }This one in update_attstats() looks wrong. Why are you passing NULL
instead of an opened index state? We keep track of indstate for all
the pg_statistic tuples updated.HeapTupleSetField() is used nowhere. Do we really need it?
--
Michael
As I hinted at earlier on, I've continue to develop this patch [1]https://github.com/gburd/postgres/pull/18.
It's not ready to post as patches just yet. I've paused making all the
changes as the time required is non-trivial. Here's some of what I
thought through and a taste so that I can (hopefully) get feedback (pos
or neg) before investing the rest of a week into updating every case.
bool replaces[Natts...] was static, Bitmapset * is a heap alloc/free
====================================================================
Yes, and I tried a few ideas out to avoid this. If you recall my
earlier work to test Bitmapset[2]/messages/by-id/7BD1ABDB-B03A-464A-9BA9-A73B55AD8A1F@getmailspring.com was in part to see if I could extend
that datatype to allow for a static version. Closest I could come was this
+#define CatalogUpdateContext(table_name, var, tuple) \
+ do { \
+ struct { \
+ bool nulls[Natts_##table_name]; \
+ Datum values[Natts_##table_name]; \
+ Bitmapset updated; \
+ bitmapword bits[BITMAPSET_SIZE(Natts_##table_name)]; \
+ } _##table_name##_##var##_ = {.nulls = {false}, .values = {0}, \
+ .updated.nwords = BITMAPSET_SIZE(Natts_##table_name), \
+ .updated.type = T_Bitmapset, .bits = {0} }; \
+ CatalogTupleContext *(var##_ctx) = \
+ (CatalogTupleContext *)&_##table_name##_##var##_; \
+ Form_##table_name (var##_form) = \
+ (Form_##table_name) GETSTRUCT(tuple); \
+ } while(0)
Which would create the right size statically allocated Bitmapset, but it
wouldn't be "valid" because the last word in the set is all zeros and so
calling into any function that calls bms_is_valid() would assert. I
could simply embed the logic for bms_add_member() etc into the macros,
but then I'd be creating a mess for the future. The only advantage is
that you'd be avoiding a palloc()/free() possibly a realloc(). There's
something to be said for that, but this felt a bit over the line.
When I thought about adding a patch that extended/changed Bitmapset to
allow for static allocation I felt that too would become the objection
that sinks this whole idea, so for now I'm not going to try that. Maybe
some other time.
In the end, after trying a few things (including pre-sizing the
Bitmapset by creating it as a singleton setting the Natts+1 value at
initialization to avoid realloc) I went back to accepting the
palloc/free model as simple enough.
E_TOO_MANY_MACROS
=======================================================================
I'm not thrilled with the multitude of macros for somewhat similar
cases. So I tried using _Generic(), but that's not supported on MSVC
and only allowed to be generic at compile time over a single type and
dispatch to a function, not another macro, so you couldn't simply
de-reference in the Form case.
+static inline void
+_CatalogTupleValueSet(CatalogTupleContext *ctx, int attnum, Datum
value, size_t off, size_t sz)
+{
+ ctx->values[attnum] = value;
+ ctx->nulls[attnum] = false;
+}
+
+static inline void
+_CatalogTupleFormSet(void *form, int attnum, Datum value,
+ size_t off, size_t sz)
+{
+ memcpy((char *)form + off, &value, sz);
+}
+
+#define CatalogTupleSet(ctx_or_form, table_name, field, value) \
+ _Generic((ctx_or_form), \
+ CatalogTupleContext *: _CatalogTupleValueSet, \
+ Form_##table_name * : _CatalogTupleFormSet \
+ )(ctx_or_form, \
+ Anum_##table_name##_##field - 1, \
+ value, \
+ offsetof(FormData_##table_name, field), \
+ sizeof(((FormData_##table_name *)0)->field))
Another method for macros was to depend on sizeof() at compile time to
adjust what was built.
+#define _CAT_CTX_SET(ctx, attnum, value) \
+ ((ctx)->values[(attnum)] = (value), \
+ (ctx)->nulls[(attnum)] = false, \
+ (ctx)->updated = bms_add_member((ctx)->updated, (attnum)))
+
+#define _CAT_FORM_SET(form, table_name, field, value) \
+ (form)[Anum_##table_name##_##field - 1] = (value)
+
+#define CatalogTupleSet_turnary(ctx_or_form, table_name, field, value) \
+ (sizeof(*(ctx_or_form)) == sizeof(CatalogTupleContext) \
+ ? (_CAT_CTX_SET((CatalogTupleContext *)(ctx_or_form), \
+ Anum_##table_name##_##field - 1, value), \
+ (void)0) /* force statement context */ \
+ : (_CAT_FORM_SET(((Anum_##table_name *)(ctx_or_form)), table_name,
field, value), \
+ (void)0))
This feels wrong as who knows if today or someday the size of a form
just happens to be the same as the CatalogTupleContext? So I put that aside.
I looked into some wild ideas that included tuple arity to encode the
action type as Thomas mentioned would be innovative and cool something like:
HeapTupleSet((pg_type, values, nulls),
(typname, NameGetDatum(&name)),
(typnamespace, ObjectIdGetDatum(typeNamespace)),
(typowner, ObjectIdGetDatum(ownerId)),
(typlen, Int16GetDatum(sizeof(int32),
(typdefaultbi), /* list of 1 means null! */
(typdefault),
(some_attr, FooGetDatum(...), foo > bar), /* list of 3 =
conditional null! */
...);
But a) I couldn't ever get that to work as I'd hoped it would and b)
inventing a DSL in the C pre-processor isn't a goal of mine.
Everything needs you to pass in "values, nulls, updated"!
=====================================================================
I thought about this a bit too, the only way to avoid this was to own
the declaration as well as the manipulation of these things. I don't
want to change the entirety of the way we manipulate catalog tuples for
insert/update, I just wanted to capture what attributes changed on
update so I could use that later to avoid HeapDetermineColumnsInfo().
But, I've taken a swing at it and here's where I've landed:
Old "Form/GETSTRUCT" model:
Form_pg_index form = (Form_pg_index) GETSTRUCT(tuple);
form->inisclustered = false;
CatalogTupleUpdate(relation, &tuple->t_self, tuple);
New:
CatalogUpdateFormContext(pg_index, ctx);
CatalogSetForm(pg_index, ctx, tuple);
CatalogTupleUpdateField(ctx, pg_index, indisclustered, false);
ModifyCatalogTupleField(relation, tuple, ctx);
Old "values/nulls/replaces" model:
bool nulls[Natts_pg_type];
bool replaces[Natts_pg_type];
Datum values[Natts_pg_type];
values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType);
nulls[Anum_pg_type_typdefaultbin - 1] = true;
replaces[Anum_pg_type_oid - 1] = false;
tup = heap_modify_tuple(tuple, desc, values, nulls, replaces);
CatalogTupleUpdate(relation, &tuple->t_self, tuple);
New:
CatalogUpdateValuesContext(pg_type, ctx);
CatalogTupleUpdateValue(ctx, pg_type, typtype, CharGetDatum(typeType));
ModifyCatalogTupleValues(relation, tuple, ctx);
I'm about a third of the way done converting to this new pattern and
it's better. As I said earlier I'm concerned that after a lot of effort
the pattern would need to change again, so I'd rather shake out those
concerns/ideas now early on. You can see the changes in [1]https://github.com/gburd/postgres/pull/18, take a
look at htup.h, aclchk.c, pg_aggregate.c, and a few other places.
Now there are macros for: 1) declaration, 2) setting/mutating, 3)
modifying/inserting. I guess I was starting to feel like I was digging
a hole no one would appreciate or agree was necessary so I'm asking for
early feedback because rule #1 when you find yourself digging a hole is
to stop digging.
best.
-greg
[1]: https://github.com/gburd/postgres/pull/18
[2]: /messages/by-id/7BD1ABDB-B03A-464A-9BA9-A73B55AD8A1F@getmailspring.com
On Tue, Dec 02, 2025 at 10:21:36AM -0500, Greg Burd wrote:
On Dec 2 2025, at 2:09 am, Michael Paquier <michael@paquier.xyz> wrote:
Thanks for taking the time to review this chunky patch. I've been
quietly reworking it a bit, I'll go over that in a bit because I'd
appreciate opinions before I'm too far into the changes.
Noted.
I started off just trying to make
HeapDetermineColumnsInfo() go away, these seem like good goals as well
and touch the same area of code.
This one is an interesting piece of argument.
indexing.c: has the change to CatalogTupleUpdate/Insert and removal of
their "WithInfo" companions. If that second part is controversial then
I don't mind reverting it, but IMO this is cleaner and might either
inspire more call sites to create and reuse CatalogIndexState or for
someone (me?) to address the comment that pre-dates my work:I'm OK with the simplification on this one, but let's make that a
separate patch extracted from 0001. The changes with
CatalogTupleUpdate() and CatalogTupleInsert() don't have to be
included with the changes that introduce a bitmap integration to track
the attributes that are updated. This is pointing to the fact that
there are not that many callers of the WithInfo() flavors in the tree,
compared to the non-info ones (24 AFAIK, vs 160-ish for the Insert
path it seems, for example).That makes sense, but another approach is to do the work mentioned in
the comment and somehow cache the CatalogIndexState (which is a somewhat
redacted ResultRelInfo by another name) somewhere.
Yes, perhaps we should just do that. That may simplify some of the
existing catalog paths, where we decide to open directly the indexes,
as you have already noticed while working on 0002.
As I hinted at earlier on, I've continue to develop this patch [1].
It's not ready to post as patches just yet. I've paused making all the
changes as the time required is non-trivial. Here's some of what I
thought through and a taste so that I can (hopefully) get feedback (pos
or neg) before investing the rest of a week into updating every case.
Okay, noted.
+#define CatalogUpdateContext(table_name, var, tuple) \ + do { \ + struct { \ + bool nulls[Natts_##table_name]; \ + Datum values[Natts_##table_name]; \ + Bitmapset updated; \ + bitmapword bits[BITMAPSET_SIZE(Natts_##table_name)]; \ + } _##table_name##_##var##_ = {.nulls = {false}, .values = {0}, \ + .updated.nwords = BITMAPSET_SIZE(Natts_##table_name), \ + .updated.type = T_Bitmapset, .bits = {0} }; \ + CatalogTupleContext *(var##_ctx) = \ + (CatalogTupleContext *)&_##table_name##_##var##_; \ + Form_##table_name (var##_form) = \ + (Form_##table_name) GETSTRUCT(tuple); \ + } while(0)Which would create the right size statically allocated Bitmapset, but it
wouldn't be "valid" because the last word in the set is all zeros and so
calling into any function that calls bms_is_valid() would assert. I
could simply embed the logic for bms_add_member() etc into the macros,
but then I'd be creating a mess for the future. The only advantage is
that you'd be avoiding a palloc()/free() possibly a realloc(). There's
something to be said for that, but this felt a bit over the line.
Hmm. That feels like too much magic to me. We don't have such
complex macros in the tree, currently. And do we really need to
sacrifice readability over some extra palloc()/free() in what are
non-hot code paths?
In the end, after trying a few things (including pre-sizing the
Bitmapset by creating it as a singleton setting the Natts+1 value at
initialization to avoid realloc) I went back to accepting the
palloc/free model as simple enough.
Yeah, I'd agree that this is better.
+#define CatalogTupleSet_turnary(ctx_or_form, table_name, field, value) \ + (sizeof(*(ctx_or_form)) == sizeof(CatalogTupleContext) \ + ? (_CAT_CTX_SET((CatalogTupleContext *)(ctx_or_form), \ + Anum_##table_name##_##field - 1, value), \ + (void)0) /* force statement context */ \ + : (_CAT_FORM_SET(((Anum_##table_name *)(ctx_or_form)), table_name, field, value), \ + (void)0))This feels wrong as who knows if today or someday the size of a form
just happens to be the same as the CatalogTupleContext? So I put that aside.
I wouldn't do that either, yes.
New:
CatalogUpdateValuesContext(pg_type, ctx);CatalogTupleUpdateValue(ctx, pg_type, typtype, CharGetDatum(typeType));
ModifyCatalogTupleValues(relation, tuple, ctx);I'm about a third of the way done converting to this new pattern and
it's better. As I said earlier I'm concerned that after a lot of effort
the pattern would need to change again, so I'd rather shake out those
concerns/ideas now early on. You can see the changes in [1], take a
look at htup.h, aclchk.c, pg_aggregate.c, and a few other places.
One thing not mentioned here is CatalogUpdateValuesDecl(), macro that
hides the bitmap with the updated values, so you'd need one to ensure
that the rest works. Perhaps all that should not be in htup.h. We
may want to header reordering to show that there is a split with heap
tuples, also one of your goals.
Now there are macros for: 1) declaration, 2) setting/mutating, 3)
modifying/inserting. I guess I was starting to feel like I was digging
a hole no one would appreciate or agree was necessary so I'm asking for
early feedback because rule #1 when you find yourself digging a hole is
to stop digging.
I'm not completely sure about this one. Some of the directions and
decisions that need to be taken here also depend on your other work
posted at [1]/messages/by-id/78574B24-BE0A-42C5-8075-3FA9FA63B8FC@amazon.com -- Michael. Looking at v23 from this other thread, the code paths
touched there are different from what's touched here (heaptuple.c vs
heapam.c). You have mentioned that both share some ground. Is there
a specific part in the patch of the other thread I should look at to
get an idea of the bigger picture you have in mind?
[1]: /messages/by-id/78574B24-BE0A-42C5-8075-3FA9FA63B8FC@amazon.com -- Michael
--
Michael
On Dec 2 2025, at 11:16 pm, Michael Paquier <michael@paquier.xyz> wrote:
On Tue, Dec 02, 2025 at 10:21:36AM -0500, Greg Burd wrote:
On Dec 2 2025, at 2:09 am, Michael Paquier <michael@paquier.xyz> wrote:
Thanks for taking the time to review this chunky patch. I've been
quietly reworking it a bit, I'll go over that in a bit because I'd
appreciate opinions before I'm too far into the changes.
Michael,
Thanks for continuing to help me along with this patch, I appreciate
your attention and time.
Noted.
I started off just trying to make
HeapDetermineColumnsInfo() go away, these seem like good goals as well
and touch the same area of code.This one is an interesting piece of argument.
I've looked in the email archives a bit and didn't come up with much
related to catalog upgrades. I don't know if there is much on the
record information on this idea, but from what I've been told the idea
of decoupling heap from catalogs with the goal of getting closer to
making online upgrades possible has been referenced a few times in
hallway tracks at various conferences.
indexing.c: has the change to CatalogTupleUpdate/Insert and removal of
their "WithInfo" companions. If that second part is controversial then
I don't mind reverting it, but IMO this is cleaner and might either
inspire more call sites to create and reuse CatalogIndexState or for
someone (me?) to address the comment that pre-dates my work:I'm OK with the simplification on this one, but let's make that a
separate patch extracted from 0001. The changes with
CatalogTupleUpdate() and CatalogTupleInsert() don't have to be
included with the changes that introduce a bitmap integration to track
the attributes that are updated. This is pointing to the fact that
there are not that many callers of the WithInfo() flavors in the tree,
compared to the non-info ones (24 AFAIK, vs 160-ish for the Insert
path it seems, for example).That makes sense, but another approach is to do the work mentioned in
the comment and somehow cache the CatalogIndexState (which is a somewhat
redacted ResultRelInfo by another name) somewhere.Yes, perhaps we should just do that. That may simplify some of the
existing catalog paths, where we decide to open directly the indexes,
as you have already noticed while working on 0002.
I'll see what I can do to extract this piece into a separate patch.
New:
CatalogUpdateValuesContext(pg_type, ctx);CatalogTupleUpdateValue(ctx, pg_type, typtype, CharGetDatum(typeType));
ModifyCatalogTupleValues(relation, tuple, ctx);I'm about a third of the way done converting to this new pattern and
it's better. As I said earlier I'm concerned that after a lot of effort
the pattern would need to change again, so I'd rather shake out those
concerns/ideas now early on. You can see the changes in [1], take a
look at htup.h, aclchk.c, pg_aggregate.c, and a few other places.One thing not mentioned here is CatalogUpdateValuesDecl(), macro that
hides the bitmap with the updated values, so you'd need one to ensure
that the rest works. Perhaps all that should not be in htup.h. We
may want to header reordering to show that there is a split with heap
tuples, also one of your goals.
Yes, my current thinking for htup.h is here [1]https://github.com/gburd/postgres/blob/cf-6221/src/include/access/htup.h#L90-L277 L90-L277 in a GitHub
branch on my fork of the Postgres repo.
Places I've converted so as to see the new pattern:
* aclchk.c [2]https://github.com/gburd/postgres/blob/cf-6221/src/backend/catalog/aclchk.c#L1319-L1341 shows a insert or modify case
* heap.c [3]https://github.com/gburd/postgres/blob/cf-6221/src/backend/catalog/heap.c#L1686C2-L1746 modify a catalog tuple
* attribute_stats.c [4]https://github.com/gburd/postgres/blob/cf-6221/src/backend/statistics/attribute_stats.c#L750-L806 a bit more tricky use case
There are more.
Now there are macros for: 1) declaration, 2) setting/mutating, 3)
modifying/inserting. I guess I was starting to feel like I was digging
a hole no one would appreciate or agree was necessary so I'm asking for
early feedback because rule #1 when you find yourself digging a hole is
to stop digging.I'm not completely sure about this one. Some of the directions and
decisions that need to be taken here also depend on your other work
posted at [1]. Looking at v23 from this other thread, the code paths
touched there are different from what's touched here (heaptuple.c vs
heapam.c). You have mentioned that both share some ground. Is there
a specific part in the patch of the other thread I should look at to
get an idea of the bigger picture you have in mind?
Yes, the links referenced above on that branch. I'll post an
updated/rebased patch set here again for reference, but understand it's
only partially done, as a way to capture the idea (and not depend on
links into GitHub).
[1]: /messages/by-id/78574B24-BE0A-42C5-8075-3FA9FA63B8FC@amazon.com
Right, within that thread there is this message [5]/messages/by-id/BCF1BF66-7A1B-4E01-87DC-0BE45EDF2F98@greg.burd.me that notes:
Ideally, my patch to restructure how catalog tuples are updated [<this
thread>] is committed and we can fully remove
HeapDetermineColumnsInfo() and likely speed up all catalog updates in
the process. That's what motivated [<this thread>], please take a
look, it required a huge number of changes so I thought it deserved a
life/thread of its own.
There are two major paths into heap_update(), one from
heapam_tuple_update() and one from simple_heap_update(). The first is
from the executor side via the table AM API and my other thread [6]/messages/by-id/78574B24-BE0A-42C5-8075-3FA9FA63B8FC@amazon.com that
you referenced is trying to address that. This thread is focused on the
catalog updates that flow into simple_heap_update(). Really that
function should be renamed to catalog_heap_update() as that's the only
purpose AFAICT.
Does that connect the dots a bit more clearly?
--
Michael
Included in the attached patch set is that first patch from the other
thread as the 0003 patch here and shows the ultimate goal, but it is a work-in-progress.
This patch set removes the need to call HeapDetermineColumnsInfo() on
the simple_heap_update() path because the Bitmapset of modified columns
is passed in and intersected against the indexed attributes
accomplishing the same outcome.
I haven't yet split out the "WithInfo" functions or worked out how to
cache the CatalogIndexState. I thought I'd finalize the approach, then
work that out as it might be impacted by refinements to proposed approach.
* 0001 Reorganize heap update logic and update simple_heap_update()
Focus on the macros in htup.h and the changes to the files that use
these macros in this commit, my ask of reviewers is that we agree on the
pattern established in this commit before I fully implement it across
all files in the 0002 patch.
* 0002 Update the remainder of catalog updates using the new APIs
Most files in this patch are still using the first version of the
macros. Only aclchk.c, heap.c, and index.c have been converted to show
how this approach plays out.
* 0003 Refactor how we form HeapTuples for CatalogTuple(Insert|Update)
This commit is borrowed from the other thread to demonstrate how these
changes impact heap updates. Thanks for your consideration, I
appreciate your time.
best.
-greg
[1]: https://github.com/gburd/postgres/blob/cf-6221/src/include/access/htup.h#L90-L277
[2]: https://github.com/gburd/postgres/blob/cf-6221/src/backend/catalog/aclchk.c#L1319-L1341
[3]: https://github.com/gburd/postgres/blob/cf-6221/src/backend/catalog/heap.c#L1686C2-L1746
[4]: https://github.com/gburd/postgres/blob/cf-6221/src/backend/statistics/attribute_stats.c#L750-L806
[5]: /messages/by-id/BCF1BF66-7A1B-4E01-87DC-0BE45EDF2F98@greg.burd.me
[6]: /messages/by-id/78574B24-BE0A-42C5-8075-3FA9FA63B8FC@amazon.com
Attachments:
v2-0003-Reorganize-heap-update-logic-and-update-simple_he.patchapplication/octet-streamDownload
From f4ff3b48ac46794d8e044b41de79db641c7e2f83 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
Date: Sun, 2 Nov 2025 11:36:20 -0500
Subject: [PATCH v2 3/3] Reorganize heap update logic and update
simple_heap_update()
This commit refactors the interaction between heap_tuple_update(),
heap_update(), and simple_heap_update() to improve code organization and
flexibility. The changes are functionally equivalent to the previous
implementation except that now updates to catalog tuples no longer
invoke HeapDetermineColumnsInfo() to determine which indexed attributes changed.
The set of modified attributes is now passed into simple_heap_update()
which then intersects that with the indexed attributes. The remaining
logic from HeapDetermineColumnsInfo() related to replica identity still
exists in simple_heap_update().
As part of this reorganization, the handling of replica identity key
attributes has been adjusted. Instead of fetching a second copy of
the bitmap during an update operation, the caller is now required to
provide it. This change applies to both heap_update() and
heap_delete().
---
src/backend/access/heap/heapam.c | 566 +++++++++++------------
src/backend/access/heap/heapam_handler.c | 117 ++++-
src/backend/catalog/indexing.c | 2 +-
src/include/access/heapam.h | 27 +-
4 files changed, 410 insertions(+), 302 deletions(-)
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4d382a04338..e2ec62f528d 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -39,18 +39,24 @@
#include "access/syncscan.h"
#include "access/valid.h"
#include "access/visibilitymap.h"
+#include "access/xact.h"
#include "access/xloginsert.h"
+#include "catalog/catalog.h"
#include "catalog/pg_database.h"
#include "catalog/pg_database_d.h"
#include "commands/vacuum.h"
+#include "nodes/bitmapset.h"
#include "pgstat.h"
#include "port/pg_bitutils.h"
+#include "storage/bufmgr.h"
+#include "storage/itemptr.h"
#include "storage/lmgr.h"
#include "storage/predicate.h"
#include "storage/procarray.h"
#include "utils/datum.h"
#include "utils/injection_point.h"
#include "utils/inval.h"
+#include "utils/relcache.h"
#include "utils/spccache.h"
#include "utils/syscache.h"
@@ -62,16 +68,8 @@ static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf,
HeapTuple newtup, HeapTuple old_key_tuple,
bool all_visible_cleared, bool new_all_visible_cleared);
#ifdef USE_ASSERT_CHECKING
-static void check_lock_if_inplace_updateable_rel(Relation relation,
- const ItemPointerData *otid,
- HeapTuple newtup);
static void check_inplace_rel_lock(HeapTuple oldtup);
#endif
-static Bitmapset *HeapDetermineColumnsInfo(Relation relation,
- Bitmapset *interesting_cols,
- Bitmapset *external_cols,
- HeapTuple oldtup, HeapTuple newtup,
- bool *has_external);
static bool heap_acquire_tuplock(Relation relation, const ItemPointerData *tid,
LockTupleMode mode, LockWaitPolicy wait_policy,
bool *have_tuple_lock);
@@ -103,10 +101,10 @@ static bool ConditionalMultiXactIdWait(MultiXactId multi, MultiXactStatus status
static void index_delete_sort(TM_IndexDeleteOp *delstate);
static int bottomup_sort_and_shrink(TM_IndexDeleteOp *delstate);
static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
-static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
+static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp,
+ Bitmapset *rid_attrs, bool key_required,
bool *copy);
-
/*
* Each tuple lock mode has a corresponding heavyweight lock, and one or two
* corresponding MultiXactStatuses (one to merely lock tuples, another one to
@@ -2814,6 +2812,7 @@ heap_delete(Relation relation, const ItemPointerData *tid,
Buffer buffer;
Buffer vmbuffer = InvalidBuffer;
TransactionId new_xmax;
+ Bitmapset *rid_attrs;
uint16 new_infomask,
new_infomask2;
bool have_tuple_lock = false;
@@ -2826,6 +2825,8 @@ heap_delete(Relation relation, const ItemPointerData *tid,
AssertHasSnapshotForToast(relation);
+ rid_attrs = RelationGetIndexAttrBitmap(relation, INDEX_ATTR_BITMAP_IDENTITY_KEY);
+
/*
* Forbid this during a parallel operation, lest it allocate a combo CID.
* Other workers might need that combo CID for visibility checks, and we
@@ -3029,6 +3030,7 @@ l1:
UnlockTupleTuplock(relation, &(tp.t_self), LockTupleExclusive);
if (vmbuffer != InvalidBuffer)
ReleaseBuffer(vmbuffer);
+ bms_free(rid_attrs);
return result;
}
@@ -3050,7 +3052,10 @@ l1:
* Compute replica identity tuple before entering the critical section so
* we don't PANIC upon a memory allocation failure.
*/
- old_key_tuple = ExtractReplicaIdentity(relation, &tp, true, &old_key_copied);
+ old_key_tuple = ExtractReplicaIdentity(relation, &tp, rid_attrs,
+ true, &old_key_copied);
+ bms_free(rid_attrs);
+ rid_attrs = NULL;
/*
* If this is the first possibly-multixact-able operation in the current
@@ -3262,7 +3267,10 @@ simple_heap_delete(Relation relation, const ItemPointerData *tid)
* heap_update - replace a tuple
*
* See table_tuple_update() for an explanation of the parameters, except that
- * this routine directly takes a tuple rather than a slot.
+ * this routine directly takes a heap tuple rather than a slot.
+ *
+ * It's required that the caller has acquired the pin and lock on the buffer.
+ * That lock and pin will be managed here, not in the caller.
*
* In the failure cases, the routine fills *tmfd with the tuple's t_ctid,
* t_xmax (resolving a possible MultiXact, if necessary), and t_cmax (the last
@@ -3270,30 +3278,21 @@ simple_heap_delete(Relation relation, const ItemPointerData *tid)
* generated by another transaction).
*/
TM_Result
-heap_update(Relation relation, const ItemPointerData *otid, HeapTuple newtup,
- CommandId cid, Snapshot crosscheck, bool wait,
- TM_FailureData *tmfd, LockTupleMode *lockmode,
- TU_UpdateIndexes *update_indexes)
+heap_update(Relation relation, HeapTupleData *oldtup,
+ HeapTuple newtup, CommandId cid, Snapshot crosscheck, bool wait,
+ TM_FailureData *tmfd, LockTupleMode *lockmode, Buffer buffer,
+ Page page, BlockNumber block, ItemId lp, Bitmapset *hot_attrs,
+ Bitmapset *sum_attrs, Bitmapset *pk_attrs, Bitmapset *rid_attrs,
+ Bitmapset *mix_attrs, Buffer *vmbuffer,
+ bool rep_id_key_required, TU_UpdateIndexes *update_indexes)
{
TM_Result result;
TransactionId xid = GetCurrentTransactionId();
- Bitmapset *hot_attrs;
- Bitmapset *sum_attrs;
- Bitmapset *key_attrs;
- Bitmapset *id_attrs;
- Bitmapset *interesting_attrs;
- Bitmapset *modified_attrs;
- ItemId lp;
- HeapTupleData oldtup;
HeapTuple heaptup;
HeapTuple old_key_tuple = NULL;
bool old_key_copied = false;
- Page page;
- BlockNumber block;
MultiXactStatus mxact_status;
- Buffer buffer,
- newbuf,
- vmbuffer = InvalidBuffer,
+ Buffer newbuf,
vmbuffer_new = InvalidBuffer;
bool need_toast;
Size newtupsize,
@@ -3307,7 +3306,6 @@ heap_update(Relation relation, const ItemPointerData *otid, HeapTuple newtup,
bool all_visible_cleared_new = false;
bool checked_lockers;
bool locker_remains;
- bool id_has_external = false;
TransactionId xmax_new_tuple,
xmax_old_tuple;
uint16 infomask_old_tuple,
@@ -3315,144 +3313,13 @@ heap_update(Relation relation, const ItemPointerData *otid, HeapTuple newtup,
infomask_new_tuple,
infomask2_new_tuple;
- Assert(ItemPointerIsValid(otid));
-
- /* Cheap, simplistic check that the tuple matches the rel's rowtype. */
- Assert(HeapTupleHeaderGetNatts(newtup->t_data) <=
- RelationGetNumberOfAttributes(relation));
-
+ Assert(BufferIsLockedByMe(buffer));
+ Assert(ItemIdIsNormal(lp));
AssertHasSnapshotForToast(relation);
- /*
- * Forbid this during a parallel operation, lest it allocate a combo CID.
- * Other workers might need that combo CID for visibility checks, and we
- * have no provision for broadcasting it to them.
- */
- if (IsInParallelMode())
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
- errmsg("cannot update tuples during a parallel operation")));
-
-#ifdef USE_ASSERT_CHECKING
- check_lock_if_inplace_updateable_rel(relation, otid, newtup);
-#endif
-
- /*
- * Fetch the list of attributes to be checked for various operations.
- *
- * For HOT considerations, this is wasted effort if we fail to update or
- * have to put the new tuple on a different page. But we must compute the
- * list before obtaining buffer lock --- in the worst case, if we are
- * doing an update on one of the relevant system catalogs, we could
- * deadlock if we try to fetch the list later. In any case, the relcache
- * caches the data so this is usually pretty cheap.
- *
- * We also need columns used by the replica identity and columns that are
- * considered the "key" of rows in the table.
- *
- * Note that we get copies of each bitmap, so we need not worry about
- * relcache flush happening midway through.
- */
- hot_attrs = RelationGetIndexAttrBitmap(relation,
- INDEX_ATTR_BITMAP_HOT_BLOCKING);
- sum_attrs = RelationGetIndexAttrBitmap(relation,
- INDEX_ATTR_BITMAP_SUMMARIZED);
- key_attrs = RelationGetIndexAttrBitmap(relation, INDEX_ATTR_BITMAP_KEY);
- id_attrs = RelationGetIndexAttrBitmap(relation,
- INDEX_ATTR_BITMAP_IDENTITY_KEY);
- interesting_attrs = NULL;
- interesting_attrs = bms_add_members(interesting_attrs, hot_attrs);
- interesting_attrs = bms_add_members(interesting_attrs, sum_attrs);
- interesting_attrs = bms_add_members(interesting_attrs, key_attrs);
- interesting_attrs = bms_add_members(interesting_attrs, id_attrs);
-
- block = ItemPointerGetBlockNumber(otid);
- INJECTION_POINT("heap_update-before-pin", NULL);
- buffer = ReadBuffer(relation, block);
- page = BufferGetPage(buffer);
-
- /*
- * Before locking the buffer, pin the visibility map page if it appears to
- * be necessary. Since we haven't got the lock yet, someone else might be
- * in the middle of changing this, so we'll need to recheck after we have
- * the lock.
- */
- if (PageIsAllVisible(page))
- visibilitymap_pin(relation, block, &vmbuffer);
-
- LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
-
- lp = PageGetItemId(page, ItemPointerGetOffsetNumber(otid));
-
- /*
- * Usually, a buffer pin and/or snapshot blocks pruning of otid, ensuring
- * we see LP_NORMAL here. When the otid origin is a syscache, we may have
- * neither a pin nor a snapshot. Hence, we may see other LP_ states, each
- * of which indicates concurrent pruning.
- *
- * Failing with TM_Updated would be most accurate. However, unlike other
- * TM_Updated scenarios, we don't know the successor ctid in LP_UNUSED and
- * LP_DEAD cases. While the distinction between TM_Updated and TM_Deleted
- * does matter to SQL statements UPDATE and MERGE, those SQL statements
- * hold a snapshot that ensures LP_NORMAL. Hence, the choice between
- * TM_Updated and TM_Deleted affects only the wording of error messages.
- * Settle on TM_Deleted, for two reasons. First, it avoids complicating
- * the specification of when tmfd->ctid is valid. Second, it creates
- * error log evidence that we took this branch.
- *
- * Since it's possible to see LP_UNUSED at otid, it's also possible to see
- * LP_NORMAL for a tuple that replaced LP_UNUSED. If it's a tuple for an
- * unrelated row, we'll fail with "duplicate key value violates unique".
- * XXX if otid is the live, newer version of the newtup row, we'll discard
- * changes originating in versions of this catalog row after the version
- * the caller got from syscache. See syscache-update-pruned.spec.
- */
- if (!ItemIdIsNormal(lp))
- {
- Assert(RelationSupportsSysCache(RelationGetRelid(relation)));
-
- UnlockReleaseBuffer(buffer);
- Assert(!have_tuple_lock);
- if (vmbuffer != InvalidBuffer)
- ReleaseBuffer(vmbuffer);
- tmfd->ctid = *otid;
- tmfd->xmax = InvalidTransactionId;
- tmfd->cmax = InvalidCommandId;
- *update_indexes = TU_None;
-
- bms_free(hot_attrs);
- bms_free(sum_attrs);
- bms_free(key_attrs);
- bms_free(id_attrs);
- /* modified_attrs not yet initialized */
- bms_free(interesting_attrs);
- return TM_Deleted;
- }
-
- /*
- * Fill in enough data in oldtup for HeapDetermineColumnsInfo to work
- * properly.
- */
- oldtup.t_tableOid = RelationGetRelid(relation);
- oldtup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
- oldtup.t_len = ItemIdGetLength(lp);
- oldtup.t_self = *otid;
-
- /* the new tuple is ready, except for this: */
+ /* The new tuple is ready, except for this */
newtup->t_tableOid = RelationGetRelid(relation);
- /*
- * Determine columns modified by the update. Additionally, identify
- * whether any of the unmodified replica identity key attributes in the
- * old tuple is externally stored or not. This is required because for
- * such attributes the flattened value won't be WAL logged as part of the
- * new tuple so we must include it as part of the old_key_tuple. See
- * ExtractReplicaIdentity.
- */
- modified_attrs = HeapDetermineColumnsInfo(relation, interesting_attrs,
- id_attrs, &oldtup,
- newtup, &id_has_external);
-
/*
* If we're not updating any "key" column, we can grab a weaker lock type.
* This allows for more concurrency when we are running simultaneously
@@ -3464,7 +3331,7 @@ heap_update(Relation relation, const ItemPointerData *otid, HeapTuple newtup,
* is updates that don't manipulate key columns, not those that
* serendipitously arrive at the same key values.
*/
- if (!bms_overlap(modified_attrs, key_attrs))
+ if (!bms_overlap(mix_attrs, pk_attrs))
{
*lockmode = LockTupleNoKeyExclusive;
mxact_status = MultiXactStatusNoKeyUpdate;
@@ -3488,17 +3355,10 @@ heap_update(Relation relation, const ItemPointerData *otid, HeapTuple newtup,
key_intact = false;
}
- /*
- * Note: beyond this point, use oldtup not otid to refer to old tuple.
- * otid may very well point at newtup->t_self, which we will overwrite
- * with the new tuple's location, so there's great risk of confusion if we
- * use otid anymore.
- */
-
l2:
checked_lockers = false;
locker_remains = false;
- result = HeapTupleSatisfiesUpdate(&oldtup, cid, buffer);
+ result = HeapTupleSatisfiesUpdate(oldtup, cid, buffer);
/* see below about the "no wait" case */
Assert(result != TM_BeingModified || wait);
@@ -3530,8 +3390,8 @@ l2:
*/
/* must copy state data before unlocking buffer */
- xwait = HeapTupleHeaderGetRawXmax(oldtup.t_data);
- infomask = oldtup.t_data->t_infomask;
+ xwait = HeapTupleHeaderGetRawXmax(oldtup->t_data);
+ infomask = oldtup->t_data->t_infomask;
/*
* Now we have to do something about the existing locker. If it's a
@@ -3571,13 +3431,12 @@ l2:
* requesting a lock and already have one; avoids deadlock).
*/
if (!current_is_member)
- heap_acquire_tuplock(relation, &(oldtup.t_self), *lockmode,
+ heap_acquire_tuplock(relation, &oldtup->t_self, *lockmode,
LockWaitBlock, &have_tuple_lock);
/* wait for multixact */
MultiXactIdWait((MultiXactId) xwait, mxact_status, infomask,
- relation, &oldtup.t_self, XLTW_Update,
- &remain);
+ relation, &oldtup->t_self, XLTW_Update, &remain);
checked_lockers = true;
locker_remains = remain != 0;
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
@@ -3587,9 +3446,9 @@ l2:
* could update this tuple before we get to this point. Check
* for xmax change, and start over if so.
*/
- if (xmax_infomask_changed(oldtup.t_data->t_infomask,
+ if (xmax_infomask_changed(oldtup->t_data->t_infomask,
infomask) ||
- !TransactionIdEquals(HeapTupleHeaderGetRawXmax(oldtup.t_data),
+ !TransactionIdEquals(HeapTupleHeaderGetRawXmax(oldtup->t_data),
xwait))
goto l2;
}
@@ -3614,8 +3473,8 @@ l2:
* before this one, which are important to keep in case this
* subxact aborts.
*/
- if (!HEAP_XMAX_IS_LOCKED_ONLY(oldtup.t_data->t_infomask))
- update_xact = HeapTupleGetUpdateXid(oldtup.t_data);
+ if (!HEAP_XMAX_IS_LOCKED_ONLY(oldtup->t_data->t_infomask))
+ update_xact = HeapTupleGetUpdateXid(oldtup->t_data);
else
update_xact = InvalidTransactionId;
@@ -3656,9 +3515,9 @@ l2:
* lock.
*/
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
- heap_acquire_tuplock(relation, &(oldtup.t_self), *lockmode,
+ heap_acquire_tuplock(relation, &oldtup->t_self, *lockmode,
LockWaitBlock, &have_tuple_lock);
- XactLockTableWait(xwait, relation, &oldtup.t_self,
+ XactLockTableWait(xwait, relation, &oldtup->t_self,
XLTW_Update);
checked_lockers = true;
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
@@ -3668,20 +3527,20 @@ l2:
* other xact could update this tuple before we get to this point.
* Check for xmax change, and start over if so.
*/
- if (xmax_infomask_changed(oldtup.t_data->t_infomask, infomask) ||
+ if (xmax_infomask_changed(oldtup->t_data->t_infomask, infomask) ||
!TransactionIdEquals(xwait,
- HeapTupleHeaderGetRawXmax(oldtup.t_data)))
+ HeapTupleHeaderGetRawXmax(oldtup->t_data)))
goto l2;
/* Otherwise check if it committed or aborted */
- UpdateXmaxHintBits(oldtup.t_data, buffer, xwait);
- if (oldtup.t_data->t_infomask & HEAP_XMAX_INVALID)
+ UpdateXmaxHintBits(oldtup->t_data, buffer, xwait);
+ if (oldtup->t_data->t_infomask & HEAP_XMAX_INVALID)
can_continue = true;
}
if (can_continue)
result = TM_Ok;
- else if (!ItemPointerEquals(&oldtup.t_self, &oldtup.t_data->t_ctid))
+ else if (!ItemPointerEquals(&oldtup->t_self, &oldtup->t_data->t_ctid))
result = TM_Updated;
else
result = TM_Deleted;
@@ -3694,39 +3553,33 @@ l2:
result == TM_Updated ||
result == TM_Deleted ||
result == TM_BeingModified);
- Assert(!(oldtup.t_data->t_infomask & HEAP_XMAX_INVALID));
+ Assert(!(oldtup->t_data->t_infomask & HEAP_XMAX_INVALID));
Assert(result != TM_Updated ||
- !ItemPointerEquals(&oldtup.t_self, &oldtup.t_data->t_ctid));
+ !ItemPointerEquals(&oldtup->t_self, &oldtup->t_data->t_ctid));
}
if (crosscheck != InvalidSnapshot && result == TM_Ok)
{
/* Perform additional check for transaction-snapshot mode RI updates */
- if (!HeapTupleSatisfiesVisibility(&oldtup, crosscheck, buffer))
+ if (!HeapTupleSatisfiesVisibility(oldtup, crosscheck, buffer))
result = TM_Updated;
}
if (result != TM_Ok)
{
- tmfd->ctid = oldtup.t_data->t_ctid;
- tmfd->xmax = HeapTupleHeaderGetUpdateXid(oldtup.t_data);
+ tmfd->ctid = oldtup->t_data->t_ctid;
+ tmfd->xmax = HeapTupleHeaderGetUpdateXid(oldtup->t_data);
if (result == TM_SelfModified)
- tmfd->cmax = HeapTupleHeaderGetCmax(oldtup.t_data);
+ tmfd->cmax = HeapTupleHeaderGetCmax(oldtup->t_data);
else
tmfd->cmax = InvalidCommandId;
UnlockReleaseBuffer(buffer);
if (have_tuple_lock)
- UnlockTupleTuplock(relation, &(oldtup.t_self), *lockmode);
- if (vmbuffer != InvalidBuffer)
- ReleaseBuffer(vmbuffer);
+ UnlockTupleTuplock(relation, &oldtup->t_self, *lockmode);
+ if (*vmbuffer != InvalidBuffer)
+ ReleaseBuffer(*vmbuffer);
*update_indexes = TU_None;
- bms_free(hot_attrs);
- bms_free(sum_attrs);
- bms_free(key_attrs);
- bms_free(id_attrs);
- bms_free(modified_attrs);
- bms_free(interesting_attrs);
return result;
}
@@ -3739,10 +3592,10 @@ l2:
* tuple has been locked or updated under us, but hopefully it won't
* happen very often.
*/
- if (vmbuffer == InvalidBuffer && PageIsAllVisible(page))
+ if (*vmbuffer == InvalidBuffer && PageIsAllVisible(page))
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
- visibilitymap_pin(relation, block, &vmbuffer);
+ visibilitymap_pin(relation, block, vmbuffer);
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
goto l2;
}
@@ -3753,9 +3606,9 @@ l2:
* If the tuple we're updating is locked, we need to preserve the locking
* info in the old tuple's Xmax. Prepare a new Xmax value for this.
*/
- compute_new_xmax_infomask(HeapTupleHeaderGetRawXmax(oldtup.t_data),
- oldtup.t_data->t_infomask,
- oldtup.t_data->t_infomask2,
+ compute_new_xmax_infomask(HeapTupleHeaderGetRawXmax(oldtup->t_data),
+ oldtup->t_data->t_infomask,
+ oldtup->t_data->t_infomask2,
xid, *lockmode, true,
&xmax_old_tuple, &infomask_old_tuple,
&infomask2_old_tuple);
@@ -3767,12 +3620,12 @@ l2:
* tuple. (In rare cases that might also be InvalidTransactionId and yet
* not have the HEAP_XMAX_INVALID bit set; that's fine.)
*/
- if ((oldtup.t_data->t_infomask & HEAP_XMAX_INVALID) ||
- HEAP_LOCKED_UPGRADED(oldtup.t_data->t_infomask) ||
+ if ((oldtup->t_data->t_infomask & HEAP_XMAX_INVALID) ||
+ HEAP_LOCKED_UPGRADED(oldtup->t_data->t_infomask) ||
(checked_lockers && !locker_remains))
xmax_new_tuple = InvalidTransactionId;
else
- xmax_new_tuple = HeapTupleHeaderGetRawXmax(oldtup.t_data);
+ xmax_new_tuple = HeapTupleHeaderGetRawXmax(oldtup->t_data);
if (!TransactionIdIsValid(xmax_new_tuple))
{
@@ -3787,7 +3640,7 @@ l2:
* Note that since we're doing an update, the only possibility is that
* the lockers had FOR KEY SHARE lock.
*/
- if (oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI)
+ if (oldtup->t_data->t_infomask & HEAP_XMAX_IS_MULTI)
{
GetMultiXactIdHintBits(xmax_new_tuple, &infomask_new_tuple,
&infomask2_new_tuple);
@@ -3815,7 +3668,7 @@ l2:
* Replace cid with a combo CID if necessary. Note that we already put
* the plain cid into the new tuple.
*/
- HeapTupleHeaderAdjustCmax(oldtup.t_data, &cid, &iscombo);
+ HeapTupleHeaderAdjustCmax(oldtup->t_data, &cid, &iscombo);
/*
* If the toaster needs to be activated, OR if the new tuple will not fit
@@ -3832,12 +3685,12 @@ l2:
relation->rd_rel->relkind != RELKIND_MATVIEW)
{
/* toast table entries should never be recursively toasted */
- Assert(!HeapTupleHasExternal(&oldtup));
+ Assert(!HeapTupleHasExternal(oldtup));
Assert(!HeapTupleHasExternal(newtup));
need_toast = false;
}
else
- need_toast = (HeapTupleHasExternal(&oldtup) ||
+ need_toast = (HeapTupleHasExternal(oldtup) ||
HeapTupleHasExternal(newtup) ||
newtup->t_len > TOAST_TUPLE_THRESHOLD);
@@ -3870,9 +3723,9 @@ l2:
* updating, because the potentially created multixact would otherwise
* be wrong.
*/
- compute_new_xmax_infomask(HeapTupleHeaderGetRawXmax(oldtup.t_data),
- oldtup.t_data->t_infomask,
- oldtup.t_data->t_infomask2,
+ compute_new_xmax_infomask(HeapTupleHeaderGetRawXmax(oldtup->t_data),
+ oldtup->t_data->t_infomask,
+ oldtup->t_data->t_infomask2,
xid, *lockmode, false,
&xmax_lock_old_tuple, &infomask_lock_old_tuple,
&infomask2_lock_old_tuple);
@@ -3882,18 +3735,18 @@ l2:
START_CRIT_SECTION();
/* Clear obsolete visibility flags ... */
- oldtup.t_data->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED);
- oldtup.t_data->t_infomask2 &= ~HEAP_KEYS_UPDATED;
- HeapTupleClearHotUpdated(&oldtup);
+ oldtup->t_data->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED);
+ oldtup->t_data->t_infomask2 &= ~HEAP_KEYS_UPDATED;
+ HeapTupleClearHotUpdated(oldtup);
/* ... and store info about transaction updating this tuple */
Assert(TransactionIdIsValid(xmax_lock_old_tuple));
- HeapTupleHeaderSetXmax(oldtup.t_data, xmax_lock_old_tuple);
- oldtup.t_data->t_infomask |= infomask_lock_old_tuple;
- oldtup.t_data->t_infomask2 |= infomask2_lock_old_tuple;
- HeapTupleHeaderSetCmax(oldtup.t_data, cid, iscombo);
+ HeapTupleHeaderSetXmax(oldtup->t_data, xmax_lock_old_tuple);
+ oldtup->t_data->t_infomask |= infomask_lock_old_tuple;
+ oldtup->t_data->t_infomask2 |= infomask2_lock_old_tuple;
+ HeapTupleHeaderSetCmax(oldtup->t_data, cid, iscombo);
/* temporarily make it look not-updated, but locked */
- oldtup.t_data->t_ctid = oldtup.t_self;
+ oldtup->t_data->t_ctid = oldtup->t_self;
/*
* Clear all-frozen bit on visibility map if needed. We could
@@ -3902,7 +3755,7 @@ l2:
* worthwhile.
*/
if (PageIsAllVisible(page) &&
- visibilitymap_clear(relation, block, vmbuffer,
+ visibilitymap_clear(relation, block, *vmbuffer,
VISIBILITYMAP_ALL_FROZEN))
cleared_all_frozen = true;
@@ -3916,10 +3769,10 @@ l2:
XLogBeginInsert();
XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
- xlrec.offnum = ItemPointerGetOffsetNumber(&oldtup.t_self);
+ xlrec.offnum = ItemPointerGetOffsetNumber(&oldtup->t_self);
xlrec.xmax = xmax_lock_old_tuple;
- xlrec.infobits_set = compute_infobits(oldtup.t_data->t_infomask,
- oldtup.t_data->t_infomask2);
+ xlrec.infobits_set = compute_infobits(oldtup->t_data->t_infomask,
+ oldtup->t_data->t_infomask2);
xlrec.flags =
cleared_all_frozen ? XLH_LOCK_ALL_FROZEN_CLEARED : 0;
XLogRegisterData(&xlrec, SizeOfHeapLock);
@@ -3941,7 +3794,7 @@ l2:
if (need_toast)
{
/* Note we always use WAL and FSM during updates */
- heaptup = heap_toast_insert_or_update(relation, newtup, &oldtup, 0);
+ heaptup = heap_toast_insert_or_update(relation, newtup, oldtup, 0);
newtupsize = MAXALIGN(heaptup->t_len);
}
else
@@ -3977,20 +3830,20 @@ l2:
/* It doesn't fit, must use RelationGetBufferForTuple. */
newbuf = RelationGetBufferForTuple(relation, heaptup->t_len,
buffer, 0, NULL,
- &vmbuffer_new, &vmbuffer,
+ &vmbuffer_new, vmbuffer,
0);
/* We're all done. */
break;
}
/* Acquire VM page pin if needed and we don't have it. */
- if (vmbuffer == InvalidBuffer && PageIsAllVisible(page))
- visibilitymap_pin(relation, block, &vmbuffer);
+ if (*vmbuffer == InvalidBuffer && PageIsAllVisible(page))
+ visibilitymap_pin(relation, block, vmbuffer);
/* Re-acquire the lock on the old tuple's page. */
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/* Re-check using the up-to-date free space */
pagefree = PageGetHeapFreeSpace(page);
if (newtupsize > pagefree ||
- (vmbuffer == InvalidBuffer && PageIsAllVisible(page)))
+ (*vmbuffer == InvalidBuffer && PageIsAllVisible(page)))
{
/*
* Rats, it doesn't fit anymore, or somebody just now set the
@@ -4028,7 +3881,7 @@ l2:
* will include checking the relation level, there is no benefit to a
* separate check for the new tuple.
*/
- CheckForSerializableConflictIn(relation, &oldtup.t_self,
+ CheckForSerializableConflictIn(relation, &oldtup->t_self,
BufferGetBlockNumber(buffer));
/*
@@ -4036,7 +3889,6 @@ l2:
* has enough space for the new tuple. If they are the same buffer, only
* one pin is held.
*/
-
if (newbuf == buffer)
{
/*
@@ -4044,7 +3896,7 @@ l2:
* to do a HOT update. Check if any of the index columns have been
* changed.
*/
- if (!bms_overlap(modified_attrs, hot_attrs))
+ if (!bms_overlap(mix_attrs, hot_attrs))
{
use_hot_update = true;
@@ -4055,7 +3907,7 @@ l2:
* indexes if the columns were updated, or we may fail to detect
* e.g. value bound changes in BRIN minmax indexes.
*/
- if (bms_overlap(modified_attrs, sum_attrs))
+ if (bms_overlap(mix_attrs, sum_attrs))
summarized_update = true;
}
}
@@ -4072,10 +3924,8 @@ l2:
* logged. Pass old key required as true only if the replica identity key
* columns are modified or it has external data.
*/
- old_key_tuple = ExtractReplicaIdentity(relation, &oldtup,
- bms_overlap(modified_attrs, id_attrs) ||
- id_has_external,
- &old_key_copied);
+ old_key_tuple = ExtractReplicaIdentity(relation, oldtup, rid_attrs,
+ rep_id_key_required, &old_key_copied);
/* NO EREPORT(ERROR) from here till changes are logged */
START_CRIT_SECTION();
@@ -4097,7 +3947,7 @@ l2:
if (use_hot_update)
{
/* Mark the old tuple as HOT-updated */
- HeapTupleSetHotUpdated(&oldtup);
+ HeapTupleSetHotUpdated(oldtup);
/* And mark the new tuple as heap-only */
HeapTupleSetHeapOnly(heaptup);
/* Mark the caller's copy too, in case different from heaptup */
@@ -4106,7 +3956,7 @@ l2:
else
{
/* Make sure tuples are correctly marked as not-HOT */
- HeapTupleClearHotUpdated(&oldtup);
+ HeapTupleClearHotUpdated(oldtup);
HeapTupleClearHeapOnly(heaptup);
HeapTupleClearHeapOnly(newtup);
}
@@ -4115,17 +3965,17 @@ l2:
/* Clear obsolete visibility flags, possibly set by ourselves above... */
- oldtup.t_data->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED);
- oldtup.t_data->t_infomask2 &= ~HEAP_KEYS_UPDATED;
+ oldtup->t_data->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED);
+ oldtup->t_data->t_infomask2 &= ~HEAP_KEYS_UPDATED;
/* ... and store info about transaction updating this tuple */
Assert(TransactionIdIsValid(xmax_old_tuple));
- HeapTupleHeaderSetXmax(oldtup.t_data, xmax_old_tuple);
- oldtup.t_data->t_infomask |= infomask_old_tuple;
- oldtup.t_data->t_infomask2 |= infomask2_old_tuple;
- HeapTupleHeaderSetCmax(oldtup.t_data, cid, iscombo);
+ HeapTupleHeaderSetXmax(oldtup->t_data, xmax_old_tuple);
+ oldtup->t_data->t_infomask |= infomask_old_tuple;
+ oldtup->t_data->t_infomask2 |= infomask2_old_tuple;
+ HeapTupleHeaderSetCmax(oldtup->t_data, cid, iscombo);
/* record address of new tuple in t_ctid of old one */
- oldtup.t_data->t_ctid = heaptup->t_self;
+ oldtup->t_data->t_ctid = heaptup->t_self;
/* clear PD_ALL_VISIBLE flags, reset all visibilitymap bits */
if (PageIsAllVisible(BufferGetPage(buffer)))
@@ -4133,7 +3983,7 @@ l2:
all_visible_cleared = true;
PageClearAllVisible(BufferGetPage(buffer));
visibilitymap_clear(relation, BufferGetBlockNumber(buffer),
- vmbuffer, VISIBILITYMAP_VALID_BITS);
+ *vmbuffer, VISIBILITYMAP_VALID_BITS);
}
if (newbuf != buffer && PageIsAllVisible(BufferGetPage(newbuf)))
{
@@ -4158,12 +4008,12 @@ l2:
*/
if (RelationIsAccessibleInLogicalDecoding(relation))
{
- log_heap_new_cid(relation, &oldtup);
+ log_heap_new_cid(relation, oldtup);
log_heap_new_cid(relation, heaptup);
}
recptr = log_heap_update(relation, buffer,
- newbuf, &oldtup, heaptup,
+ newbuf, oldtup, heaptup,
old_key_tuple,
all_visible_cleared,
all_visible_cleared_new);
@@ -4188,7 +4038,7 @@ l2:
* both tuple versions in one call to inval.c so we can avoid redundant
* sinval messages.)
*/
- CacheInvalidateHeapTuple(relation, &oldtup, heaptup);
+ CacheInvalidateHeapTuple(relation, oldtup, heaptup);
/* Now we can release the buffer(s) */
if (newbuf != buffer)
@@ -4196,14 +4046,14 @@ l2:
ReleaseBuffer(buffer);
if (BufferIsValid(vmbuffer_new))
ReleaseBuffer(vmbuffer_new);
- if (BufferIsValid(vmbuffer))
- ReleaseBuffer(vmbuffer);
+ if (BufferIsValid(*vmbuffer))
+ ReleaseBuffer(*vmbuffer);
/*
* Release the lmgr tuple lock, if we had it.
*/
if (have_tuple_lock)
- UnlockTupleTuplock(relation, &(oldtup.t_self), *lockmode);
+ UnlockTupleTuplock(relation, &oldtup->t_self, *lockmode);
pgstat_count_heap_update(relation, use_hot_update, newbuf != buffer);
@@ -4236,13 +4086,6 @@ l2:
if (old_key_tuple != NULL && old_key_copied)
heap_freetuple(old_key_tuple);
- bms_free(hot_attrs);
- bms_free(sum_attrs);
- bms_free(key_attrs);
- bms_free(id_attrs);
- bms_free(modified_attrs);
- bms_free(interesting_attrs);
-
return TM_Ok;
}
@@ -4251,7 +4094,7 @@ l2:
* Confirm adequate lock held during heap_update(), per rules from
* README.tuplock section "Locking to write inplace-updated tables".
*/
-static void
+void
check_lock_if_inplace_updateable_rel(Relation relation,
const ItemPointerData *otid,
HeapTuple newtup)
@@ -4423,7 +4266,7 @@ heap_attr_equals(TupleDesc tupdesc, int attrnum, Datum value1, Datum value2,
* listed as interesting) of the old tuple is a member of external_cols and is
* stored externally.
*/
-static Bitmapset *
+Bitmapset *
HeapDetermineColumnsInfo(Relation relation,
Bitmapset *interesting_cols,
Bitmapset *external_cols,
@@ -4506,25 +4349,171 @@ HeapDetermineColumnsInfo(Relation relation,
}
/*
- * simple_heap_update - replace a tuple
- *
- * This routine may be used to update a tuple when concurrent updates of
- * the target tuple are not expected (for example, because we have a lock
- * on the relation associated with the tuple). Any failure is reported
- * via ereport().
+ * This routine may be used to update a tuple when concurrent updates of the
+ * target tuple are not expected (for example, because we have a lock on the
+ * relation associated with the tuple). Any failure is reported via ereport().
*/
void
-simple_heap_update(Relation relation, const ItemPointerData *otid, HeapTuple tup,
- TU_UpdateIndexes *update_indexes)
+simple_heap_update(Relation relation, const ItemPointerData *otid, HeapTuple tuple,
+ const Bitmapset *updated, TU_UpdateIndexes *update_indexes)
{
TM_Result result;
TM_FailureData tmfd;
LockTupleMode lockmode;
+ Buffer buffer;
+ Buffer vmbuffer = InvalidBuffer;
+ Page page;
+ BlockNumber block;
+ Bitmapset *hot_attrs,
+ *sum_attrs,
+ *pk_attrs,
+ *rid_attrs,
+ *mix_attrs,
+ *idx_attrs;
+ ItemId lp;
+ HeapTupleData oldtup;
+ bool rep_id_key_required = false;
+
+ Assert(ItemPointerIsValid(otid));
+
+ /* Cheap, simplistic check that the tuple matches the rel's rowtype. */
+ Assert(HeapTupleHeaderGetNatts(tuple->t_data) <=
+ RelationGetNumberOfAttributes(relation));
+
+ /*
+ * Forbid this during a parallel operation, lest it allocate a combo CID.
+ * Other workers might need that combo CID for visibility checks, and we
+ * have no provision for broadcasting it to them.
+ */
+ if (IsInParallelMode())
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
+ errmsg("cannot update tuples during a parallel operation")));
+
+#ifdef USE_ASSERT_CHECKING
+ check_lock_if_inplace_updateable_rel(relation, otid, tuple);
+#endif
+
+ /*
+ * Fetch the list of attributes to be checked for various operations.
+ *
+ * For HOT considerations, this is wasted effort if we fail to update or
+ * have to put the new tuple on a different page. But we must compute the
+ * list before obtaining buffer lock --- in the worst case, if we are
+ * doing an update on one of the relevant system catalogs, we could
+ * deadlock if we try to fetch the list later. In any case, the relcache
+ * caches the data so this is usually pretty cheap.
+ *
+ * We also need columns used by the replica identity and columns that are
+ * considered the "key" of rows in the table.
+ *
+ * Note that we get copies of each bitmap, so we need not worry about
+ * relcache flush happening midway through.
+ */
+ hot_attrs = RelationGetIndexAttrBitmap(relation,
+ INDEX_ATTR_BITMAP_HOT_BLOCKING);
+ sum_attrs = RelationGetIndexAttrBitmap(relation,
+ INDEX_ATTR_BITMAP_SUMMARIZED);
+ pk_attrs = RelationGetIndexAttrBitmap(relation, INDEX_ATTR_BITMAP_KEY);
+ rid_attrs = RelationGetIndexAttrBitmap(relation,
+ INDEX_ATTR_BITMAP_IDENTITY_KEY);
+
+ idx_attrs = bms_copy(hot_attrs);
+ idx_attrs = bms_add_members(idx_attrs, sum_attrs);
+ idx_attrs = bms_add_members(idx_attrs, pk_attrs);
+ idx_attrs = bms_add_members(idx_attrs, rid_attrs);
+
+ block = ItemPointerGetBlockNumber(otid);
+ INJECTION_POINT("heap_update-before-pin", NULL);
+ buffer = ReadBuffer(relation, block);
+ page = BufferGetPage(buffer);
+
+ /*
+ * Before locking the buffer, pin the visibility map page if it appears to
+ * be necessary. Since we haven't got the lock yet, someone else might be
+ * in the middle of changing this, so we'll need to recheck after we have
+ * the lock.
+ */
+ if (PageIsAllVisible(page))
+ visibilitymap_pin(relation, block, &vmbuffer);
+
+ LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+
+ lp = PageGetItemId(page, ItemPointerGetOffsetNumber(otid));
+
+ /*
+ * Usually, a buffer pin and/or snapshot blocks pruning of otid, ensuring
+ * we see LP_NORMAL here. When the otid origin is a syscache, we may have
+ * neither a pin nor a snapshot. Hence, we may see other LP_ states, each
+ * of which indicates concurrent pruning.
+ *
+ * Failing with TM_Updated would be most accurate. However, unlike other
+ * TM_Updated scenarios, we don't know the successor ctid in LP_UNUSED and
+ * LP_DEAD cases. While the distinction between TM_Updated and TM_Deleted
+ * does matter to SQL statements UPDATE and MERGE, those SQL statements
+ * hold a snapshot that ensures LP_NORMAL. Hence, the choice between
+ * TM_Updated and TM_Deleted affects only the wording of error messages.
+ * Settle on TM_Deleted, for two reasons. First, it avoids complicating
+ * the specification of when tmfd->ctid is valid. Second, it creates
+ * error log evidence that we took this branch.
+ *
+ * Since it's possible to see LP_UNUSED at otid, it's also possible to see
+ * LP_NORMAL for a tuple that replaced LP_UNUSED. If it's a tuple for an
+ * unrelated row, we'll fail with "duplicate key value violates unique".
+ * XXX if otid is the live, newer version of the newtup row, we'll discard
+ * changes originating in versions of this catalog row after the version
+ * the caller got from syscache. See syscache-update-pruned.spec.
+ */
+ if (!ItemIdIsNormal(lp))
+ {
+ Assert(RelationSupportsSysCache(RelationGetRelid(relation)));
+
+ UnlockReleaseBuffer(buffer);
+ if (vmbuffer != InvalidBuffer)
+ ReleaseBuffer(vmbuffer);
+ *update_indexes = TU_None;
+
+ bms_free(hot_attrs);
+ bms_free(sum_attrs);
+ bms_free(pk_attrs);
+ bms_free(rid_attrs);
+ bms_free(idx_attrs);
+ /* mix_attrs not yet initialized */
+
+ elog(ERROR, "tuple concurrently deleted");
+
+ return;
+ }
+
+ /* Partially construct the oldtup to pass into heap_update() */
+ oldtup.t_tableOid = RelationGetRelid(relation);
+ oldtup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+ oldtup.t_len = ItemIdGetLength(lp);
+ oldtup.t_self = *otid;
+
+ /* We know what attributes were updated, which were indexed too? */
+ Assert(!bms_is_empty(updated));
+ mix_attrs = bms_intersect(updated, idx_attrs);
+
+ /*
+ * We'll need to WAL log the replica identity attributes if either they
+ * overlap with the modified indexed attributes or, as we've checked for
+ * just now in HeapDetermineColumnsInfo, they were unmodified external
+ * indexed attributes.
+ */
+ rep_id_key_required = rep_id_key_required || bms_overlap(mix_attrs, rid_attrs);
+
+ result = heap_update(relation, &oldtup, tuple, GetCurrentCommandId(true),
+ InvalidSnapshot, true /* wait for commit */ , &tmfd, &lockmode,
+ buffer, page, block, lp, hot_attrs, sum_attrs, pk_attrs,
+ rid_attrs, mix_attrs, &vmbuffer, rep_id_key_required,
+ update_indexes);
+
+ bms_free(hot_attrs);
+ bms_free(sum_attrs);
+ bms_free(pk_attrs);
+ bms_free(rid_attrs);
- result = heap_update(relation, otid, tup,
- GetCurrentCommandId(true), InvalidSnapshot,
- true /* wait for commit */ ,
- &tmfd, &lockmode, update_indexes);
switch (result)
{
case TM_SelfModified:
@@ -9164,12 +9153,11 @@ log_heap_new_cid(Relation relation, HeapTuple tup)
* the same tuple that was passed in.
*/
static HeapTuple
-ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
- bool *copy)
+ExtractReplicaIdentity(Relation relation, HeapTuple tp, Bitmapset *rid_attrs,
+ bool key_required, bool *copy)
{
TupleDesc desc = RelationGetDescr(relation);
char replident = relation->rd_rel->relreplident;
- Bitmapset *idattrs;
HeapTuple key_tuple;
bool nulls[MaxHeapAttributeNumber];
Datum values[MaxHeapAttributeNumber];
@@ -9200,17 +9188,13 @@ ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
if (!key_required)
return NULL;
- /* find out the replica identity columns */
- idattrs = RelationGetIndexAttrBitmap(relation,
- INDEX_ATTR_BITMAP_IDENTITY_KEY);
-
/*
* If there's no defined replica identity columns, treat as !key_required.
* (This case should not be reachable from heap_update, since that should
* calculate key_required accurately. But heap_delete just passes
* constant true for key_required, so we can hit this case in deletes.)
*/
- if (bms_is_empty(idattrs))
+ if (bms_is_empty(rid_attrs))
return NULL;
/*
@@ -9223,7 +9207,7 @@ ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
for (int i = 0; i < desc->natts; i++)
{
if (bms_is_member(i + 1 - FirstLowInvalidHeapAttributeNumber,
- idattrs))
+ rid_attrs))
Assert(!nulls[i]);
else
nulls[i] = true;
@@ -9232,8 +9216,6 @@ ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
key_tuple = heap_form_tuple(desc, values, nulls);
*copy = true;
- bms_free(idattrs);
-
/*
* If the tuple, which by here only contains indexed columns, still has
* toasted columns, force them to be inlined. This is somewhat unlikely
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index bcbac844bb6..1cf9a18775d 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -44,6 +44,7 @@
#include "storage/procarray.h"
#include "storage/smgr.h"
#include "utils/builtins.h"
+#include "utils/injection_point.h"
#include "utils/rel.h"
static void reform_and_rewrite_tuple(HeapTuple tuple,
@@ -312,23 +313,133 @@ heapam_tuple_delete(Relation relation, ItemPointer tid, CommandId cid,
return heap_delete(relation, tid, cid, crosscheck, wait, tmfd, changingPart);
}
-
static TM_Result
heapam_tuple_update(Relation relation, ItemPointer otid, TupleTableSlot *slot,
CommandId cid, Snapshot snapshot, Snapshot crosscheck,
bool wait, TM_FailureData *tmfd,
LockTupleMode *lockmode, TU_UpdateIndexes *update_indexes)
{
+ bool rep_id_key_required = false;
bool shouldFree = true;
HeapTuple tuple = ExecFetchSlotHeapTuple(slot, true, &shouldFree);
+ HeapTupleData oldtup;
+ Buffer buffer;
+ Buffer vmbuffer = InvalidBuffer;
+ Page page;
+ BlockNumber block;
+ ItemId lp;
+ Bitmapset *hot_attrs,
+ *sum_attrs,
+ *pk_attrs,
+ *rid_attrs,
+ *mix_attrs,
+ *idx_attrs;
TM_Result result;
+ Assert(ItemPointerIsValid(otid));
+
+ /* Cheap, simplistic check that the tuple matches the rel's rowtype. */
+ Assert(HeapTupleHeaderGetNatts(tuple->t_data) <=
+ RelationGetNumberOfAttributes(relation));
+
+ /*
+ * Forbid this during a parallel operation, lest it allocate a combo CID.
+ * Other workers might need that combo CID for visibility checks, and we
+ * have no provision for broadcasting it to them.
+ */
+ if (IsInParallelMode())
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
+ errmsg("cannot update tuples during a parallel operation")));
+
+#ifdef USE_ASSERT_CHECKING
+ check_lock_if_inplace_updateable_rel(relation, otid, tuple);
+#endif
+
+ /*
+ * Fetch the list of attributes to be checked for various operations.
+ *
+ * For HOT considerations, this is wasted effort if we fail to update or
+ * have to put the new tuple on a different page. But we must compute the
+ * list before obtaining buffer lock --- in the worst case, if we are
+ * doing an update on one of the relevant system catalogs, we could
+ * deadlock if we try to fetch the list later. In any case, the relcache
+ * caches the data so this is usually pretty cheap.
+ *
+ * We also need columns used by the replica identity and columns that are
+ * considered the "key" of rows in the table.
+ *
+ * Note that we get copies of each bitmap, so we need not worry about
+ * relcache flush happening midway through.
+ */
+ hot_attrs = RelationGetIndexAttrBitmap(relation,
+ INDEX_ATTR_BITMAP_HOT_BLOCKING);
+ sum_attrs = RelationGetIndexAttrBitmap(relation,
+ INDEX_ATTR_BITMAP_SUMMARIZED);
+ pk_attrs = RelationGetIndexAttrBitmap(relation, INDEX_ATTR_BITMAP_KEY);
+ rid_attrs = RelationGetIndexAttrBitmap(relation,
+ INDEX_ATTR_BITMAP_IDENTITY_KEY);
+
+ idx_attrs = bms_copy(hot_attrs);
+ idx_attrs = bms_add_members(idx_attrs, sum_attrs);
+ idx_attrs = bms_add_members(idx_attrs, pk_attrs);
+ idx_attrs = bms_add_members(idx_attrs, rid_attrs);
+
+ block = ItemPointerGetBlockNumber(otid);
+ INJECTION_POINT("heap_update-before-pin", NULL);
+ buffer = ReadBuffer(relation, block);
+ page = BufferGetPage(buffer);
+
+ /*
+ * Before locking the buffer, pin the visibility map page if it appears to
+ * be necessary. Since we haven't got the lock yet, someone else might be
+ * in the middle of changing this, so we'll need to recheck after we have
+ * the lock.
+ */
+ if (PageIsAllVisible(page))
+ visibilitymap_pin(relation, block, &vmbuffer);
+
+ LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+
+ lp = PageGetItemId(page, ItemPointerGetOffsetNumber(otid));
+
+ Assert(ItemIdIsNormal(lp));
+
+ /*
+ * Partially construct the oldtup for HeapDetermineColumnsInfo to work and
+ * then pass that on to heap_update.
+ */
+ oldtup.t_tableOid = RelationGetRelid(relation);
+ oldtup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+ oldtup.t_len = ItemIdGetLength(lp);
+ oldtup.t_self = *otid;
+
+ mix_attrs = HeapDetermineColumnsInfo(relation, idx_attrs, rid_attrs,
+ &oldtup, tuple, &rep_id_key_required);
+
+ /*
+ * We'll need to WAL log the replica identity attributes if either they
+ * overlap with the modified indexed attributes or, as we've checked for
+ * just now in HeapDetermineColumnsInfo, they were unmodified external
+ * indexed attributes.
+ */
+ rep_id_key_required = rep_id_key_required || bms_overlap(mix_attrs, rid_attrs);
+
/* Update the tuple with table oid */
slot->tts_tableOid = RelationGetRelid(relation);
tuple->t_tableOid = slot->tts_tableOid;
- result = heap_update(relation, otid, tuple, cid, crosscheck, wait,
- tmfd, lockmode, update_indexes);
+ result = heap_update(relation, &oldtup, tuple, cid, crosscheck, wait, tmfd, lockmode,
+ buffer, page, block, lp, hot_attrs, sum_attrs, pk_attrs,
+ rid_attrs, mix_attrs, &vmbuffer, rep_id_key_required, update_indexes);
+
+ bms_free(hot_attrs);
+ bms_free(sum_attrs);
+ bms_free(pk_attrs);
+ bms_free(rid_attrs);
+ bms_free(mix_attrs);
+ bms_free(idx_attrs);
+
ItemPointerCopy(&tuple->t_self, &slot->tts_tid);
/*
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 51efac85f65..4553158a21a 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -347,7 +347,7 @@ CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tupl
close_indexes = true;
}
- simple_heap_update(heapRel, otid, tuple, &updateIndexes);
+ simple_heap_update(heapRel, otid, tuple, updated, &updateIndexes);
CatalogIndexInsert(indstate, tuple, updateIndexes);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 632c4332a8c..3220821df69 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -364,11 +364,13 @@ extern TM_Result heap_delete(Relation relation, const ItemPointerData *tid,
TM_FailureData *tmfd, bool changingPart);
extern void heap_finish_speculative(Relation relation, const ItemPointerData *tid);
extern void heap_abort_speculative(Relation relation, const ItemPointerData *tid);
-extern TM_Result heap_update(Relation relation, const ItemPointerData *otid,
- HeapTuple newtup,
- CommandId cid, Snapshot crosscheck, bool wait,
- TM_FailureData *tmfd, LockTupleMode *lockmode,
- TU_UpdateIndexes *update_indexes);
+extern TM_Result heap_update(Relation relation, HeapTupleData *oldtup,
+ HeapTuple newtup, CommandId cid, Snapshot crosscheck, bool wait,
+ TM_FailureData *tmfd, LockTupleMode *lockmode, Buffer buffer,
+ Page page, BlockNumber block, ItemId lp, Bitmapset *hot_attrs,
+ Bitmapset *sum_attrs, Bitmapset *pk_attrs, Bitmapset *rid_attrs,
+ Bitmapset *mix_attrs, Buffer *vmbuffer,
+ bool rep_id_key_required, TU_UpdateIndexes *update_indexes);
extern TM_Result heap_lock_tuple(Relation relation, HeapTuple tuple,
CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy,
bool follow_updates,
@@ -403,7 +405,8 @@ extern bool heap_tuple_needs_eventual_freeze(HeapTupleHeader tuple);
extern void simple_heap_insert(Relation relation, HeapTuple tup);
extern void simple_heap_delete(Relation relation, const ItemPointerData *tid);
extern void simple_heap_update(Relation relation, const ItemPointerData *otid,
- HeapTuple tup, TU_UpdateIndexes *update_indexes);
+ HeapTuple tup, const Bitmapset *updated,
+ TU_UpdateIndexes *update_indexes);
extern TransactionId heap_index_delete_tuples(Relation rel,
TM_IndexDeleteOp *delstate);
@@ -430,6 +433,18 @@ extern void log_heap_prune_and_freeze(Relation relation, Buffer buffer,
OffsetNumber *dead, int ndead,
OffsetNumber *unused, int nunused);
+/* in heap/heapam.c */
+extern Bitmapset *HeapDetermineColumnsInfo(Relation relation,
+ Bitmapset *interesting_cols,
+ Bitmapset *external_cols,
+ HeapTuple oldtup, HeapTuple newtup,
+ bool *has_external);
+#ifdef USE_ASSERT_CHECKING
+extern void check_lock_if_inplace_updateable_rel(Relation relation,
+ const ItemPointerData *otid,
+ HeapTuple newtup);
+#endif
+
/* in heap/vacuumlazy.c */
extern void heap_vacuum_rel(Relation rel,
const VacuumParams params, BufferAccessStrategy bstrategy);
--
2.49.0
v2-0001-Refactor-how-we-form-HeapTuples-for-CatalogTuple-.patchapplication/octet-streamDownload
From 058f3422536dfffe027201a59366d830c4ab7675 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
Date: Fri, 14 Nov 2025 08:02:31 -0500
Subject: [PATCH v2 1/3] Refactor how we form HeapTuples for
CatalogTuple(Insert|Update)
NOTE: this is a work-in-progress, not commitable as it is. In htup.h
there are two sets of macros that change how we insert/update catalog
tuples. The newer, proposed version are toward the top of the file
while the older v1 macros follow a "TODO" comment. The idea was not to
convert the entirety until the pattern is acceptable so as to avoid
unnecessary work.
This commit provides a set of macros that should be used when inserting
or updating tuples. These macros help declare state necessary when
tracking updates and forming new tuples. There are macros used to set
fields to new values or to NULL. Finally there are macros for inserting
or updating these tuples.
There are a few reasons to standardize catalog modification code and
move it away from direct Form/GETSTRUCT or values/nulls/replaces-style
access. First, these models can be error prone and require attention to
a variety of details that can easily be overlooked. Second, at present
while we know what fields are modified we don't preserve that
information and pass it on to the heap_update() code. Third, at some
point we'll need in-memory representations completely decoupled from the
disk to support upgradeable catalogs.
Previous to this patch there were two methods for accomplishing this
task; Form/GETSTRUCT, and values/nulls/replaces. This new approach does
not change the fundamentals of this process but instead attempts to
cover up the details so as to make it a bit more intuitive and less
error-prone. These changes are, for the most part, backward compatible.
It is now possible to retain knowledge of the set of mutated attributes
when working with catalog tuples. A follow-on patch will change
simple_heap_update() to use the updated bitmaps gathered during catalog
tuple modification so as to avoid having to call
HeapDetermineColumnsInfo(). This prevents catlog updates from having to
re-discover the set of modified attributes by comparing old/new
HeapTuple Datums while holding a buffer lock when trying to identify
indexed attributes that have new values and should prevent HOT updates.
The "Form/GETSTRUCT" model allows for direct access to the tuple data
that is then modified, copied, and then updated via
ModifyCatalogTupleUpdate() which will write the modified catalog tuple
into the heap relation.
Old:
Form_pg_index form = (Form_pg_index) GETSTRUCT(tuple);
form->inisclustered = false;
CatalogTupleUpdate(relation, &tuple->t_self, tuple);
New:
CatalogUpdateFormContext(pg_index, ctx);
CatalogSetForm(pg_index, ctx, tuple);
CatalogTupleUpdateField(ctx, pg_index, indisclustered, false);
ModifyCatalogTupleForm(relation, tuple, ctx);
The "values/nulls/replaces" model collects the necessary information to
either update or create a heap tuple using heap_modify_tuple() or
heap_form_tuple() or sometimes heap_modify_tuple_by_cols(). While all
those functions remain unchanged and can be used it is simpler to use
the ModifyCatalogTupleValues() macro to write the changed heap tuple
into the catalog relation.
Old:
bool nulls[Natts_pg_type];
bool replaces[Natts_pg_type];
Datum values[Natts_pg_type];
values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType);
nulls[Anum_pg_type_typdefaultbin - 1] = true;
replaces[Anum_pg_type_oid - 1] = false;
tup = heap_modify_tuple(tuple, desc, values, nulls, replaces);
CatalogTupleUpdate(relation, &tuple->t_self, tuple);
New:
CatalogUpdateValuesContext(pg_type, ctx);
CatalogTupleUpdateValue(ctx, pg_type, typtype, CharGetDatum(typeType));
ModifyCatalogTupleValues(relation, tuple, ctx);
The heap_update_tuple() function is functionally equivalent to
heap_modify_tuple(), but takes a Bitmapset called "updated" rather than
an array of bool generally called "replaces" as a method for indicating
what was modified. Additionally, this new function tries to balance the
tradeoffs of calling heap_getattr() versus heap_deform_tuple() based
on the ratio of attributes updated and their known runtime complexities.
Both paths are functionally equivalent.
The changes also include initialization of the values/nulls arrays
rather than depending on loops or memset().
---
src/backend/access/common/heaptuple.c | 119 +++++++++++
src/backend/catalog/indexing.c | 137 +++++++------
src/backend/catalog/pg_aggregate.c | 74 +++----
src/backend/catalog/pg_constraint.c | 161 +++++++--------
src/backend/commands/alter.c | 55 +++--
src/backend/commands/analyze.c | 84 +++-----
src/backend/statistics/attribute_stats.c | 194 +++++++-----------
src/include/access/htup.h | 250 +++++++++++++++++++++++
src/include/access/htup_details.h | 8 +
src/include/catalog/indexing.h | 17 +-
10 files changed, 704 insertions(+), 395 deletions(-)
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 74a52d87067..364f03b043e 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -1325,6 +1325,125 @@ heap_modify_tuple_by_cols(HeapTuple tuple,
return newTuple;
}
+/*
+ * heap_update_tuple
+ * Form a new tuple from an old tuple and a set of replacement values.
+ *
+ * Creates a new HeapTuple by selectively replacing attributes from the original
+ * tuple with new values. The 'updated' Bitmapset specifies which attributes
+ * (by attribute number, 1-based adjusted by FirstLowInvalidHeapAttributeNumber)
+ * should be replaced with corresponding entries from new_values and new_isnull
+ * arrays (0-based indices).
+ *
+ * Performance strategy:
+ * - If updating many attributes (> 2*natts/3), use heap_getattr() to extract
+ * only the few non-updated attributes. This is O(k*n) where k is the number
+ * of non-updated attributes, which is small when updating many.
+ * - If updating few attributes (<= 2*natts/3), use heap_deform_tuple() to
+ * extract all attributes at once (O(n)), then replace the updated ones.
+ * This avoids the O(n^2) cost of many heap_getattr() calls.
+ *
+ * The threshold of 2*natts/3 balances the fixed O(n) cost of heap_deform_tuple
+ * against the variable O(k*n) cost of heap_getattr, where k = natts - num_updated.
+ */
+HeapTuple
+heap_update_tuple(HeapTuple tuple,
+ TupleDesc desc,
+ const Datum *new_values,
+ const bool *new_nulls,
+ const Bitmapset *updated)
+{
+ int natts = desc->natts;
+ int num_updated;
+ Datum *values;
+ bool *nulls;
+ HeapTuple new_tuple;
+
+ Assert(!bms_is_empty(updated));
+
+ num_updated = bms_num_members(updated);
+ Assert(num_updated <= natts);
+
+ values = (Datum *) palloc0(natts * sizeof(Datum));
+ nulls = (bool *) palloc0(natts * sizeof(bool));
+
+ /*
+ * Choose strategy based on update density. When updating most attributes,
+ * it's cheaper to extract the few unchanged ones individually.
+ */
+ if (num_updated > (2 * natts) / 3)
+ {
+ /* Updating many: use heap_getattr for the few non-updated attributes */
+ for (int i = 0; i < natts; i++)
+ {
+ /*
+ * Convert array index to attribute number, then to bitmapset
+ * member. Array index i (0-based) -> attnum (1-based) -> bms
+ * member.
+ */
+ AttrNumber attnum = i + 1;
+ int member = attnum - FirstLowInvalidHeapAttributeNumber;
+
+ if (bms_is_member(member, updated))
+ {
+ /* Use replacement value */
+ if (unlikely(!new_values || !new_nulls))
+ values[i] = heap_getattr(tuple, attnum, desc, &nulls[i]);
+
+ if (likely(new_values))
+ values[i] = new_values[i];
+
+ if (likely(new_nulls))
+ nulls[i] = new_nulls[i];
+ }
+ else
+ {
+ /* Extract original value using heap_getattr (1-based) */
+ values[i] = heap_getattr(tuple, attnum, desc, &nulls[i]);
+ }
+ }
+ }
+ else
+ {
+ int member = -1;
+
+ /* Updating few: deform entire tuple, then replace updated attributes */
+ heap_deform_tuple(tuple, desc, values, nulls);
+
+ while ((member = bms_next_member(updated, member)) >= 0)
+ {
+ /*
+ * Convert bitmapset member to attribute number, then to array
+ * index. bms_member -> attnum (1-based) -> array index i
+ * (0-based).
+ */
+ AttrNumber attnum = member + FirstLowInvalidHeapAttributeNumber;
+ int i = attnum - 1;
+
+ Assert(i >= 0 && i < natts);
+
+ if (likely(new_values))
+ values[i] = new_values[i];
+
+ if (likely(new_nulls))
+ nulls[i] = new_nulls[i];
+ }
+ }
+
+ /* Create the new tuple */
+ new_tuple = heap_form_tuple(desc, values, nulls);
+
+ pfree(values);
+ pfree(nulls);
+
+ /* Preserve tuple identity and location information from the original */
+ new_tuple->t_data->t_ctid = tuple->t_data->t_ctid;
+ new_tuple->t_self = tuple->t_self;
+ new_tuple->t_tableOid = tuple->t_tableOid;
+
+ return new_tuple;
+}
+
/*
* heap_deform_tuple
* Given a tuple, extract data into values/isnull arrays; this is
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 004c5121000..51efac85f65 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -225,58 +225,67 @@ CatalogTupleCheckConstraints(Relation heapRel, HeapTuple tup)
*
* This is a convenience routine for the common case of inserting a single
* tuple in a system catalog; it inserts a new heap tuple, keeping indexes
- * current. Avoid using it for multiple tuples, since opening the indexes
- * and building the index info structures is moderately expensive.
- * (Use CatalogTupleInsertWithInfo in such cases.)
+ * current.
+ *
+ * If 'indstate' is NULL, the function opens and closes the indexes internally.
+ * This is convenient for single-tuple updates but has overhead from opening the
+ * indexes and building index info structures.
+ *
+ * If 'indstate' is provided (non-NULL), it is used directly without opening or
+ * closing indexes. This allows callers to amortize index management costs across
+ * multiple tuple updates. Callers must use CatalogOpenIndexes() before the first
+ * update and CatalogCloseIndexes() after the last update.
+ *
+ * XXX: At some point we might cache the CatalogIndexState data somewhere (perhaps
+ * in the relcache) so that callers needn't trouble over this.
*/
void
-CatalogTupleInsert(Relation heapRel, HeapTuple tup)
+CatalogTupleInsert(Relation heapRel, HeapTuple tup,
+ CatalogIndexState indstate)
{
- CatalogIndexState indstate;
-
- CatalogTupleCheckConstraints(heapRel, tup);
-
- indstate = CatalogOpenIndexes(heapRel);
+ bool close_indexes = false;
- simple_heap_insert(heapRel, tup);
-
- CatalogIndexInsert(indstate, tup, TU_All);
- CatalogCloseIndexes(indstate);
-}
+ /* Open indexes if not provided by caller */
+ if (indstate == NULL)
+ {
+ indstate = CatalogOpenIndexes(heapRel);
+ close_indexes = true;
+ }
-/*
- * CatalogTupleInsertWithInfo - as above, but with caller-supplied index info
- *
- * This should be used when it's important to amortize CatalogOpenIndexes/
- * CatalogCloseIndexes work across multiple insertions. At some point we
- * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
- * so that callers needn't trouble over this ... but we don't do so today.
- */
-void
-CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
- CatalogIndexState indstate)
-{
CatalogTupleCheckConstraints(heapRel, tup);
simple_heap_insert(heapRel, tup);
CatalogIndexInsert(indstate, tup, TU_All);
+
+ /* Close indexes only if we opened them ourselves */
+ if (close_indexes)
+ CatalogCloseIndexes(indstate);
}
/*
- * CatalogTuplesMultiInsertWithInfo - as above, but for multiple tuples
+ * CatalogTuplesMultiInsert - as above, but for multiple tuples
*
* Insert multiple tuples into the given catalog relation at once, with an
* amortized cost of CatalogOpenIndexes.
*/
void
-CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot,
- int ntuples, CatalogIndexState indstate)
+CatalogTuplesMultiInsert(Relation heapRel, TupleTableSlot **slot,
+ int ntuples, CatalogIndexState indstate)
{
+ bool close_indexes = false;
+
/* Nothing to do */
if (ntuples <= 0)
return;
+ /* Open indexes if not provided by caller */
+ if (indstate == NULL)
+ {
+ indstate = CatalogOpenIndexes(heapRel);
+ close_indexes = true;
+ }
+
heap_multi_insert(heapRel, slot, ntuples,
GetCurrentCommandId(true), 0, NULL);
@@ -296,6 +305,10 @@ CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot,
if (should_free)
heap_freetuple(tuple);
}
+
+ /* Close indexes only if we opened them ourselves */
+ if (close_indexes)
+ CatalogCloseIndexes(indstate);
}
/*
@@ -303,47 +316,44 @@ CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot,
*
* Update the tuple identified by "otid", replacing it with the data in "tup".
*
- * This is a convenience routine for the common case of updating a single
- * tuple in a system catalog; it updates one heap tuple, keeping indexes
- * current. Avoid using it for multiple tuples, since opening the indexes
- * and building the index info structures is moderately expensive.
- * (Use CatalogTupleUpdateWithInfo in such cases.)
+ * This function updates a heap tuple in a system catalog and keeps its indexes
+ * current. The 'updated' bitmapset specifies which columns were modified.
+ *
+ * If 'indstate' is NULL, the function opens and closes the indexes internally.
+ * This is convenient for single-tuple updates but has overhead from opening the
+ * indexes and building index info structures.
+ *
+ * If 'indstate' is provided (non-NULL), it is used directly without opening or
+ * closing indexes. This allows callers to amortize index management costs across
+ * multiple tuple updates. Callers must use CatalogOpenIndexes() before the first
+ * update and CatalogCloseIndexes() after the last update.
+ *
+ * XXX: At some point we might cache the CatalogIndexState data somewhere (perhaps
+ * in the relcache) so that callers needn't trouble over this.
*/
void
-CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
+CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tuple,
+ const Bitmapset *updated, CatalogIndexState indstate)
{
- CatalogIndexState indstate;
TU_UpdateIndexes updateIndexes = TU_All;
+ bool close_indexes = false;
- CatalogTupleCheckConstraints(heapRel, tup);
-
- indstate = CatalogOpenIndexes(heapRel);
-
- simple_heap_update(heapRel, otid, tup, &updateIndexes);
-
- CatalogIndexInsert(indstate, tup, updateIndexes);
- CatalogCloseIndexes(indstate);
-}
+ CatalogTupleCheckConstraints(heapRel, tuple);
-/*
- * CatalogTupleUpdateWithInfo - as above, but with caller-supplied index info
- *
- * This should be used when it's important to amortize CatalogOpenIndexes/
- * CatalogCloseIndexes work across multiple updates. At some point we
- * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
- * so that callers needn't trouble over this ... but we don't do so today.
- */
-void
-CatalogTupleUpdateWithInfo(Relation heapRel, const ItemPointerData *otid, HeapTuple tup,
- CatalogIndexState indstate)
-{
- TU_UpdateIndexes updateIndexes = TU_All;
+ /* Open indexes if not provided by caller */
+ if (indstate == NULL)
+ {
+ indstate = CatalogOpenIndexes(heapRel);
+ close_indexes = true;
+ }
- CatalogTupleCheckConstraints(heapRel, tup);
+ simple_heap_update(heapRel, otid, tuple, &updateIndexes);
- simple_heap_update(heapRel, otid, tup, &updateIndexes);
+ CatalogIndexInsert(indstate, tuple, updateIndexes);
- CatalogIndexInsert(indstate, tup, updateIndexes);
+ /* Close indexes only if we opened them ourselves */
+ if (close_indexes)
+ CatalogCloseIndexes(indstate);
}
/*
@@ -355,11 +365,6 @@ CatalogTupleUpdateWithInfo(Relation heapRel, const ItemPointerData *otid, HeapTu
* cleanup will be done later by VACUUM. However, callers of this function
* shouldn't have to know that; we'd like a uniform abstraction for all
* catalog tuple changes. Hence, provide this currently-trivial wrapper.
- *
- * The abstraction is a bit leaky in that we don't provide an optimized
- * CatalogTupleDeleteWithInfo version, because there is currently nothing to
- * optimize. If we ever need that, rather than touching a lot of call sites,
- * it might be better to do something about caching CatalogIndexState.
*/
void
CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index a1cb5719a0c..0519241cbf0 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -79,9 +79,6 @@ AggregateCreate(const char *aggName,
Relation aggdesc;
HeapTuple tup;
HeapTuple oldtup;
- bool nulls[Natts_pg_aggregate];
- Datum values[Natts_pg_aggregate];
- bool replaces[Natts_pg_aggregate];
Form_pg_proc proc;
Oid transfn;
Oid finalfn = InvalidOid; /* can be omitted */
@@ -100,14 +97,14 @@ AggregateCreate(const char *aggName,
int nargs_transfn;
int nargs_finalfn;
Oid procOid;
- TupleDesc tupDesc;
char *detailmsg;
- int i;
ObjectAddress myself,
referenced;
ObjectAddresses *addrs;
AclResult aclresult;
+ CatalogUpdateValuesContext(pg_aggregate, ctx);
+
/* sanity checks (caller should have caught these) */
if (!aggName)
elog(ERROR, "no aggregate name supplied");
@@ -584,7 +581,7 @@ AggregateCreate(const char *aggName,
/*
* permission checks on used types
*/
- for (i = 0; i < numArgs; i++)
+ for (int i = 0; i < numArgs; i++)
{
aclresult = object_aclcheck(TypeRelationId, aggArgTypes[i], GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK)
@@ -648,43 +645,36 @@ AggregateCreate(const char *aggName,
* Okay to create the pg_aggregate entry.
*/
aggdesc = table_open(AggregateRelationId, RowExclusiveLock);
- tupDesc = aggdesc->rd_att;
/* initialize nulls and values */
- for (i = 0; i < Natts_pg_aggregate; i++)
- {
- nulls[i] = false;
- values[i] = (Datum) 0;
- replaces[i] = true;
- }
- values[Anum_pg_aggregate_aggfnoid - 1] = ObjectIdGetDatum(procOid);
- values[Anum_pg_aggregate_aggkind - 1] = CharGetDatum(aggKind);
- values[Anum_pg_aggregate_aggnumdirectargs - 1] = Int16GetDatum(numDirectArgs);
- values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn);
- values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn);
- values[Anum_pg_aggregate_aggcombinefn - 1] = ObjectIdGetDatum(combinefn);
- values[Anum_pg_aggregate_aggserialfn - 1] = ObjectIdGetDatum(serialfn);
- values[Anum_pg_aggregate_aggdeserialfn - 1] = ObjectIdGetDatum(deserialfn);
- values[Anum_pg_aggregate_aggmtransfn - 1] = ObjectIdGetDatum(mtransfn);
- values[Anum_pg_aggregate_aggminvtransfn - 1] = ObjectIdGetDatum(minvtransfn);
- values[Anum_pg_aggregate_aggmfinalfn - 1] = ObjectIdGetDatum(mfinalfn);
- values[Anum_pg_aggregate_aggfinalextra - 1] = BoolGetDatum(finalfnExtraArgs);
- values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs);
- values[Anum_pg_aggregate_aggfinalmodify - 1] = CharGetDatum(finalfnModify);
- values[Anum_pg_aggregate_aggmfinalmodify - 1] = CharGetDatum(mfinalfnModify);
- values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
- values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
- values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace);
- values[Anum_pg_aggregate_aggmtranstype - 1] = ObjectIdGetDatum(aggmTransType);
- values[Anum_pg_aggregate_aggmtransspace - 1] = Int32GetDatum(aggmTransSpace);
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggfnoid, ObjectIdGetDatum(procOid));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggkind, CharGetDatum(aggKind));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggnumdirectargs, Int16GetDatum(numDirectArgs));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggtransfn, ObjectIdGetDatum(transfn));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggfinalfn, ObjectIdGetDatum(finalfn));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggcombinefn, ObjectIdGetDatum(combinefn));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggserialfn, ObjectIdGetDatum(serialfn));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggdeserialfn, ObjectIdGetDatum(deserialfn));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggmtransfn, ObjectIdGetDatum(mtransfn));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggminvtransfn, ObjectIdGetDatum(minvtransfn));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggmfinalfn, ObjectIdGetDatum(mfinalfn));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggfinalextra, BoolGetDatum(finalfnExtraArgs));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggmfinalextra, BoolGetDatum(mfinalfnExtraArgs));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggfinalmodify, CharGetDatum(finalfnModify));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggmfinalmodify, CharGetDatum(mfinalfnModify));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggsortop, ObjectIdGetDatum(sortop));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggtranstype, ObjectIdGetDatum(aggTransType));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggtransspace, Int32GetDatum(aggTransSpace));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggmtranstype, ObjectIdGetDatum(aggmTransType));
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggmtransspace, Int32GetDatum(aggmTransSpace));
if (agginitval)
- values[Anum_pg_aggregate_agginitval - 1] = CStringGetTextDatum(agginitval);
+ CatalogTupleUpdateValue(ctx, pg_aggregate, agginitval, CStringGetTextDatum(agginitval));
else
- nulls[Anum_pg_aggregate_agginitval - 1] = true;
+ CatalogTupleUpdateValueNull(ctx, pg_aggregate, agginitval);
if (aggminitval)
- values[Anum_pg_aggregate_aggminitval - 1] = CStringGetTextDatum(aggminitval);
+ CatalogTupleUpdateValue(ctx, pg_aggregate, aggminitval, CStringGetTextDatum(aggminitval));
else
- nulls[Anum_pg_aggregate_aggminitval - 1] = true;
+ CatalogTupleUpdateValueNull(ctx, pg_aggregate, aggminitval);
if (replace)
oldtup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(procOid));
@@ -717,18 +707,12 @@ AggregateCreate(const char *aggName,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot change number of direct arguments of an aggregate function")));
- replaces[Anum_pg_aggregate_aggfnoid - 1] = false;
- replaces[Anum_pg_aggregate_aggkind - 1] = false;
- replaces[Anum_pg_aggregate_aggnumdirectargs - 1] = false;
-
- tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
- CatalogTupleUpdate(aggdesc, &tup->t_self, tup);
+ ModifyCatalogTupleValues(aggdesc, oldtup, ctx);
ReleaseSysCache(oldtup);
}
else
{
- tup = heap_form_tuple(tupDesc, values, nulls);
- CatalogTupleInsert(aggdesc, tup);
+ InsertCatalogTupleValues(aggdesc, ctx);
}
table_close(aggdesc, RowExclusiveLock);
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 9944e4bd2d1..d09daad0b1b 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -84,9 +84,6 @@ CreateConstraintEntry(const char *constraintName,
{
Relation conDesc;
Oid conOid;
- HeapTuple tup;
- bool nulls[Natts_pg_constraint];
- Datum values[Natts_pg_constraint];
ArrayType *conkeyArray;
ArrayType *confkeyArray;
ArrayType *conpfeqopArray;
@@ -100,6 +97,8 @@ CreateConstraintEntry(const char *constraintName,
ObjectAddresses *addrs_auto;
ObjectAddresses *addrs_normal;
+ CatalogInsertValuesContext(pg_constraint, ctx);
+
/* Only CHECK or FOREIGN KEY constraint can be not enforced */
Assert(isEnforced || constraintType == CONSTRAINT_CHECK ||
constraintType == CONSTRAINT_FOREIGN);
@@ -175,79 +174,70 @@ CreateConstraintEntry(const char *constraintName,
else
conexclopArray = NULL;
- /* initialize nulls and values */
- for (i = 0; i < Natts_pg_constraint; i++)
- {
- nulls[i] = false;
- values[i] = (Datum) 0;
- }
-
conOid = GetNewOidWithIndex(conDesc, ConstraintOidIndexId,
Anum_pg_constraint_oid);
- values[Anum_pg_constraint_oid - 1] = ObjectIdGetDatum(conOid);
- values[Anum_pg_constraint_conname - 1] = NameGetDatum(&cname);
- values[Anum_pg_constraint_connamespace - 1] = ObjectIdGetDatum(constraintNamespace);
- values[Anum_pg_constraint_contype - 1] = CharGetDatum(constraintType);
- values[Anum_pg_constraint_condeferrable - 1] = BoolGetDatum(isDeferrable);
- values[Anum_pg_constraint_condeferred - 1] = BoolGetDatum(isDeferred);
- values[Anum_pg_constraint_conenforced - 1] = BoolGetDatum(isEnforced);
- values[Anum_pg_constraint_convalidated - 1] = BoolGetDatum(isValidated);
- values[Anum_pg_constraint_conrelid - 1] = ObjectIdGetDatum(relId);
- values[Anum_pg_constraint_contypid - 1] = ObjectIdGetDatum(domainId);
- values[Anum_pg_constraint_conindid - 1] = ObjectIdGetDatum(indexRelId);
- values[Anum_pg_constraint_conparentid - 1] = ObjectIdGetDatum(parentConstrId);
- values[Anum_pg_constraint_confrelid - 1] = ObjectIdGetDatum(foreignRelId);
- values[Anum_pg_constraint_confupdtype - 1] = CharGetDatum(foreignUpdateType);
- values[Anum_pg_constraint_confdeltype - 1] = CharGetDatum(foreignDeleteType);
- values[Anum_pg_constraint_confmatchtype - 1] = CharGetDatum(foreignMatchType);
- values[Anum_pg_constraint_conislocal - 1] = BoolGetDatum(conIsLocal);
- values[Anum_pg_constraint_coninhcount - 1] = Int16GetDatum(conInhCount);
- values[Anum_pg_constraint_connoinherit - 1] = BoolGetDatum(conNoInherit);
- values[Anum_pg_constraint_conperiod - 1] = BoolGetDatum(conPeriod);
+ CatalogTupleSetValue(ctx, pg_constraint, oid, ObjectIdGetDatum(conOid));
+ CatalogTupleSetValue(ctx, pg_constraint, conname, NameGetDatum(&cname));
+ CatalogTupleSetValue(ctx, pg_constraint, connamespace, ObjectIdGetDatum(constraintNamespace));
+ CatalogTupleSetValue(ctx, pg_constraint, contype, CharGetDatum(constraintType));
+ CatalogTupleSetValue(ctx, pg_constraint, condeferrable, BoolGetDatum(isDeferrable));
+ CatalogTupleSetValue(ctx, pg_constraint, condeferred, BoolGetDatum(isDeferred));
+ CatalogTupleSetValue(ctx, pg_constraint, conenforced, BoolGetDatum(isEnforced));
+ CatalogTupleSetValue(ctx, pg_constraint, convalidated, BoolGetDatum(isValidated));
+ CatalogTupleSetValue(ctx, pg_constraint, conrelid, ObjectIdGetDatum(relId));
+ CatalogTupleSetValue(ctx, pg_constraint, contypid, ObjectIdGetDatum(domainId));
+ CatalogTupleSetValue(ctx, pg_constraint, conindid, ObjectIdGetDatum(indexRelId));
+ CatalogTupleSetValue(ctx, pg_constraint, conparentid, ObjectIdGetDatum(parentConstrId));
+ CatalogTupleSetValue(ctx, pg_constraint, confrelid, ObjectIdGetDatum(foreignRelId));
+ CatalogTupleSetValue(ctx, pg_constraint, confupdtype, CharGetDatum(foreignUpdateType));
+ CatalogTupleSetValue(ctx, pg_constraint, confdeltype, CharGetDatum(foreignDeleteType));
+ CatalogTupleSetValue(ctx, pg_constraint, confmatchtype, CharGetDatum(foreignMatchType));
+ CatalogTupleSetValue(ctx, pg_constraint, conislocal, BoolGetDatum(conIsLocal));
+ CatalogTupleSetValue(ctx, pg_constraint, coninhcount, Int16GetDatum(conInhCount));
+ CatalogTupleSetValue(ctx, pg_constraint, connoinherit, BoolGetDatum(conNoInherit));
+ CatalogTupleSetValue(ctx, pg_constraint, conperiod, BoolGetDatum(conPeriod));
if (conkeyArray)
- values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray);
+ CatalogTupleSetValue(ctx, pg_constraint, conkey, PointerGetDatum(conkeyArray));
else
- nulls[Anum_pg_constraint_conkey - 1] = true;
+ CatalogTupleSetValueNull(ctx, pg_constraint, conkey);
if (confkeyArray)
- values[Anum_pg_constraint_confkey - 1] = PointerGetDatum(confkeyArray);
+ CatalogTupleSetValue(ctx, pg_constraint, confkey, PointerGetDatum(confkeyArray));
else
- nulls[Anum_pg_constraint_confkey - 1] = true;
+ CatalogTupleSetValueNull(ctx, pg_constraint, confkey);
if (conpfeqopArray)
- values[Anum_pg_constraint_conpfeqop - 1] = PointerGetDatum(conpfeqopArray);
+ CatalogTupleSetValue(ctx, pg_constraint, conpfeqop, PointerGetDatum(conpfeqopArray));
else
- nulls[Anum_pg_constraint_conpfeqop - 1] = true;
+ CatalogTupleSetValueNull(ctx, pg_constraint, conpfeqop);
if (conppeqopArray)
- values[Anum_pg_constraint_conppeqop - 1] = PointerGetDatum(conppeqopArray);
+ CatalogTupleSetValue(ctx, pg_constraint, conppeqop, PointerGetDatum(conppeqopArray));
else
- nulls[Anum_pg_constraint_conppeqop - 1] = true;
+ CatalogTupleSetValueNull(ctx, pg_constraint, conppeqop);
if (conffeqopArray)
- values[Anum_pg_constraint_conffeqop - 1] = PointerGetDatum(conffeqopArray);
+ CatalogTupleSetValue(ctx, pg_constraint, conffeqop, PointerGetDatum(conffeqopArray));
else
- nulls[Anum_pg_constraint_conffeqop - 1] = true;
+ CatalogTupleSetValueNull(ctx, pg_constraint, conffeqop);
if (confdelsetcolsArray)
- values[Anum_pg_constraint_confdelsetcols - 1] = PointerGetDatum(confdelsetcolsArray);
+ CatalogTupleSetValue(ctx, pg_constraint, confdelsetcols, PointerGetDatum(confdelsetcolsArray));
else
- nulls[Anum_pg_constraint_confdelsetcols - 1] = true;
+ CatalogTupleSetValueNull(ctx, pg_constraint, confdelsetcols);
if (conexclopArray)
- values[Anum_pg_constraint_conexclop - 1] = PointerGetDatum(conexclopArray);
+ CatalogTupleSetValue(ctx, pg_constraint, conexclop, PointerGetDatum(conexclopArray));
else
- nulls[Anum_pg_constraint_conexclop - 1] = true;
+ CatalogTupleSetValueNull(ctx, pg_constraint, conexclop);
if (conBin)
- values[Anum_pg_constraint_conbin - 1] = CStringGetTextDatum(conBin);
+ CatalogTupleSetValue(ctx, pg_constraint, conbin, CStringGetTextDatum(conBin));
else
- nulls[Anum_pg_constraint_conbin - 1] = true;
+ CatalogTupleSetValueNull(ctx, pg_constraint, conbin);
- tup = heap_form_tuple(RelationGetDescr(conDesc), values, nulls);
-
- CatalogTupleInsert(conDesc, tup);
+ InsertCatalogTupleValues(conDesc, ctx);
ObjectAddressSet(conobject, ConstraintRelationId, conOid);
@@ -747,21 +737,21 @@ AdjustNotNullInheritance(Oid relid, AttrNumber attnum,
if (HeapTupleIsValid(tup))
{
Relation pg_constraint;
- Form_pg_constraint conform;
- bool changed = false;
+
+ CatalogUpdateFormContext(pg_constraint, ctx);
+ CatalogSetForm(pg_constraint, ctx, tup);
pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock);
- conform = (Form_pg_constraint) GETSTRUCT(tup);
/*
* If the NO INHERIT flag we're asked for doesn't match what the
* existing constraint has, throw an error.
*/
- if (is_no_inherit != conform->connoinherit)
+ if (is_no_inherit != CatalogGetFormField(ctx, connoinherit))
ereport(ERROR,
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"",
- NameStr(conform->conname), get_rel_name(relid)),
+ NameStr(CatalogGetFormField(ctx, conname)), get_rel_name(relid)),
errhint("You might need to make the existing constraint inheritable using %s.",
"ALTER TABLE ... ALTER CONSTRAINT ... INHERIT"));
@@ -769,31 +759,29 @@ AdjustNotNullInheritance(Oid relid, AttrNumber attnum,
* Throw an error if the existing constraint is NOT VALID and caller
* wants a valid one.
*/
- if (!is_notvalid && !conform->convalidated)
+ if (!is_notvalid && !CatalogGetFormField(ctx, convalidated))
ereport(ERROR,
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("incompatible NOT VALID constraint \"%s\" on relation \"%s\"",
- NameStr(conform->conname), get_rel_name(relid)),
+ NameStr(CatalogGetFormField(ctx, conname)), get_rel_name(relid)),
errhint("You might need to validate it using %s.",
"ALTER TABLE ... VALIDATE CONSTRAINT"));
if (!is_local)
{
- if (pg_add_s16_overflow(conform->coninhcount, 1,
- &conform->coninhcount))
- ereport(ERROR,
- errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("too many inheritance parents"));
- changed = true;
+ CatalogTupleCondUpdateValue(ctx, pg_constraint, coninhcount,
+ pg_add_s16_overflow(CatalogGetFormField(ctx, coninhcount), 1,
+ &CatalogGetFormField(ctx, coninhcount)),
+ ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("too many inheritance parents")));
}
- else if (!conform->conislocal)
+ else if (!CatalogGetFormField(ctx, conislocal))
{
- conform->conislocal = true;
- changed = true;
+ CatalogTupleUpdateField(ctx, pg_constraint, conislocal, true);
}
- if (changed)
- CatalogTupleUpdate(pg_constraint, &tup->t_self, tup);
+ if (CatalogTupleHasChanged(ctx))
+ UpdateCatalogTupleForm(pg_constraint, tup, ctx);
table_close(pg_constraint, RowExclusiveLock);
@@ -928,6 +916,7 @@ RemoveConstraintById(Oid conId)
Relation pgrel;
HeapTuple relTup;
Form_pg_class classForm;
+ Bitmapset *updated = NULL;
pgrel = table_open(RelationRelationId, RowExclusiveLock);
relTup = SearchSysCacheCopy1(RELOID,
@@ -938,14 +927,14 @@ RemoveConstraintById(Oid conId)
classForm = (Form_pg_class) GETSTRUCT(relTup);
if (classForm->relchecks > 0)
- classForm->relchecks--;
+ HeapTupleUpdateField(pg_class, relchecks, classForm->relchecks - 1, classForm, updated);
else
/* should not happen */
elog(WARNING, "relation \"%s\" has relchecks = %d",
RelationGetRelationName(rel), classForm->relchecks);
- CatalogTupleUpdate(pgrel, &relTup->t_self, relTup);
-
+ CatalogTupleUpdate(pgrel, &relTup->t_self, relTup, updated, NULL);
+ bms_free(updated);
heap_freetuple(relTup);
table_close(pgrel, RowExclusiveLock);
@@ -990,6 +979,7 @@ RenameConstraintById(Oid conId, const char *newname)
Relation conDesc;
HeapTuple tuple;
Form_pg_constraint con;
+ Bitmapset *updated = NULL;
conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
@@ -1020,11 +1010,13 @@ RenameConstraintById(Oid conId, const char *newname)
/* OK, do the rename --- tuple is a copy, so OK to scribble on it */
namestrcpy(&(con->conname), newname);
+ HeapTupleMarkColumnUpdated(pg_constraint, conname, updated);
- CatalogTupleUpdate(conDesc, &tuple->t_self, tuple);
+ CatalogTupleUpdate(conDesc, &tuple->t_self, tuple, updated, NULL);
InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
+ bms_free(updated);
heap_freetuple(tuple);
table_close(conDesc, RowExclusiveLock);
}
@@ -1072,15 +1064,17 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
/* Don't update if the object is already part of the namespace */
if (conform->connamespace == oldNspId && oldNspId != newNspId)
{
+ Bitmapset *updated = NULL;
+
tup = heap_copytuple(tup);
conform = (Form_pg_constraint) GETSTRUCT(tup);
- conform->connamespace = newNspId;
-
- CatalogTupleUpdate(conRel, &tup->t_self, tup);
+ HeapTupleUpdateField(pg_constraint, connamespace, newNspId, conform, updated);
+ CatalogTupleUpdate(conRel, &tup->t_self, tup, updated, NULL);
+ bms_free(updated);
/*
- * Note: currently, the constraint will not have its own
+ * NOTE: currently, the constraint will not have its own
* dependency on the namespace, so we don't need to do
* changeDependencyFor().
*/
@@ -1116,6 +1110,7 @@ ConstraintSetParentConstraint(Oid childConstrId,
newtup;
ObjectAddress depender;
ObjectAddress referenced;
+ Bitmapset *updated = NULL;
constrRel = table_open(ConstraintRelationId, RowExclusiveLock);
tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(childConstrId));
@@ -1131,16 +1126,17 @@ ConstraintSetParentConstraint(Oid childConstrId,
elog(ERROR, "constraint %u already has a parent constraint",
childConstrId);
- constrForm->conislocal = false;
+ HeapTupleUpdateField(pg_constraint, conislocal, false, constrForm, updated);
if (pg_add_s16_overflow(constrForm->coninhcount, 1,
&constrForm->coninhcount))
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
- constrForm->conparentid = parentConstrId;
+ HeapTupleMarkColumnUpdated(pg_constraint, coninhcount, updated);
+ HeapTupleUpdateField(pg_constraint, conparentid, parentConstrId, constrForm, updated);
- CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
+ CatalogTupleUpdate(constrRel, &tuple->t_self, newtup, updated, NULL);
ObjectAddressSet(depender, ConstraintRelationId, childConstrId);
@@ -1152,14 +1148,14 @@ ConstraintSetParentConstraint(Oid childConstrId,
}
else
{
- constrForm->coninhcount--;
- constrForm->conislocal = true;
- constrForm->conparentid = InvalidOid;
+ HeapTupleUpdateField(pg_constraint, coninhcount, constrForm->coninhcount - 1, constrForm, updated);
+ HeapTupleUpdateField(pg_constraint, conislocal, true, constrForm, updated);
+ HeapTupleUpdateField(pg_constraint, conparentid, InvalidOid, constrForm, updated);
/* Make sure there's no further inheritance. */
Assert(constrForm->coninhcount == 0);
- CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
+ CatalogTupleUpdate(constrRel, &tuple->t_self, newtup, updated, NULL);
deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
ConstraintRelationId,
@@ -1169,6 +1165,7 @@ ConstraintSetParentConstraint(Oid childConstrId,
DEPENDENCY_PARTITION_SEC);
}
+ bms_free(updated);
ReleaseSysCache(tuple);
table_close(constrRel, RowExclusiveLock);
}
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index cb75e11fced..b132301e683 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -180,7 +180,7 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
AclResult aclresult;
Datum *values;
bool *nulls;
- bool *replaces;
+ Bitmapset *updated = NULL;
NameData nameattrdata;
oldtup = SearchSysCache1(oidCacheId, ObjectIdGetDatum(objectId));
@@ -326,15 +326,21 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
/* Build modified tuple */
values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
- replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
+
+ /*
+ * NOTE: We can't use the CatalogTuple*() macros here because 'Anum_name'
+ * isn't a table/field name, it's a index for the relation passed into the
+ * function as an argument.
+ */
namestrcpy(&nameattrdata, new_name);
values[Anum_name - 1] = NameGetDatum(&nameattrdata);
- replaces[Anum_name - 1] = true;
- newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
- values, nulls, replaces);
+ updated = bms_add_member(updated, Anum_name - FirstLowInvalidHeapAttributeNumber);
+
+ newtup = heap_update_tuple(oldtup, RelationGetDescr(rel),
+ values, nulls, updated);
/* Perform actual update */
- CatalogTupleUpdate(rel, &oldtup->t_self, newtup);
+ CatalogTupleUpdate(rel, &oldtup->t_self, newtup, updated, NULL);
InvokeObjectPostAlterHook(classId, objectId, 0);
@@ -357,7 +363,7 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
/* Release memory */
pfree(values);
pfree(nulls);
- pfree(replaces);
+ bms_free(updated);
heap_freetuple(newtup);
ReleaseSysCache(oldtup);
@@ -705,7 +711,7 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
newtup;
Datum *values;
bool *nulls;
- bool *replaces;
+ Bitmapset *updated = NULL;
tup = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objid));
if (!HeapTupleIsValid(tup)) /* should not happen */
@@ -804,19 +810,21 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
/* Build modified tuple */
values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
- replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
+
+ /* NOTE: Don't use the CatalogTuple*() macros here either. */
values[Anum_namespace - 1] = ObjectIdGetDatum(nspOid);
- replaces[Anum_namespace - 1] = true;
- newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
- values, nulls, replaces);
+ updated = bms_add_member(updated, Anum_namespace - FirstLowInvalidHeapAttributeNumber);
+
+ newtup = heap_update_tuple(tup, RelationGetDescr(rel),
+ values, nulls, updated);
/* Perform actual update */
- CatalogTupleUpdate(rel, &tup->t_self, newtup);
+ CatalogTupleUpdate(rel, &tup->t_self, newtup, updated, NULL);
/* Release memory */
pfree(values);
pfree(nulls);
- pfree(replaces);
+ bms_free(updated);
/* update dependency to point to the new schema */
if (changeDependencyFor(classId, objid,
@@ -967,7 +975,7 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
HeapTuple newtup;
Datum *values;
bool *nulls;
- bool *replaces;
+ Bitmapset *updated = NULL;
/* Superusers can bypass permission checks */
if (!superuser())
@@ -1014,9 +1022,10 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
nattrs = RelationGetNumberOfAttributes(rel);
values = palloc0(nattrs * sizeof(Datum));
nulls = palloc0(nattrs * sizeof(bool));
- replaces = palloc0(nattrs * sizeof(bool));
+
+ /* NOTE: Don't use the CatalogTuple() macros here either */
values[Anum_owner - 1] = ObjectIdGetDatum(new_ownerId);
- replaces[Anum_owner - 1] = true;
+ updated = bms_add_member(updated, Anum_owner - FirstLowInvalidHeapAttributeNumber);
/*
* Determine the modified ACL for the new owner. This is only
@@ -1032,16 +1041,18 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
newAcl = aclnewowner(DatumGetAclP(datum),
old_ownerId, new_ownerId);
+
+ /* NOTE: Don't use the CatalogTuple*() macros here either */
values[Anum_acl - 1] = PointerGetDatum(newAcl);
- replaces[Anum_acl - 1] = true;
+ updated = bms_add_member(updated, Anum_acl - FirstLowInvalidHeapAttributeNumber);
}
}
- newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
- values, nulls, replaces);
+ newtup = heap_update_tuple(oldtup, RelationGetDescr(rel),
+ values, nulls, updated);
/* Perform actual update */
- CatalogTupleUpdate(rel, &newtup->t_self, newtup);
+ CatalogTupleUpdate(rel, &newtup->t_self, newtup, updated, NULL);
UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock);
@@ -1051,7 +1062,7 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
/* Release memory */
pfree(values);
pfree(nulls);
- pfree(replaces);
+ bms_free(updated);
}
else
UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock);
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 25089fae3e0..6fb774133d9 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -29,6 +29,7 @@
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/pg_inherits.h"
+#include "catalog/pg_statistic.h"
#include "commands/progress.h"
#include "commands/tablecmds.h"
#include "commands/vacuum.h"
@@ -1666,50 +1667,34 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
for (attno = 0; attno < natts; attno++)
{
VacAttrStats *stats = vacattrstats[attno];
- HeapTuple stup,
- oldtup;
- int i,
- k,
+ HeapTuple oldtup;
+ int k,
n;
- Datum values[Natts_pg_statistic];
- bool nulls[Natts_pg_statistic];
- bool replaces[Natts_pg_statistic];
+
+ CatalogUpdateValuesContext(pg_statistic, ctx);
/* Ignore attr if we weren't able to collect stats */
if (!stats->stats_valid)
continue;
- /*
- * Construct a new pg_statistic tuple
- */
- for (i = 0; i < Natts_pg_statistic; ++i)
- {
- nulls[i] = false;
- replaces[i] = true;
- }
+ /* Construct a new pg_statistic tuple */
+ CatalogTupleUpdateMarkAllColumnsUpdated(ctx, pg_statistic);
+ CatalogTupleSetValue(ctx, pg_statistic, starelid, ObjectIdGetDatum(relid));
+ CatalogTupleSetValue(ctx, pg_statistic, staattnum, Int16GetDatum(stats->tupattnum));
+ CatalogTupleSetValue(ctx, pg_statistic, stainherit, BoolGetDatum(inh));
+ CatalogTupleSetValue(ctx, pg_statistic, stanullfrac, Float4GetDatum(stats->stanullfrac));
+ CatalogTupleSetValue(ctx, pg_statistic, stawidth, Int32GetDatum(stats->stawidth));
+ CatalogTupleSetValue(ctx, pg_statistic, stadistinct, Float4GetDatum(stats->stadistinct));
- values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(relid);
- values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(stats->tupattnum);
- values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(inh);
- 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);
- i = Anum_pg_statistic_stakind1 - 1;
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
- {
- values[i++] = Int16GetDatum(stats->stakind[k]); /* stakindN */
- }
- i = Anum_pg_statistic_staop1 - 1;
+ CatalogTupleSetValue(ctx, pg_statistic, stakind1 + k, Int16GetDatum(stats->stakind[k]));
+
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
- {
- values[i++] = ObjectIdGetDatum(stats->staop[k]); /* staopN */
- }
- i = Anum_pg_statistic_stacoll1 - 1;
+ CatalogTupleSetValue(ctx, pg_statistic, staop1 + k, ObjectIdGetDatum(stats->staop[k]));
+
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
- {
- values[i++] = ObjectIdGetDatum(stats->stacoll[k]); /* stacollN */
- }
- i = Anum_pg_statistic_stanumbers1 - 1;
+ CatalogTupleSetValue(ctx, pg_statistic, stacoll1 + k, ObjectIdGetDatum(stats->stacoll[k]));
+
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
{
if (stats->stanumbers[k] != NULL)
@@ -1721,15 +1706,12 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
for (n = 0; n < nnum; n++)
numdatums[n] = Float4GetDatum(stats->stanumbers[k][n]);
arry = construct_array_builtin(numdatums, nnum, FLOAT4OID);
- values[i++] = PointerGetDatum(arry); /* stanumbersN */
+ CatalogTupleSetValue(ctx, pg_statistic, stanumbers1 + k, PointerGetDatum(arry));
}
else
- {
- nulls[i] = true;
- values[i++] = (Datum) 0;
- }
+ CatalogTupleSetValueNull(ctx, pg_statistic, stanumbers1 + k);
}
- i = Anum_pg_statistic_stavalues1 - 1;
+
for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
{
if (stats->stavalues[k] != NULL)
@@ -1742,12 +1724,11 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
stats->statyplen[k],
stats->statypbyval[k],
stats->statypalign[k]);
- values[i++] = PointerGetDatum(arry); /* stavaluesN */
+ CatalogTupleSetValue(ctx, pg_statistic, stavalues1 + k, PointerGetDatum(arry));
}
else
{
- nulls[i] = true;
- values[i++] = (Datum) 0;
+ CatalogTupleSetValueNull(ctx, pg_statistic, stavalues1 + k);
}
}
@@ -1761,29 +1742,26 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
if (indstate == NULL)
indstate = CatalogOpenIndexes(sd);
+ ctx->idx = indstate;
+
if (HeapTupleIsValid(oldtup))
{
- /* Yes, replace it */
- stup = heap_modify_tuple(oldtup,
- RelationGetDescr(sd),
- values,
- nulls,
- replaces);
+ /* Yes, replace existing tuple */
+ ModifyCatalogTupleValues(sd, oldtup, ctx);
ReleaseSysCache(oldtup);
- CatalogTupleUpdateWithInfo(sd, &stup->t_self, stup, indstate);
}
else
{
/* No, insert new tuple */
- stup = heap_form_tuple(RelationGetDescr(sd), values, nulls);
- CatalogTupleInsertWithInfo(sd, stup, indstate);
+ InsertCatalogTupleValues(sd, ctx);
}
- heap_freetuple(stup);
+ CatalogTupleReuseUpdateContext(ctx);
}
if (indstate != NULL)
CatalogCloseIndexes(indstate);
+
table_close(sd, RowExclusiveLock);
}
diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c
index ef4d768feab..fd4a25326b3 100644
--- a/src/backend/statistics/attribute_stats.c
+++ b/src/backend/statistics/attribute_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 "catalog/pg_collation.h"
@@ -120,15 +121,13 @@ static bool get_elem_stat_type(Oid atttypid, char atttyptype,
Oid *elemtypid, Oid *elem_eq_opr);
static Datum text_to_stavalues(const char *staname, FmgrInfo *array_in, Datum d,
Oid typid, int32 typmod, bool *ok);
-static void set_stats_slot(Datum *values, bool *nulls, bool *replaces,
+static void set_stats_slot(void *_ctx,
int16 stakind, Oid staop, Oid stacoll,
Datum stanumbers, bool stanumbers_isnull,
Datum stavalues, bool stavalues_isnull);
-static void upsert_pg_statistic(Relation starel, HeapTuple oldtup,
- const Datum *values, const bool *nulls, const bool *replaces);
+static void upsert_pg_statistic(Relation starel, HeapTuple oldtup, void *_ctx);
static bool delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit);
-static void init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited,
- Datum *values, bool *nulls, bool *replaces);
+static void init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited, void *_ctx);
/*
* Insert or Update Attribute Statistics
@@ -182,13 +181,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
bool do_bounds_histogram = !PG_ARGISNULL(RANGE_BOUNDS_HISTOGRAM_ARG);
bool do_range_length_histogram = !PG_ARGISNULL(RANGE_LENGTH_HISTOGRAM_ARG) &&
!PG_ARGISNULL(RANGE_EMPTY_FRAC_ARG);
-
- Datum values[Natts_pg_statistic] = {0};
- bool nulls[Natts_pg_statistic] = {0};
- bool replaces[Natts_pg_statistic] = {0};
-
bool result = true;
+ CatalogUpdateValuesContext(pg_statistic, ctx);
+
stats_check_required_arg(fcinfo, attarginfo, ATTRELSCHEMA_ARG);
stats_check_required_arg(fcinfo, attarginfo, ATTRELNAME_ARG);
@@ -359,27 +355,19 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
/* initialize from existing tuple if exists */
if (HeapTupleIsValid(statup))
- heap_deform_tuple(statup, RelationGetDescr(starel), values, nulls);
+ DeformCatalogTuple(starel, statup, ctx);
else
- init_empty_stats_tuple(reloid, attnum, inherited, values, nulls,
- replaces);
+ init_empty_stats_tuple(reloid, attnum, inherited, (void *) ctx);
/* if specified, set to argument values */
if (!PG_ARGISNULL(NULL_FRAC_ARG))
- {
- values[Anum_pg_statistic_stanullfrac - 1] = PG_GETARG_DATUM(NULL_FRAC_ARG);
- replaces[Anum_pg_statistic_stanullfrac - 1] = true;
- }
+ CatalogTupleUpdateValue(ctx, pg_statistic, stanullfrac, PG_GETARG_DATUM(NULL_FRAC_ARG));
+
if (!PG_ARGISNULL(AVG_WIDTH_ARG))
- {
- values[Anum_pg_statistic_stawidth - 1] = PG_GETARG_DATUM(AVG_WIDTH_ARG);
- replaces[Anum_pg_statistic_stawidth - 1] = true;
- }
+ CatalogTupleUpdateValue(ctx, pg_statistic, stawidth, PG_GETARG_DATUM(AVG_WIDTH_ARG));
+
if (!PG_ARGISNULL(N_DISTINCT_ARG))
- {
- values[Anum_pg_statistic_stadistinct - 1] = PG_GETARG_DATUM(N_DISTINCT_ARG);
- replaces[Anum_pg_statistic_stadistinct - 1] = true;
- }
+ CatalogTupleUpdateValue(ctx, pg_statistic, stadistinct, PG_GETARG_DATUM(N_DISTINCT_ARG));
/* STATISTIC_KIND_MCV */
if (do_mcv)
@@ -394,7 +382,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (converted)
{
- set_stats_slot(values, nulls, replaces,
+ set_stats_slot(ctx,
STATISTIC_KIND_MCV,
eq_opr, atttypcoll,
stanumbers, false, stavalues, false);
@@ -417,7 +405,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (converted)
{
- set_stats_slot(values, nulls, replaces,
+ set_stats_slot(ctx,
STATISTIC_KIND_HISTOGRAM,
lt_opr, atttypcoll,
0, true, stavalues, false);
@@ -433,7 +421,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
ArrayType *arry = construct_array_builtin(elems, 1, FLOAT4OID);
Datum stanumbers = PointerGetDatum(arry);
- set_stats_slot(values, nulls, replaces,
+ set_stats_slot(ctx,
STATISTIC_KIND_CORRELATION,
lt_opr, atttypcoll,
stanumbers, false, 0, true);
@@ -454,7 +442,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (converted)
{
- set_stats_slot(values, nulls, replaces,
+ set_stats_slot(ctx,
STATISTIC_KIND_MCELEM,
elem_eq_opr, atttypcoll,
stanumbers, false, stavalues, false);
@@ -468,7 +456,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
{
Datum stanumbers = PG_GETARG_DATUM(ELEM_COUNT_HISTOGRAM_ARG);
- set_stats_slot(values, nulls, replaces,
+ set_stats_slot(ctx,
STATISTIC_KIND_DECHIST,
elem_eq_opr, atttypcoll,
stanumbers, false, 0, true);
@@ -494,7 +482,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (converted)
{
- set_stats_slot(values, nulls, replaces,
+ set_stats_slot(ctx,
STATISTIC_KIND_BOUNDS_HISTOGRAM,
InvalidOid, InvalidOid,
0, true, stavalues, false);
@@ -521,7 +509,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (converted)
{
- set_stats_slot(values, nulls, replaces,
+ set_stats_slot(ctx,
STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM,
Float8LessOperator, InvalidOid,
stanumbers, false, stavalues, false);
@@ -530,7 +518,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
result = false;
}
- upsert_pg_statistic(starel, statup, values, nulls, replaces);
+ upsert_pg_statistic(starel, statup, ctx);
if (HeapTupleIsValid(statup))
ReleaseSysCache(statup);
@@ -760,92 +748,75 @@ text_to_stavalues(const char *staname, FmgrInfo *array_in, Datum d, Oid typid,
* slot.
*/
static void
-set_stats_slot(Datum *values, bool *nulls, bool *replaces,
+set_stats_slot(void *_ctx,
int16 stakind, Oid staop, Oid stacoll,
Datum stanumbers, bool stanumbers_isnull,
Datum stavalues, bool stavalues_isnull)
{
- int slotidx;
+ CatalogUpdateValuesDecl(pg_statistic, ctx) * ctx = _ctx;
+ int i = 0;
int first_empty = -1;
- AttrNumber stakind_attnum;
- AttrNumber staop_attnum;
- AttrNumber stacoll_attnum;
- /* find existing slot with given stakind */
- for (slotidx = 0; slotidx < STATISTIC_NUM_SLOTS; slotidx++)
+ /*
+ * This might seem odd, to be adding 'i' to the name of the field on these
+ * macros, but that's what we need to do here to find the proper slot
+ * offset and record the proper value into the updated bitmap.
+ *
+ * Example: CatalogTupleValue(ctx, pg_statistic, stakind1 + i);
+ *
+ * Becomes: ctx.values[Anum_pg_statistic_stakind1 + i - 1];
+ *
+ * The result is you're indexing the i'th value, exactly what we needed.
+ */
+
+ /* Find existing slot with given stakind */
+ for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
{
- stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx;
+ Datum d = CatalogTupleValue(ctx, pg_statistic, stakind1 + i);
+ int16 v = DatumGetInt16(d);
+
+ if (first_empty < 0 && v == 0)
+ first_empty = i;
- if (first_empty < 0 &&
- DatumGetInt16(values[stakind_attnum]) == 0)
- first_empty = slotidx;
- if (DatumGetInt16(values[stakind_attnum]) == stakind)
+ if (v == stakind)
break;
}
- if (slotidx >= STATISTIC_NUM_SLOTS && first_empty >= 0)
- slotidx = first_empty;
+ if (i >= STATISTIC_NUM_SLOTS && first_empty >= 0)
+ i = first_empty;
- if (slotidx >= STATISTIC_NUM_SLOTS)
+ if (i >= STATISTIC_NUM_SLOTS)
ereport(ERROR,
- (errmsg("maximum number of statistics slots exceeded: %d",
- slotidx + 1)));
+ (errmsg("maximum number of statistics slots exceeded: %d", i + 1)));
- stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx;
- staop_attnum = Anum_pg_statistic_staop1 - 1 + slotidx;
- stacoll_attnum = Anum_pg_statistic_stacoll1 - 1 + slotidx;
+ if (DatumGetInt16(CatalogTupleValue(ctx, pg_statistic, stakind1 + i)) != stakind)
+ CatalogTupleUpdateValue(ctx, pg_statistic, stakind1 + i, Int16GetDatum(stakind));
+
+ if (DatumGetInt16(CatalogTupleValue(ctx, pg_statistic, staop1 + i)) != staop)
+ CatalogTupleUpdateValue(ctx, pg_statistic, staop1 + i, ObjectIdGetDatum(staop));
+
+ if (DatumGetInt16(CatalogTupleValue(ctx, pg_statistic, stacoll1 + i)) != stacoll)
+ CatalogTupleUpdateValue(ctx, pg_statistic, stacoll1 + i, ObjectIdGetDatum(stacoll));
- if (DatumGetInt16(values[stakind_attnum]) != stakind)
- {
- values[stakind_attnum] = Int16GetDatum(stakind);
- replaces[stakind_attnum] = true;
- }
- if (DatumGetObjectId(values[staop_attnum]) != staop)
- {
- values[staop_attnum] = ObjectIdGetDatum(staop);
- replaces[staop_attnum] = true;
- }
- if (DatumGetObjectId(values[stacoll_attnum]) != stacoll)
- {
- values[stacoll_attnum] = ObjectIdGetDatum(stacoll);
- replaces[stacoll_attnum] = true;
- }
if (!stanumbers_isnull)
- {
- values[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = stanumbers;
- nulls[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = false;
- replaces[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = true;
- }
+ CatalogTupleUpdateValue(ctx, pg_statistic, stanumbers1 + i, stanumbers);
+
if (!stavalues_isnull)
- {
- values[Anum_pg_statistic_stavalues1 - 1 + slotidx] = stavalues;
- nulls[Anum_pg_statistic_stavalues1 - 1 + slotidx] = false;
- replaces[Anum_pg_statistic_stavalues1 - 1 + slotidx] = true;
- }
+ CatalogTupleUpdateValue(ctx, pg_statistic, stavalues1 + i, stavalues);
}
/*
* Upsert the pg_statistic record.
*/
static void
-upsert_pg_statistic(Relation starel, HeapTuple oldtup,
- const Datum *values, const bool *nulls, const bool *replaces)
+upsert_pg_statistic(Relation starel, HeapTuple oldtup, void *_ctx)
{
- HeapTuple newtup;
+ CatalogUpdateValuesDecl(pg_statistic, ctx) * ctx = _ctx;
if (HeapTupleIsValid(oldtup))
- {
- newtup = heap_modify_tuple(oldtup, RelationGetDescr(starel),
- values, nulls, replaces);
- CatalogTupleUpdate(starel, &newtup->t_self, newtup);
- }
+ ModifyCatalogTupleValues(starel, oldtup, ctx);
else
- {
- newtup = heap_form_tuple(RelationGetDescr(starel), values, nulls);
- CatalogTupleInsert(starel, newtup);
- }
-
- heap_freetuple(newtup);
+ InsertCatalogTupleValues(starel, ctx);
CommandCounterIncrement();
}
@@ -884,37 +855,28 @@ delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit)
* Initialize values and nulls for a new stats tuple.
*/
static void
-init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited,
- Datum *values, bool *nulls, bool *replaces)
+init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited, void *_ctx)
{
- memset(nulls, true, sizeof(bool) * Natts_pg_statistic);
- memset(replaces, true, sizeof(bool) * Natts_pg_statistic);
+ CatalogUpdateValuesDecl(pg_statistic, ctx) * ctx = (struct _cat_pg_statistic_ctx_upd_vals *) _ctx;
- /* must initialize non-NULL attributes */
+ CatalogTupleUpdateMarkAllColumnsUpdated(ctx, pg_statistic);
+ memset(ctx->nulls, true, sizeof(bool) * Natts_pg_statistic);
- values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(reloid);
- nulls[Anum_pg_statistic_starelid - 1] = false;
- values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(attnum);
- nulls[Anum_pg_statistic_staattnum - 1] = false;
- values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(inherited);
- nulls[Anum_pg_statistic_stainherit - 1] = false;
+ /* Now we must initialize non-NULL attributes */
+ CatalogTupleUpdateValue(ctx, pg_statistic, starelid, ObjectIdGetDatum(reloid));
+ CatalogTupleUpdateValue(ctx, pg_statistic, staattnum, Int16GetDatum(attnum));
+ CatalogTupleUpdateValue(ctx, pg_statistic, stainherit, BoolGetDatum(inherited));
- values[Anum_pg_statistic_stanullfrac - 1] = DEFAULT_NULL_FRAC;
- nulls[Anum_pg_statistic_stanullfrac - 1] = false;
- values[Anum_pg_statistic_stawidth - 1] = DEFAULT_AVG_WIDTH;
- nulls[Anum_pg_statistic_stawidth - 1] = false;
- values[Anum_pg_statistic_stadistinct - 1] = DEFAULT_N_DISTINCT;
- nulls[Anum_pg_statistic_stadistinct - 1] = false;
+ CatalogTupleUpdateValue(ctx, pg_statistic, stanullfrac, DEFAULT_NULL_FRAC);
+ CatalogTupleUpdateValue(ctx, pg_statistic, stawidth, DEFAULT_AVG_WIDTH);
+ CatalogTupleUpdateValue(ctx, pg_statistic, stadistinct, DEFAULT_N_DISTINCT);
/* initialize stakind, staop, and stacoll slots */
- for (int slotnum = 0; slotnum < STATISTIC_NUM_SLOTS; slotnum++)
+ for (int i = 0; i < STATISTIC_NUM_SLOTS; i++)
{
- values[Anum_pg_statistic_stakind1 + slotnum - 1] = (Datum) 0;
- nulls[Anum_pg_statistic_stakind1 + slotnum - 1] = false;
- values[Anum_pg_statistic_staop1 + slotnum - 1] = ObjectIdGetDatum(InvalidOid);
- nulls[Anum_pg_statistic_staop1 + slotnum - 1] = false;
- values[Anum_pg_statistic_stacoll1 + slotnum - 1] = ObjectIdGetDatum(InvalidOid);
- nulls[Anum_pg_statistic_stacoll1 + slotnum - 1] = false;
+ CatalogTupleUpdateValue(ctx, pg_statistic, stakind1 + i, (Datum) 0);
+ CatalogTupleUpdateValue(ctx, pg_statistic, staop1 + i, ObjectIdGetDatum(InvalidOid));
+ CatalogTupleUpdateValue(ctx, pg_statistic, stacoll1 + i, ObjectIdGetDatum(InvalidOid));
}
}
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
index f6b766697e2..896a1e804ca 100644
--- a/src/include/access/htup.h
+++ b/src/include/access/htup.h
@@ -14,6 +14,8 @@
#ifndef HTUP_H
#define HTUP_H
+#include "catalog/pg_aggregate_d.h"
+#include "nodes/bitmapset.h"
#include "storage/itemptr.h"
/* typedefs and forward declarations for structs defined in htup_details.h */
@@ -77,6 +79,254 @@ typedef HeapTupleData *HeapTuple;
*/
#define HeapTupleIsValid(tuple) ((tuple) != NULL)
+#define HeapTupleSetValue(table_name, field, value, values) \
+ (values)[Anum_##table_name##_##field - 1] = (value)
+
+#define HeapTupleSetValueNull(table_name, field, values, nulls) \
+ do { \
+ (values)[Anum_##table_name##_##field - 1] = (Datum) 0; \
+ (nulls)[Anum_##table_name##_##field - 1] = true; \
+ } while(0)
+
+/*
+ * The following should be used when manipulating CatalogTuples for
+ * insert or update.
+ */
+
+#define CatalogInsertValuesDecl(table_name, var) \
+ struct _cat_##table_name##_##var##_ins_vals { \
+ CatalogIndexState idx; \
+ bool nulls[Natts_##table_name]; \
+ Datum values[Natts_##table_name]; \
+ }
+#define CatalogInsertValuesContext(table_name, var) \
+ CatalogInsertValuesDecl(table_name, var) _##table_name##_##var = { \
+ .idx = NULL, \
+ .nulls = {false}, \
+ .values = {0} \
+ }, *var = &_##table_name##_##var
+
+#define CatalogUpdateValuesDecl(table_name, var) \
+ struct _cat_##table_name##_##var##_upd_vals { \
+ CatalogIndexState idx; \
+ bool nulls[Natts_##table_name]; \
+ Datum values[Natts_##table_name]; \
+ Bitmapset *updated; \
+ }
+#define CatalogUpdateValuesContext(table_name, var) \
+ CatalogUpdateValuesDecl(table_name, var) _##table_name##_##var = { \
+ .idx = NULL, \
+ .nulls = {false}, \
+ .values = {0}, \
+ .updated = NULL \
+ }, *var = &_##table_name##_##var
+
+#define CatalogFormContext(table_name, var, tuple) \
+ Form_##table_name var = (Form_##table_name) GETSTRUCT(tuple)
+
+#define CatalogInsertFormDecl(table_name, var) \
+ struct _cat_##table_name##_##var##_ins_form { \
+ CatalogIndexState idx; \
+ Form_##table_name form; \
+ bool nulls[Natts_##table_name]; \
+ }
+#define CatalogInsertFormContext(table_name, var) \
+ CatalogInsertFormDecl(table_name, var) _##table_name##_##var = { \
+ .idx = NULL, \
+ .form = NULL, \
+ .nulls = {false} \
+ }, *var = &_##table_name##_##var
+
+#define CatalogUpdateFormDecl(table_name, var) \
+ struct _cat_##table_name##_##var##_upd_form { \
+ CatalogIndexState idx; \
+ Form_##table_name form; \
+ bool nulls[Natts_##table_name]; \
+ Bitmapset *updated; \
+ }
+#define CatalogUpdateFormContext(table_name, var) \
+ CatalogUpdateFormDecl(table_name, var) _##table_name##_##var = { \
+ .idx = NULL, \
+ .form = NULL, \
+ .nulls = {false}, \
+ .updated = NULL \
+ }, *var = &_##table_name##_##var
+
+#define CatalogSetForm(table_name, var, tuple) \
+ var->form = (Form_##table_name) GETSTRUCT(tuple)
+
+#define CatalogGetFormField(var, field) var->form->field
+
+#define CatalogTupleValue(var, table_name, field) \
+ var->values[Anum_##table_name##_##field - 1]
+
+#define FormCatalogTuple(relation, var) \
+ heap_form_tuple(RelationGetDescr(relation), var->values, var->nulls)
+
+#define DeformCatalogTuple(relation, tuple, var) \
+ heap_deform_tuple(tuple, RelationGetDescr(relation), var->values, var->nulls)
+
+#define ModifyCatalogTupleValues(relation, tuple, var) \
+ do { \
+ HeapTuple new; \
+ \
+ new = heap_update_tuple(tuple, RelationGetDescr(relation), \
+ var->values, var->nulls, var->updated); \
+ CatalogTupleUpdate(relation, &new->t_self, new, var->updated, var->idx); \
+ heap_freetuple(new); \
+ } while(0)
+
+#define UpdateCatalogTupleForm(relation, tuple, var) \
+ CatalogTupleUpdate(relation, &tuple->t_self, tuple, var->updated, var->idx)
+
+#define ModifyCatalogTupleForm(relation, tuple, var) \
+ do { \
+ HeapTuple new; \
+ \
+ new = heap_update_tuple(tuple, RelationGetDescr(relation), \
+ NULL, var->nulls, var->updated); \
+ CatalogTupleUpdate(relation, &new->t_self, new, var->updated, var->idx); \
+ heap_freetuple(new); \
+ } while(0)
+
+#define InsertCatalogTupleValues(relation, var) \
+ do { \
+ HeapTuple new = heap_form_tuple(RelationGetDescr(relation), \
+ var->values, var->nulls); \
+ CatalogTupleInsert(relation, new, var->idx); \
+ heap_freetuple(new); \
+ } while(0)
+
+#define CatalogTupleSetField(var, table_name, field, value) \
+ var->field = (value)
+
+#define CatalogTupleSetFieldNull(var, table_name, field) \
+ var->nulls[Anum_##table_name##_##field - 1] = true
+
+#define CatalogTupleSetValue(var, table_name, field, value) \
+ do { \
+ var->values[Anum_##table_name##_##field - 1] = (value); \
+ var->nulls[Anum_##table_name##_##field - 1] = false; \
+ } while(0)
+
+#define CatalogTupleSetValueNull(var, table_name, field) \
+ var->nulls[Anum_##table_name##_##field - 1] = true
+
+#define CatalogTupleUpdateValue(var, table_name, field, value) \
+ do { \
+ var->values[Anum_##table_name##_##field - 1] = (value); \
+ var->nulls[Anum_##table_name##_##field - 1] = false; \
+ var->updated = bms_add_member(var->updated, \
+ Anum_##table_name##_##field - \
+ FirstLowInvalidHeapAttributeNumber); \
+ } while(0)
+
+#define CatalogTupleUpdateValueNull(var, table_name, field) \
+ do { \
+ var->nulls[Anum_##table_name##_##field - 1] = true; \
+ var->updated = bms_add_member(var->updated, \
+ Anum_##table_name##_##field - \
+ FirstLowInvalidHeapAttributeNumber); \
+ } while(0)
+
+#define CatalogTupleUpdateField(var, table_name, field, value) \
+ do { \
+ var->form->field = (value); \
+ var->nulls[Anum_##table_name##_##field - 1] = false; \
+ var->updated = bms_add_member(var->updated, \
+ Anum_##table_name##_##field - \
+ FirstLowInvalidHeapAttributeNumber); \
+ } while(0)
+
+#define CatalogTupleCondUpdateField(var, table_name, field, cond_set_value, stmt) \
+ if (!(cond_set_value)) \
+ { \
+ var->nulls[Anum_##table_name##_##field - 1] = false; \
+ var->updated = bms_add_member(var->updated, \
+ Anum_##table_name##_##field - \
+ FirstLowInvalidHeapAttributeNumber); \
+ } else stmt
+
+#define CatalogTupleUpdateStrField(var, table_name, field, value) \
+ do { \
+ namestrcpy(&(var->form->field), value); \
+ var->nulls[Anum_##table_name##_##field - 1] = false; \
+ var->updated = bms_add_member(var->updated, \
+ Anum_##table_name##_##field - \
+ FirstLowInvalidHeapAttributeNumber); \
+ } while(0)
+
+#define CatalogTupleUpdateFieldNull(var, table_name, field) \
+ do { \
+ var->nulls[Anum_##table_name##_##field - 1] = true; \
+ var->updated = bms_add_member(var->updated, \
+ Anum_##table_name##_##field - \
+ FirstLowInvalidHeapAttributeNumber); \
+ } while(0)
+
+#define CatalogTupleUpdateMarkAllColumnsUpdated(var, table_name) \
+ var->updated = bms_add_range(var->updated, 1 - FirstLowInvalidHeapAttributeNumber, \
+ Natts_##table_name - FirstLowInvalidHeapAttributeNumber)
+
+#define CatalogTupleReuseUpdateContext(var) \
+ do { \
+ bms_free(var->updated); \
+ var->updated = NULL; \
+ } while(0)
+
+#define CatalogTupleHasChanged(var) (!bms_is_empty(var->updated))
+
+
+
+/* TODO BELOW */
+
+#define HeapTupleValue(table_name, field, values) \
+ (values)[Anum_##table_name##_##field - 1]
+
+#define HeapTupleSetField(table_name, field, value, form_ptr) \
+ (form_ptr)->field = (value)
+
+#define HeapTupleSetFieldNull(table_name, field, nulls) \
+ (nulls)[Anum_##table_name##_##field - 1] = true
+
+/*
+ * These are useful when forming tuples for CatalogTupleUpdate()
+ *
+ * Updated catalog tuples need to track which fields were changed when
+ * calling heap_update_tuple(), so we use a bitmap to keep track of that.
+ */
+#define HeapTupleMarkColumnUpdated(table_name, field, updated) \
+ (updated) = bms_add_member((updated), \
+ Anum_##table_name##_##field - FirstLowInvalidHeapAttributeNumber)
+
+#define HeapTupleUpdateSetAllColumnsUpdated(table_name, updated) \
+ (updated) = bms_add_range((updated), 1 - FirstLowInvalidHeapAttributeNumber, \
+ Natts_##table_name - FirstLowInvalidHeapAttributeNumber)
+
+#define HeapTupleSetColumnNotUpdated(table_name, field, updated) \
+ (updated) = bms_del_member((updated), \
+ Anum_##table_name##_##field - FirstLowInvalidHeapAttributeNumber)
+
+#define HeapTupleUpdateField(table_name, field, value, form_ptr, updated) \
+ do { \
+ (form_ptr)->field = (value); \
+ HeapTupleMarkColumnUpdated(table_name, field, updated); \
+ } while(0)
+
+#define HeapTupleUpdateValue(table_name, field, value, values, nulls, updated) \
+ do { \
+ (values)[Anum_##table_name##_##field - 1] = (Datum) (value); \
+ (nulls)[Anum_##table_name##_##field - 1] = false; \
+ HeapTupleMarkColumnUpdated(table_name, field, updated); \
+ } while(0)
+
+#define HeapTupleUpdateValueNull(table_name, field, values, nulls, updated) \
+ do { \
+ (values)[Anum_##table_name##_##field - 1] = (Datum) 0; \
+ (nulls)[Anum_##table_name##_##field - 1] = true; \
+ HeapTupleMarkColumnUpdated(table_name, field, updated); \
+ } while(0)
+
/* HeapTupleHeader functions implemented in utils/time/combocid.c */
extern CommandId HeapTupleHeaderGetCmin(const HeapTupleHeaderData *tup);
extern CommandId HeapTupleHeaderGetCmax(const HeapTupleHeaderData *tup);
diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h
index f3593acc8c2..814d764ee97 100644
--- a/src/include/access/htup_details.h
+++ b/src/include/access/htup_details.h
@@ -21,6 +21,9 @@
#include "storage/bufpage.h"
#include "varatt.h"
+/* Forward declarations */
+typedef struct Bitmapset Bitmapset;
+
/*
* MaxTupleAttributeNumber limits the number of (user) columns in a tuple.
* The key limit on this value is that the size of the fixed overhead for
@@ -835,6 +838,11 @@ extern HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple,
const int *replCols,
const Datum *replValues,
const bool *replIsnull);
+extern HeapTuple heap_update_tuple(HeapTuple tuple,
+ TupleDesc tupleDesc,
+ const Datum *replValues,
+ const bool *replIsnull,
+ const Bitmapset *replaces);
extern void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
Datum *values, bool *isnull);
extern void heap_freetuple(HeapTuple htup);
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 77c17d3fb7a..685ff3d2bd1 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -37,18 +37,13 @@ typedef struct ResultRelInfo *CatalogIndexState;
*/
extern CatalogIndexState CatalogOpenIndexes(Relation heapRel);
extern void CatalogCloseIndexes(CatalogIndexState indstate);
-extern void CatalogTupleInsert(Relation heapRel, HeapTuple tup);
-extern void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
- CatalogIndexState indstate);
-extern void CatalogTuplesMultiInsertWithInfo(Relation heapRel,
- TupleTableSlot **slot,
- int ntuples,
- CatalogIndexState indstate);
+extern void CatalogTupleInsert(Relation heapRel, HeapTuple tup,
+ CatalogIndexState indstate);
+extern void CatalogTuplesMultiInsert(Relation heapRel, TupleTableSlot **slot,
+ int ntuples, CatalogIndexState indstate);
extern void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid,
- HeapTuple tup);
-extern void CatalogTupleUpdateWithInfo(Relation heapRel,
- const ItemPointerData *otid, HeapTuple tup,
- CatalogIndexState indstate);
+ HeapTuple tuple, const struct Bitmapset *updated,
+ CatalogIndexState indstate);
extern void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid);
#endif /* INDEXING_H */
--
2.49.0
v2-0002-Update-the-remainder-of-catalog-updates-using-the.patchapplication/octet-streamDownload
From 112821d5e0a930c53f0ab236b1a0250c85d61527 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
Date: Fri, 14 Nov 2025 08:43:14 -0500
Subject: [PATCH v2 2/3] Update the remainder of catalog updates using the new
APIs
NOTE: This is a work-in-progress commit, some of the files (aclchk.c,
heap.c) have been adapted to use the proposed macros, the rest remain
unchanged and use the ealier macros.
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.
---
src/backend/catalog/aclchk.c | 166 ++----
src/backend/catalog/heap.c | 382 ++++++-------
src/backend/catalog/index.c | 227 ++++----
src/backend/catalog/partition.c | 5 +-
src/backend/catalog/pg_attrdef.c | 38 +-
src/backend/catalog/pg_cast.c | 23 +-
src/backend/catalog/pg_collation.c | 40 +-
src/backend/catalog/pg_constraint.c | 2 +-
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 | 67 +--
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 | 20 +-
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 | 69 +--
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 | 569 ++++++++++++--------
src/backend/commands/tablespace.c | 47 +-
src/backend/commands/trigger.c | 109 ++--
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 | 60 +--
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 +-
60 files changed, 2228 insertions(+), 2585 deletions(-)
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index d183f2990ce..de1ed36d0f9 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -1154,7 +1154,6 @@ SetDefaultACL(InternalDefaultACL *iacls)
Acl *def_acl;
Acl *old_acl;
Acl *new_acl;
- HeapTuple newtuple;
int noldmembers;
int nnewmembers;
Oid *oldmembers;
@@ -1315,36 +1314,30 @@ 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};
Oid defAclOid;
+ CatalogUpdateValuesContext(pg_default_acl, ctx);
+
if (isNew)
{
/* 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);
-
- newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
- CatalogTupleInsert(rel, newtuple);
+ CatalogTupleSetValue(ctx, pg_default_acl, oid, ObjectIdGetDatum(defAclOid));
+ CatalogTupleSetValue(ctx, pg_default_acl, defaclrole, ObjectIdGetDatum(iacls->roleid));
+ CatalogTupleSetValue(ctx, pg_default_acl, defaclnamespace, ObjectIdGetDatum(iacls->nspid));
+ CatalogTupleSetValue(ctx, pg_default_acl, defaclobjtype, CharGetDatum(objtype));
+ CatalogTupleSetValue(ctx, pg_default_acl, defaclacl, PointerGetDatum(new_acl));
+
+ InsertCatalogTupleValues(rel, ctx);
}
else
{
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;
-
- newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
- values, nulls, replaces);
- CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
+ CatalogTupleUpdateValue(ctx, pg_default_acl, defaclacl, PointerGetDatum(new_acl));
+ ModifyCatalogTupleValues(rel, tuple, ctx);
}
/* these dependencies don't change in an update */
@@ -1648,15 +1641,13 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
Oid grantorId;
AclMode avail_goptions;
bool need_update;
- HeapTuple newtuple;
- Datum values[Natts_pg_attribute] = {0};
- bool nulls[Natts_pg_attribute] = {0};
- bool replaces[Natts_pg_attribute] = {0};
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
+ CatalogUpdateValuesContext(pg_attribute, ctx);
+
attr_tuple = SearchSysCache2(ATTNUM,
ObjectIdGetDatum(relOid),
Int16GetDatum(attnum));
@@ -1742,22 +1733,18 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
*/
if (ACL_NUM(new_acl) > 0)
{
- values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
+ CatalogTupleUpdateValue(ctx, pg_attribute, attacl, PointerGetDatum(new_acl));
need_update = true;
}
else
{
- nulls[Anum_pg_attribute_attacl - 1] = true;
+ CatalogTupleUpdateValueNull(ctx, pg_attribute, attacl);
need_update = !isNull;
}
- replaces[Anum_pg_attribute_attacl - 1] = true;
if (need_update)
{
- newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
- values, nulls, replaces);
-
- CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
+ ModifyCatalogTupleValues(attRelation, attr_tuple, ctx);
/* Update initial privileges for extensions */
recordExtensionInitPriv(relOid, RelationRelationId, attnum,
@@ -1958,14 +1945,12 @@ ExecGrant_Relation(InternalGrant *istmt)
AclMode avail_goptions;
Acl *new_acl;
Oid grantorId;
- HeapTuple newtuple;
- Datum values[Natts_pg_class] = {0};
- bool nulls[Natts_pg_class] = {0};
- bool replaces[Natts_pg_class] = {0};
int nnewmembers;
Oid *newmembers;
ObjectType objtype;
+ CatalogUpdateValuesContext(pg_class, ctx);
+
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), this_privileges,
old_acl, ownerId,
@@ -2011,13 +1996,8 @@ 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);
-
- newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
- values, nulls, replaces);
-
- CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+ CatalogTupleUpdateValue(ctx, pg_class, relacl, PointerGetDatum(new_acl));
+ ModifyCatalogTupleValues(relation, tuple, ctx);
UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock);
/* Update initial privileges for extensions */
@@ -2140,7 +2120,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 +2194,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 CatalogTuple*() macros 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 +2220,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();
@@ -2286,10 +2270,6 @@ ExecGrant_Largeobject(InternalGrant *istmt)
Acl *new_acl;
Oid grantorId;
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};
int noldmembers;
int nnewmembers;
Oid *oldmembers;
@@ -2298,6 +2278,8 @@ ExecGrant_Largeobject(InternalGrant *istmt)
SysScanDesc scan;
HeapTuple tuple;
+ CatalogUpdateValuesContext(pg_largeobject_metadata, ctx);
+
/* There's no syscache for pg_largeobject_metadata */
ScanKeyInit(&entry[0],
Anum_pg_largeobject_metadata_oid,
@@ -2367,14 +2349,8 @@ 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);
-
- newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
- values, nulls, replaces);
-
- CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+ CatalogTupleUpdateValue(ctx, pg_largeobject_metadata, lomacl, PointerGetDatum(new_acl));
+ ModifyCatalogTupleValues(relation, tuple, ctx);
/* Update initial privileges for extensions */
recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
@@ -2524,19 +2500,11 @@ ExecGrant_Parameter(InternalGrant *istmt)
}
else
{
- /* 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};
-
- replaces[Anum_pg_parameter_acl_paracl - 1] = true;
- values[Anum_pg_parameter_acl_paracl - 1] = PointerGetDatum(new_acl);
-
- newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
- values, nulls, replaces);
+ /* finished building new ACL value, now update it */
+ CatalogUpdateValuesContext(pg_parameter_acl, ctx);
- CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+ CatalogTupleUpdateValue(ctx, pg_parameter_acl, paracl, PointerGetDatum(new_acl));
+ ModifyCatalogTupleValues(relation, tuple, ctx);
}
/* Update initial privileges for extensions */
@@ -4631,7 +4599,6 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
Relation relation;
ScanKeyData key[3];
SysScanDesc scan;
- HeapTuple tuple;
HeapTuple oldtuple;
int noldmembers;
int nnewmembers;
@@ -4666,9 +4633,6 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
/* If we find an entry, update it with the latest ACL. */
if (HeapTupleIsValid(oldtuple))
{
- Datum values[Natts_pg_init_privs] = {0};
- bool nulls[Natts_pg_init_privs] = {0};
- bool replace[Natts_pg_init_privs] = {0};
Datum oldAclDatum;
bool isNull;
Acl *old_acl;
@@ -4687,13 +4651,10 @@ 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;
-
- oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
- values, nulls, replace);
+ CatalogUpdateValuesContext(pg_init_privs, ctx);
- CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple);
+ CatalogTupleUpdateValue(ctx, pg_init_privs, initprivs, PointerGetDatum(new_acl));
+ ModifyCatalogTupleValues(relation, oldtuple, ctx);
}
else
{
@@ -4703,8 +4664,7 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
}
else
{
- Datum values[Natts_pg_init_privs] = {0};
- bool nulls[Natts_pg_init_privs] = {0};
+ CatalogInsertValuesContext(pg_init_privs, ctx);
/*
* Only add a new entry if the new ACL is non-NULL.
@@ -4715,19 +4675,15 @@ 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);
+ CatalogTupleSetValue(ctx, pg_init_privs, objoid, ObjectIdGetDatum(objoid));
+ CatalogTupleSetValue(ctx, pg_init_privs, classoid, ObjectIdGetDatum(classoid));
+ CatalogTupleSetValue(ctx, pg_init_privs, objsubid, Int32GetDatum(objsubid));
/* This function only handles initial privileges of extensions */
- values[Anum_pg_init_privs_privtype - 1] =
- CharGetDatum(INITPRIVS_EXTENSION);
-
- values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
+ CatalogTupleSetValue(ctx, pg_init_privs, privtype, CharGetDatum(INITPRIVS_EXTENSION));
+ CatalogTupleSetValue(ctx, pg_init_privs, initprivs, PointerGetDatum(new_acl));
- tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
-
- CatalogTupleInsert(relation, tuple);
+ InsertCatalogTupleValues(relation, ctx);
/* Update pg_shdepend, too. */
noldmembers = 0;
@@ -4764,7 +4720,6 @@ ReplaceRoleInInitPriv(Oid oldroleid, Oid newroleid,
bool isNull;
Acl *old_acl;
Acl *new_acl;
- HeapTuple newtuple;
int noldmembers;
int nnewmembers;
Oid *oldmembers;
@@ -4825,17 +4780,11 @@ 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};
-
/* Update existing entry. */
- values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
- replaces[Anum_pg_init_privs_initprivs - 1] = true;
+ CatalogUpdateValuesContext(pg_init_privs, ctx);
- newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel),
- values, nulls, replaces);
- CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
+ CatalogTupleUpdateValue(ctx, pg_init_privs, initprivs, PointerGetDatum(new_acl));
+ ModifyCatalogTupleValues(rel, oldtuple, ctx);
}
/*
@@ -4875,7 +4824,6 @@ RemoveRoleFromInitPriv(Oid roleid, Oid classid, Oid objid, int32 objsubid)
bool isNull;
Acl *old_acl;
Acl *new_acl;
- HeapTuple newtuple;
int noldmembers;
int nnewmembers;
Oid *oldmembers;
@@ -4961,17 +4909,11 @@ 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};
-
/* Update existing entry. */
- values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
- replaces[Anum_pg_init_privs_initprivs - 1] = true;
+ CatalogUpdateValuesContext(pg_init_privs, ctx);
- newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel),
- values, nulls, replaces);
- CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
+ CatalogTupleUpdateValue(ctx, pg_init_privs, initprivs, PointerGetDatum(new_acl));
+ ModifyCatalogTupleValues(rel, oldtuple, ctx);
}
/*
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index fd6537567ea..24a815c9784 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,63 +918,55 @@ 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];
- HeapTuple tup;
+
+ CatalogInsertValuesContext(pg_class, ctx);
/* 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);
+ CatalogTupleSetValue(ctx, pg_class, oid, ObjectIdGetDatum(new_rel_oid));
+ CatalogTupleSetValue(ctx, pg_class, relname, NameGetDatum(&rd_rel->relname));
+ CatalogTupleSetValue(ctx, pg_class, relnamespace, ObjectIdGetDatum(rd_rel->relnamespace));
+ CatalogTupleSetValue(ctx, pg_class, reltype, ObjectIdGetDatum(rd_rel->reltype));
+ CatalogTupleSetValue(ctx, pg_class, reloftype, ObjectIdGetDatum(rd_rel->reloftype));
+ CatalogTupleSetValue(ctx, pg_class, relowner, ObjectIdGetDatum(rd_rel->relowner));
+ CatalogTupleSetValue(ctx, pg_class, relam, ObjectIdGetDatum(rd_rel->relam));
+ CatalogTupleSetValue(ctx, pg_class, relfilenode, ObjectIdGetDatum(rd_rel->relfilenode));
+ CatalogTupleSetValue(ctx, pg_class, reltablespace, ObjectIdGetDatum(rd_rel->reltablespace));
+ CatalogTupleSetValue(ctx, pg_class, relpages, Int32GetDatum(rd_rel->relpages));
+ CatalogTupleSetValue(ctx, pg_class, reltuples, Float4GetDatum(rd_rel->reltuples));
+ CatalogTupleSetValue(ctx, pg_class, relallvisible, Int32GetDatum(rd_rel->relallvisible));
+ CatalogTupleSetValue(ctx, pg_class, relallfrozen, Int32GetDatum(rd_rel->relallfrozen));
+ CatalogTupleSetValue(ctx, pg_class, reltoastrelid, ObjectIdGetDatum(rd_rel->reltoastrelid));
+ CatalogTupleSetValue(ctx, pg_class, relhasindex, BoolGetDatum(rd_rel->relhasindex));
+ CatalogTupleSetValue(ctx, pg_class, relisshared, BoolGetDatum(rd_rel->relisshared));
+ CatalogTupleSetValue(ctx, pg_class, relpersistence, CharGetDatum(rd_rel->relpersistence));
+ CatalogTupleSetValue(ctx, pg_class, relkind, CharGetDatum(rd_rel->relkind));
+ CatalogTupleSetValue(ctx, pg_class, relnatts, Int16GetDatum(rd_rel->relnatts));
+ CatalogTupleSetValue(ctx, pg_class, relchecks, Int16GetDatum(rd_rel->relchecks));
+ CatalogTupleSetValue(ctx, pg_class, relhasrules, BoolGetDatum(rd_rel->relhasrules));
+ CatalogTupleSetValue(ctx, pg_class, relhastriggers, BoolGetDatum(rd_rel->relhastriggers));
+ CatalogTupleSetValue(ctx, pg_class, relrowsecurity, BoolGetDatum(rd_rel->relrowsecurity));
+ CatalogTupleSetValue(ctx, pg_class, relforcerowsecurity, BoolGetDatum(rd_rel->relforcerowsecurity));
+ CatalogTupleSetValue(ctx, pg_class, relhassubclass, BoolGetDatum(rd_rel->relhassubclass));
+ CatalogTupleSetValue(ctx, pg_class, relispopulated, BoolGetDatum(rd_rel->relispopulated));
+ CatalogTupleSetValue(ctx, pg_class, relreplident, CharGetDatum(rd_rel->relreplident));
+ CatalogTupleSetValue(ctx, pg_class, relispartition, BoolGetDatum(rd_rel->relispartition));
+ CatalogTupleSetValue(ctx, pg_class, relrewrite, ObjectIdGetDatum(rd_rel->relrewrite));
+ CatalogTupleSetValue(ctx, pg_class, relfrozenxid, TransactionIdGetDatum(rd_rel->relfrozenxid));
+ CatalogTupleSetValue(ctx, pg_class, relminmxid, MultiXactIdGetDatum(rd_rel->relminmxid));
if (relacl != (Datum) 0)
- values[Anum_pg_class_relacl - 1] = relacl;
+ CatalogTupleSetValue(ctx, pg_class, relacl, relacl);
else
- nulls[Anum_pg_class_relacl - 1] = true;
+ CatalogTupleSetValueNull(ctx, pg_class, relacl);
if (reloptions != (Datum) 0)
- values[Anum_pg_class_reloptions - 1] = reloptions;
+ CatalogTupleSetValue(ctx, pg_class, reloptions, reloptions);
else
- nulls[Anum_pg_class_reloptions - 1] = true;
+ CatalogTupleSetValueNull(ctx, pg_class, reloptions);
/* relpartbound is set by updating this tuple, if necessary */
- nulls[Anum_pg_class_relpartbound - 1] = true;
-
- tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
+ CatalogTupleSetValueNull(ctx, pg_class, relpartbound);
/* finally insert the new tuple, update the indexes, and clean up */
- CatalogTupleInsert(pg_class_desc, tup);
-
- heap_freetuple(tup);
+ InsertCatalogTupleValues(pg_class_desc, ctx);
}
/* --------------------------------
@@ -1685,11 +1681,9 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
Relation rel;
Relation attr_rel;
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};
+
+ CatalogUpdateFormContext(pg_attribute, ctx);
/*
* Grab an exclusive lock on the target table, which we will NOT release
@@ -1707,10 +1701,11 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
attnum, relid);
- attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
+
+ CatalogSetForm(pg_attribute, ctx, tuple);
/* Mark the attribute as dropped */
- attStruct->attisdropped = true;
+ CatalogTupleUpdateField(ctx, pg_attribute, attisdropped, true);
/*
* Set the type OID to invalid. A dropped attribute's type link cannot be
@@ -1720,43 +1715,35 @@ 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;
+ CatalogTupleUpdateField(ctx, pg_attribute, atttypid, InvalidOid);
/* Remove any not-null constraint the column may have */
- attStruct->attnotnull = false;
+ CatalogTupleUpdateField(ctx, pg_attribute, attnotnull, false);
/* Unset this so no one tries to look up the generation expression */
- attStruct->attgenerated = '\0';
+ CatalogTupleUpdateField(ctx, pg_attribute, attgenerated, '\0');
/*
* Change the column name to something that isn't likely to conflict
*/
snprintf(newattname, sizeof(newattname),
"........pg.dropped.%d........", attnum);
- namestrcpy(&(attStruct->attname), newattname);
+ CatalogTupleUpdateStrField(ctx, pg_attribute, attname, newattname);
/* Clear the missing value */
- attStruct->atthasmissing = false;
- nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
- replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
+ CatalogTupleUpdateField(ctx, pg_attribute, atthasmissing, false);
+ CatalogTupleUpdateFieldNull(ctx, pg_attribute, attmissingval);
/*
* 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;
+ CatalogTupleUpdateFieldNull(ctx, pg_attribute, attstattarget);
+ CatalogTupleUpdateFieldNull(ctx, pg_attribute, attacl);
+ CatalogTupleUpdateFieldNull(ctx, pg_attribute, attoptions);
+ CatalogTupleUpdateFieldNull(ctx, pg_attribute, attfdwoptions);
- tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
- valuesAtt, nullsAtt, replacesAtt);
-
- CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
+ ModifyCatalogTupleForm(attr_rel, tuple, ctx);
/*
* Because updating the pg_attribute row will trigger a relcache flush for
@@ -1765,9 +1752,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
*/
table_close(attr_rel, RowExclusiveLock);
-
RemoveStatistics(relid, attnum);
-
relation_close(rel, NoLock);
}
@@ -1967,23 +1952,13 @@ 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];
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;
+ HeapTuple tuple;
- repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
- repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
+ CatalogUpdateValuesContext(pg_attribute, ctx);
+ CatalogTupleUpdateValue(ctx, pg_attribute, atthasmissing, BoolGetDatum(false));
+ CatalogTupleUpdateValueNull(ctx, pg_attribute, attmissingval);
/* Get a lock on pg_attribute */
attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
@@ -2002,14 +1977,7 @@ 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);
-
- CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
-
- heap_freetuple(newtuple);
- }
+ ModifyCatalogTupleValues(attr_rel, tuple, ctx);
ReleaseSysCache(tuple);
}
@@ -2029,13 +1997,11 @@ 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};
Relation attrrel;
Form_pg_attribute attStruct;
- HeapTuple atttup,
- newtup;
+ HeapTuple atttup;
+
+ CatalogUpdateValuesContext(pg_attribute, ctx);
/* This is only supported for plain tables */
Assert(rel->rd_rel->relkind == RELKIND_RELATION);
@@ -2060,15 +2026,10 @@ 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;
+ CatalogTupleUpdateValue(ctx, pg_attribute, atthasmissing, BoolGetDatum(true));
+ CatalogTupleUpdateValue(ctx, pg_attribute, attmissingval, missingval);
- newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
- valuesAtt, nullsAtt, replacesAtt);
- CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
+ ModifyCatalogTupleValues(attrrel, atttup, ctx);
/* clean up */
ReleaseSysCache(atttup);
@@ -2085,15 +2046,13 @@ 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 missingval;
Form_pg_attribute attStruct;
Relation attrrel,
tablerel;
- HeapTuple atttup,
- newtup;
+ HeapTuple atttup;
+
+ CatalogUpdateValuesContext(pg_attribute, ctx);
/* lock the table the attribute belongs to */
tablerel = table_open(relid, AccessExclusiveLock);
@@ -2120,14 +2079,10 @@ 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;
+ CatalogTupleUpdateValue(ctx, pg_attribute, atthasmissing, BoolGetDatum(true));
+ CatalogTupleUpdateValue(ctx, pg_attribute, attmissingval, missingval);
- newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
- valuesAtt, nullsAtt, replacesAtt);
- CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
+ ModifyCatalogTupleValues(attrrel, atttup, ctx);
/* clean up */
ReleaseSysCache(atttup);
@@ -2720,6 +2675,8 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
ScanKeyData skey[3];
HeapTuple tup;
+ CatalogUpdateFormContext(pg_constraint, ctx);
+
/* Search for a pg_constraint entry with same name and relation */
conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
@@ -2825,7 +2782,7 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
ccname)));
tup = heap_copytuple(tup);
- con = (Form_pg_constraint) GETSTRUCT(tup);
+ CatalogSetForm(pg_constraint, ctx, tup);
/*
* In case of partitions, an inherited constraint must be inherited
@@ -2834,24 +2791,26 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
*/
if (rel->rd_rel->relispartition)
{
- con->coninhcount = 1;
- con->conislocal = false;
+ CatalogTupleUpdateField(ctx, pg_constraint, coninhcount, 1);
+ CatalogTupleUpdateField(ctx, pg_constraint, conislocal, false);
}
else
{
if (is_local)
- con->conislocal = true;
- else if (pg_add_s16_overflow(con->coninhcount, 1,
- &con->coninhcount))
- ereport(ERROR,
- errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("too many inheritance parents"));
+ CatalogTupleUpdateField(ctx, pg_constraint, conislocal, true);
+ else
+ CatalogTupleCondUpdateField(ctx, pg_constraint, coninhcount,
+ pg_add_s16_overflow(CatalogGetFormField(ctx, coninhcount), 1,
+ &CatalogGetFormField(ctx, coninhcount)),
+ ereport(ERROR,
+ errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("too many inheritance parents")));
}
if (is_no_inherit)
{
Assert(is_local);
- con->connoinherit = true;
+ CatalogTupleUpdateField(ctx, pg_constraint, connoinherit, true);
}
/*
@@ -2863,11 +2822,11 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
if (is_enforced && !con->conenforced)
{
Assert(is_local);
- con->conenforced = true;
- con->convalidated = true;
+ CatalogTupleUpdateField(ctx, pg_constraint, conenforced, true);
+ CatalogTupleUpdateField(ctx, pg_constraint, convalidated, true);
}
- CatalogTupleUpdate(conDesc, &tup->t_self, tup);
+ UpdateCatalogTupleForm(conDesc, tup, ctx);
}
systable_endscan(conscan);
@@ -3147,7 +3106,8 @@ SetRelationNumChecks(Relation rel, int numchecks)
{
Relation relrel;
HeapTuple reltup;
- Form_pg_class relStruct;
+
+ CatalogUpdateFormContext(pg_class, ctx);
relrel = table_open(RelationRelationId, RowExclusiveLock);
reltup = SearchSysCacheCopy1(RELOID,
@@ -3155,13 +3115,12 @@ SetRelationNumChecks(Relation rel, int numchecks)
if (!HeapTupleIsValid(reltup))
elog(ERROR, "cache lookup failed for relation %u",
RelationGetRelid(rel));
- relStruct = (Form_pg_class) GETSTRUCT(reltup);
+ CatalogSetForm(pg_class, ctx, reltup);
- if (relStruct->relchecks != numchecks)
+ if (CatalogGetFormField(ctx, relchecks) != numchecks)
{
- relStruct->relchecks = numchecks;
-
- CatalogTupleUpdate(relrel, &reltup->t_self, reltup);
+ CatalogTupleUpdateField(ctx, pg_class, relchecks, numchecks);
+ UpdateCatalogTupleForm(relrel, reltup, ctx);
}
else
{
@@ -3470,7 +3429,7 @@ CopyStatistics(Oid fromrelid, Oid torelid)
if (indstate == NULL)
indstate = CatalogOpenIndexes(statrel);
- CatalogTupleInsertWithInfo(statrel, tup, indstate);
+ CatalogTupleInsert(statrel, tup, indstate);
heap_freetuple(tup);
}
@@ -3905,13 +3864,12 @@ StorePartitionKey(Relation rel,
oidvector *partcollation_vec;
Datum partexprDatum;
Relation pg_partitioned_table;
- HeapTuple tuple;
- Datum values[Natts_pg_partitioned_table];
- bool nulls[Natts_pg_partitioned_table] = {0};
ObjectAddress myself;
ObjectAddress referenced;
ObjectAddresses *addrs;
+ CatalogInsertValuesContext(pg_partitioned_table, ctx);
+
Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
/* Copy the partition attribute numbers, opclass OIDs into arrays */
@@ -3935,20 +3893,19 @@ StorePartitionKey(Relation rel,
/* Only this can ever be NULL */
if (!partexprDatum)
- nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
-
- 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;
+ CatalogTupleSetValueNull(ctx, pg_partitioned_table, partexprs);
+ else
+ CatalogTupleSetValue(ctx, pg_partitioned_table, partexprs, partexprDatum);
- tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
+ CatalogTupleSetValue(ctx, pg_partitioned_table, partrelid, ObjectIdGetDatum(RelationGetRelid(rel)));
+ CatalogTupleSetValue(ctx, pg_partitioned_table, partstrat, CharGetDatum(strategy));
+ CatalogTupleSetValue(ctx, pg_partitioned_table, partnatts, Int16GetDatum(partnatts));
+ CatalogTupleSetValue(ctx, pg_partitioned_table, partdefid, ObjectIdGetDatum(InvalidOid));
+ CatalogTupleSetValue(ctx, pg_partitioned_table, partattrs, PointerGetDatum(partattrs_vec));
+ CatalogTupleSetValue(ctx, pg_partitioned_table, partclass, PointerGetDatum(partopclass_vec));
+ CatalogTupleSetValue(ctx, pg_partitioned_table, partcollation, PointerGetDatum(partcollation_vec));
- CatalogTupleInsert(pg_partitioned_table, tuple);
+ InsertCatalogTupleValues(pg_partitioned_table, ctx);
table_close(pg_partitioned_table, RowExclusiveLock);
/* Mark this relation as dependent on a few things as follows */
@@ -4050,13 +4007,11 @@ void
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];
+ HeapTuple tuple;
Oid defaultPartOid;
+ CatalogUpdateValuesContext(pg_class, ctx);
+
/* Update pg_class tuple */
classRel = table_open(RelationRelationId, RowExclusiveLock);
tuple = SearchSysCacheCopy1(RELOID,
@@ -4065,12 +4020,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 +4036,19 @@ 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);
+ CatalogTupleUpdateValue(ctx, pg_class, relpartbound, CStringGetTextDatum(nodeToString(bound)));
+
/* Also set the flag */
- ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
+ CatalogTupleUpdateValue(ctx, pg_class, relispartition, true);
/*
* 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;
+ CatalogTupleUpdateValue(ctx, pg_class, relhassubclass, false);
- CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
- heap_freetuple(newtuple);
+ ModifyCatalogTupleValues(classRel, tuple, ctx);
table_close(classRel, RowExclusiveLock);
/*
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 5d9db167e59..5e51a8b9e9a 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -579,18 +579,16 @@ UpdateIndexRelation(Oid indexoid,
int2vector *indoption;
Datum exprsDatum;
Datum predDatum;
- Datum values[Natts_pg_index];
- bool nulls[Natts_pg_index] = {0};
Relation pg_index;
- HeapTuple tuple;
- int i;
+
+ CatalogInsertValuesContext(pg_index, ctx);
/*
* Copy the index key, opclass, and indoption info into arrays (should we
* make the caller pass them like this to start with?)
*/
indkey = buildint2vector(NULL, indexInfo->ii_NumIndexAttrs);
- for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+ for (int i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
indkey->values[i] = indexInfo->ii_IndexAttrNumbers[i];
indcollation = buildoidvector(collationOids, indexInfo->ii_NumIndexKeyAttrs);
indclass = buildoidvector(opclassOids, indexInfo->ii_NumIndexKeyAttrs);
@@ -625,53 +623,45 @@ UpdateIndexRelation(Oid indexoid,
else
predDatum = (Datum) 0;
-
- /*
- * open the system catalog index relation
- */
+ /* Open the system catalog index relation */
pg_index = table_open(IndexRelationId, RowExclusiveLock);
- /*
- * 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;
+ /* Build a pg_index tuple */
+ CatalogTupleSetValue(ctx, pg_index, indexrelid, ObjectIdGetDatum(indexoid));
+ CatalogTupleSetValue(ctx, pg_index, indrelid, ObjectIdGetDatum(heapoid));
+ CatalogTupleSetValue(ctx, pg_index, indnatts, Int16GetDatum(indexInfo->ii_NumIndexAttrs));
+ CatalogTupleSetValue(ctx, pg_index, indnkeyatts, Int16GetDatum(indexInfo->ii_NumIndexKeyAttrs));
+ CatalogTupleSetValue(ctx, pg_index, indisunique, BoolGetDatum(indexInfo->ii_Unique));
+ CatalogTupleSetValue(ctx, pg_index, indnullsnotdistinct, BoolGetDatum(indexInfo->ii_NullsNotDistinct));
+ CatalogTupleSetValue(ctx, pg_index, indisprimary, BoolGetDatum(primary));
+ CatalogTupleSetValue(ctx, pg_index, indisexclusion, BoolGetDatum(isexclusion));
+ CatalogTupleSetValue(ctx, pg_index, indimmediate, BoolGetDatum(immediate));
+ CatalogTupleSetValue(ctx, pg_index, indisclustered, BoolGetDatum(false));
+ CatalogTupleSetValue(ctx, pg_index, indisvalid, BoolGetDatum(isvalid));
+ CatalogTupleSetValue(ctx, pg_index, indcheckxmin, BoolGetDatum(false));
+ CatalogTupleSetValue(ctx, pg_index, indisready, BoolGetDatum(isready));
+ CatalogTupleSetValue(ctx, pg_index, indislive, BoolGetDatum(true));
+ CatalogTupleSetValue(ctx, pg_index, indisreplident, BoolGetDatum(false));
+ CatalogTupleSetValue(ctx, pg_index, indkey, PointerGetDatum(indkey));
+ CatalogTupleSetValue(ctx, pg_index, indcollation, PointerGetDatum(indcollation));
+ CatalogTupleSetValue(ctx, pg_index, indclass, PointerGetDatum(indclass));
+ CatalogTupleSetValue(ctx, pg_index, indoption, PointerGetDatum(indoption));
+
if (exprsDatum == (Datum) 0)
- nulls[Anum_pg_index_indexprs - 1] = true;
- values[Anum_pg_index_indpred - 1] = predDatum;
+ CatalogTupleSetValueNull(ctx, pg_index, indexprs);
+ else
+ CatalogTupleSetValue(ctx, pg_index, indexprs, exprsDatum);
+
if (predDatum == (Datum) 0)
- nulls[Anum_pg_index_indpred - 1] = true;
+ CatalogTupleSetValueNull(ctx, pg_index, indpred);
+ else
+ CatalogTupleSetValue(ctx, pg_index, indpred, predDatum);
- tuple = heap_form_tuple(RelationGetDescr(pg_index), values, nulls);
+ /* Insert the tuple into the pg_index catalog */
+ InsertCatalogTupleValues(pg_index, ctx);
- /*
- * insert the tuple into the pg_index catalog
- */
- CatalogTupleInsert(pg_index, tuple);
-
- /*
- * close the relation and free the tuple
- */
+ /* Close the relation and free the tuple */
table_close(pg_index, RowExclusiveLock);
- heap_freetuple(tuple);
}
@@ -1559,17 +1549,19 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
newClassRel;
HeapTuple oldClassTuple,
newClassTuple;
- Form_pg_class oldClassForm,
- newClassForm;
HeapTuple oldIndexTuple,
newIndexTuple;
- Form_pg_index oldIndexForm,
- newIndexForm;
bool isPartition;
Oid indexConstraintOid;
List *constraintOids = NIL;
ListCell *lc;
+ CatalogUpdateFormContext(pg_class, old_class);
+ CatalogUpdateFormContext(pg_class, new_class);
+
+ CatalogUpdateFormContext(pg_index, old_idx);
+ CatalogUpdateFormContext(pg_index, new_idx);
+
/*
* Take a necessary lock on the old and new index before swapping them.
*/
@@ -1588,20 +1580,20 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
if (!HeapTupleIsValid(newClassTuple))
elog(ERROR, "could not find tuple for relation %u", newIndexId);
- oldClassForm = (Form_pg_class) GETSTRUCT(oldClassTuple);
- newClassForm = (Form_pg_class) GETSTRUCT(newClassTuple);
+ CatalogSetForm(pg_class, old_class, oldClassTuple);
+ CatalogSetForm(pg_class, new_class, newClassTuple);
/* Swap the names */
- namestrcpy(&newClassForm->relname, NameStr(oldClassForm->relname));
- namestrcpy(&oldClassForm->relname, oldName);
+ CatalogTupleUpdateStrField(new_class, pg_class, relname, NameStr(CatalogGetFormField(old_class, relname)));
+ CatalogTupleUpdateStrField(old_class, pg_class, relname, oldName);
/* Swap the partition flags to track inheritance properly */
- isPartition = newClassForm->relispartition;
- newClassForm->relispartition = oldClassForm->relispartition;
- oldClassForm->relispartition = isPartition;
+ isPartition = CatalogGetFormField(new_class, relispartition);
+ CatalogTupleUpdateField(new_class, pg_class, relispartition, CatalogGetFormField(old_class, relispartition));
+ CatalogTupleUpdateField(old_class, pg_class, relispartition, isPartition);
- CatalogTupleUpdate(pg_class, &oldClassTuple->t_self, oldClassTuple);
- CatalogTupleUpdate(pg_class, &newClassTuple->t_self, newClassTuple);
+ ModifyCatalogTupleForm(pg_class, oldClassTuple, old_class);
+ ModifyCatalogTupleForm(pg_class, newClassTuple, new_class);
heap_freetuple(oldClassTuple);
heap_freetuple(newClassTuple);
@@ -1618,37 +1610,37 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
if (!HeapTupleIsValid(newIndexTuple))
elog(ERROR, "could not find tuple for relation %u", newIndexId);
- oldIndexForm = (Form_pg_index) GETSTRUCT(oldIndexTuple);
- newIndexForm = (Form_pg_index) GETSTRUCT(newIndexTuple);
+ CatalogSetForm(pg_index, old_idx, oldIndexTuple);
+ CatalogSetForm(pg_index, new_idx, newIndexTuple);
/*
* 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;
+ CatalogTupleUpdateField(new_idx, pg_index, indisprimary, CatalogGetFormField(old_idx, indisprimary));
+ CatalogTupleUpdateField(old_idx, pg_index, indisprimary, false);
+ CatalogTupleUpdateField(new_idx, pg_index, indisexclusion, CatalogGetFormField(old_idx, indisexclusion));
+ CatalogTupleUpdateField(old_idx, pg_index, indisexclusion, false);
+ CatalogTupleUpdateField(new_idx, pg_index, indimmediate, CatalogGetFormField(old_idx, indimmediate));
+ CatalogTupleUpdateField(old_idx, pg_index, indimmediate, true);
/* Preserve indisreplident in the new index */
- newIndexForm->indisreplident = oldIndexForm->indisreplident;
+ CatalogTupleUpdateField(new_idx, pg_index, indisreplident, CatalogGetFormField(old_idx, indisreplident));
/* Preserve indisclustered in the new index */
- newIndexForm->indisclustered = oldIndexForm->indisclustered;
+ CatalogTupleUpdateField(new_idx, pg_index, indisclustered, CatalogGetFormField(old_idx, indisclustered));
/*
* 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;
+ CatalogTupleUpdateField(new_idx, pg_index, indisvalid, true);
+ CatalogTupleUpdateField(old_idx, pg_index, indisvalid, false);
+ CatalogTupleUpdateField(old_idx, pg_index, indisclustered, false);
+ CatalogTupleUpdateField(old_idx, pg_index, indisreplident, false);
- CatalogTupleUpdate(pg_index, &oldIndexTuple->t_self, oldIndexTuple);
- CatalogTupleUpdate(pg_index, &newIndexTuple->t_self, newIndexTuple);
+ ModifyCatalogTupleForm(pg_index, oldIndexTuple, old_idx);
+ ModifyCatalogTupleForm(pg_index, newIndexTuple, new_idx);
heap_freetuple(oldIndexTuple);
heap_freetuple(newIndexTuple);
@@ -1671,24 +1663,24 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
{
HeapTuple constraintTuple,
triggerTuple;
- Form_pg_constraint conForm;
ScanKeyData key[1];
SysScanDesc scan;
Oid constraintOid = lfirst_oid(lc);
+ CatalogUpdateFormContext(pg_constraint, con);
+
/* Move the constraint from the old to the new index */
constraintTuple = SearchSysCacheCopy1(CONSTROID,
ObjectIdGetDatum(constraintOid));
if (!HeapTupleIsValid(constraintTuple))
elog(ERROR, "could not find tuple for constraint %u", constraintOid);
- conForm = ((Form_pg_constraint) GETSTRUCT(constraintTuple));
+ CatalogSetForm(pg_constraint, con, constraintTuple);
- if (conForm->conindid == oldIndexId)
+ if (CatalogGetFormField(con, conindid) == oldIndexId)
{
- conForm->conindid = newIndexId;
-
- CatalogTupleUpdate(pg_constraint, &constraintTuple->t_self, constraintTuple);
+ CatalogTupleUpdateField(con, pg_constraint, conindid, newIndexId);
+ ModifyCatalogTupleForm(pg_constraint, constraintTuple, con);
}
heap_freetuple(constraintTuple);
@@ -1704,20 +1696,18 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
while (HeapTupleIsValid((triggerTuple = systable_getnext(scan))))
{
- Form_pg_trigger tgForm = (Form_pg_trigger) GETSTRUCT(triggerTuple);
+ CatalogUpdateFormContext(pg_trigger, trg);
+ CatalogSetForm(pg_trigger, trg, triggerTuple);
- if (tgForm->tgconstrindid != oldIndexId)
+ if (CatalogGetFormField(trg, tgconstrindid) != oldIndexId)
continue;
/* Make a modifiable copy */
triggerTuple = heap_copytuple(triggerTuple);
- tgForm = (Form_pg_trigger) GETSTRUCT(triggerTuple);
-
- tgForm->tgconstrindid = newIndexId;
+ CatalogSetForm(pg_trigger, trg, triggerTuple);
- CatalogTupleUpdate(pg_trigger, &triggerTuple->t_self, triggerTuple);
-
- heap_freetuple(triggerTuple);
+ CatalogTupleUpdateField(trg, pg_trigger, tgconstrindid, newIndexId);
+ ModifyCatalogTupleForm(pg_trigger, triggerTuple, trg);
}
systable_endscan(scan);
@@ -1729,14 +1719,12 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
{
Relation description;
ScanKeyData skey[3];
- SysScanDesc sd;
HeapTuple tuple;
- Datum values[Natts_pg_description] = {0};
- bool nulls[Natts_pg_description] = {0};
- bool replaces[Natts_pg_description] = {0};
+ SysScanDesc sd;
+
+ CatalogUpdateValuesContext(pg_description, des);
- values[Anum_pg_description_objoid - 1] = ObjectIdGetDatum(newIndexId);
- replaces[Anum_pg_description_objoid - 1] = true;
+ CatalogTupleUpdateValue(des, pg_description, objoid, ObjectIdGetDatum(newIndexId));
ScanKeyInit(&skey[0],
Anum_pg_description_objoid,
@@ -1758,10 +1746,7 @@ 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);
-
+ ModifyCatalogTupleValues(description, tuple, des);
break; /* Assume there can be only one match */
}
@@ -2061,6 +2046,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 +2058,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 +2088,7 @@ index_constraint_create(Relation heapRelation,
heap_freetuple(indexTuple);
table_close(pg_index, RowExclusiveLock);
+ bms_free(updated);
}
return myself;
@@ -3130,6 +3117,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 +3130,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 +3494,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 +3513,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 +3537,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 +3553,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 +3841,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 +3858,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 +3877,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..865980213da 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
@@ -215,6 +212,7 @@ RemoveAttrDefaultById(Oid attrdefId)
HeapTuple tuple;
Oid myrelid;
AttrNumber myattnum;
+ Bitmapset *updated = NULL;
/* Grab an appropriate lock on the pg_attrdef relation */
attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
@@ -255,8 +253,8 @@ RemoveAttrDefaultById(Oid attrdefId)
myattnum, myrelid);
((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
-
- CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
+ HeapTupleMarkColumnUpdated(pg_attribute, atthasdef, updated);
+ CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple, updated, 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..d70c762e435 100644
--- a/src/backend/catalog/pg_cast.c
+++ b/src/backend/catalog/pg_cast.c
@@ -14,6 +14,7 @@
*/
#include "postgres.h"
+#include "access/htup.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "catalog/catalog.h"
@@ -53,12 +54,12 @@ CastCreate(Oid sourcetypeid, Oid targettypeid,
Relation relation;
HeapTuple tuple;
Oid castid;
- Datum values[Natts_pg_cast];
- bool nulls[Natts_pg_cast] = {0};
ObjectAddress myself,
referenced;
ObjectAddresses *addrs;
+ CatalogInsertValuesContext(pg_cast, ctx);
+
relation = table_open(CastRelationId, RowExclusiveLock);
/*
@@ -78,16 +79,14 @@ 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);
-
- tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
+ CatalogTupleSetValue(ctx, pg_cast, oid, ObjectIdGetDatum(castid));
+ CatalogTupleSetValue(ctx, pg_cast, castsource, ObjectIdGetDatum(sourcetypeid));
+ CatalogTupleSetValue(ctx, pg_cast, casttarget, ObjectIdGetDatum(targettypeid));
+ CatalogTupleSetValue(ctx, pg_cast, castfunc, ObjectIdGetDatum(funcid));
+ CatalogTupleSetValue(ctx, pg_cast, castcontext, CharGetDatum(castcontext));
+ CatalogTupleSetValue(ctx, pg_cast, castmethod, CharGetDatum(castmethod));
- CatalogTupleInsert(relation, tuple);
+ InsertCatalogTupleValues(relation, ctx);
addrs = new_object_addresses();
@@ -130,8 +129,6 @@ CastCreate(Oid sourcetypeid, Oid targettypeid,
/* Post creation hook for new cast */
InvokeObjectPostCreateHook(CastRelationId, castid, 0);
- heap_freetuple(tuple);
-
table_close(relation, RowExclusiveLock);
return myself;
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_constraint.c b/src/backend/catalog/pg_constraint.c
index d09daad0b1b..30d4f7f45e8 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -769,7 +769,7 @@ AdjustNotNullInheritance(Oid relid, AttrNumber attnum,
if (!is_local)
{
- CatalogTupleCondUpdateValue(ctx, pg_constraint, coninhcount,
+ CatalogTupleCondUpdateField(ctx, pg_constraint, coninhcount,
pg_add_s16_overflow(CatalogGetFormField(ctx, coninhcount), 1,
&CatalogGetFormField(ctx, coninhcount)),
ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
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 d608f37d361..c582ee83adc 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"
@@ -135,9 +136,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;
@@ -318,67 +319,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);
@@ -579,13 +574,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;
@@ -599,18 +594,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 0994220c53d..01721916514 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..732d1e54098 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -266,38 +266,41 @@ shdepChangeDep(Relation sdepRel,
}
else if (oldtup)
{
+ Bitmapset *updated = NULL;
+
/* Need to update existing entry */
Form_pg_shdepend shForm = (Form_pg_shdepend) GETSTRUCT(oldtup);
/* Since oldtup is a copy, we can just modify it in-memory */
shForm->refclassid = refclassid;
+ HeapTupleMarkColumnUpdated(pg_shdepend, refclassid, updated);
shForm->refobjid = refobjid;
+ HeapTupleMarkColumnUpdated(pg_shdepend, refobjid, updated);
- CatalogTupleUpdate(sdepRel, &oldtup->t_self, oldtup);
+ CatalogTupleUpdate(sdepRel, &oldtup->t_self, oldtup, updated, NULL);
+ bms_free(updated);
}
else
{
/* Need to insert new entry */
- Datum values[Natts_pg_shdepend];
- bool nulls[Natts_pg_shdepend];
-
- memset(nulls, false, sizeof(nulls));
+ Datum values[Natts_pg_shdepend] = {0};
+ bool nulls[Natts_pg_shdepend] = {false};
- 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 +958,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 +972,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 +1075,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 +1090,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..c3d8c86c05c 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;
@@ -459,6 +460,7 @@ AlterCollation(AlterCollationStmt *stmt)
datum = SysCacheGetAttrNotNull(COLLOID, tup, Anum_pg_collation_collcollate);
else
datum = SysCacheGetAttrNotNull(COLLOID, tup, Anum_pg_collation_colllocale);
+ HeapTupleMarkColumnUpdated(pg_collation, collcollate, updated);
newversion = get_collation_actual_version(collForm->collprovider,
TextDatumGetCString(datum));
@@ -468,29 +470,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 +493,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 ebc204c4462..597207f0e27 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 59d00638ee6..818babacbbe 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1377,6 +1377,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);
@@ -1425,14 +1426,25 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
}
if (volatility_item)
+ {
procForm->provolatile = interpret_func_volatility(volatility_item);
+ HeapTupleMarkColumnUpdated(pg_proc, provolatile, updated);
+ }
+
if (strict_item)
+ {
procForm->proisstrict = boolVal(strict_item->arg);
+ HeapTupleMarkColumnUpdated(pg_proc, proisstrict, updated);
+ }
if (security_def_item)
+ {
procForm->prosecdef = boolVal(security_def_item->arg);
+ HeapTupleMarkColumnUpdated(pg_proc, prosecdef, updated);
+ }
if (leakproof_item)
{
procForm->proleakproof = boolVal(leakproof_item->arg);
+ HeapTupleMarkColumnUpdated(pg_proc, proleakproof, updated);
if (procForm->proleakproof && !superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -1441,6 +1453,7 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
if (cost_item)
{
procForm->procost = defGetNumeric(cost_item);
+ HeapTupleMarkColumnUpdated(pg_proc, procost, updated);
if (procForm->procost <= 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1449,6 +1462,7 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
if (rows_item)
{
procForm->prorows = defGetNumeric(rows_item);
+ HeapTupleMarkColumnUpdated(pg_proc, prorows, updated);
if (procForm->prorows <= 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1483,17 +1497,20 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
}
procForm->prosupport = newsupport;
+ HeapTupleMarkColumnUpdated(pg_proc, prosupport, updated);
}
if (parallel_item)
+ {
procForm->proparallel = interpret_func_parallel(parallel_item);
+ HeapTupleMarkColumnUpdated(pg_proc, proparallel, updated);
+ }
if (set_items)
{
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);
@@ -1503,27 +1520,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);
@@ -1840,9 +1849,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;
@@ -1943,10 +1952,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);
@@ -1964,11 +1973,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);
@@ -1978,9 +1984,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;
}
@@ -2022,6 +2028,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 a8033be4bff..186d5f2dbf5 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);
@@ -4579,6 +4583,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));
@@ -4586,8 +4592,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 51567994126..3f3eca34179 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -125,8 +125,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;
/*
@@ -221,17 +221,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);
@@ -444,6 +444,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,
@@ -525,8 +526,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 77b1a6e2dc5..a041056b38f 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;
@@ -531,22 +531,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);
@@ -642,9 +642,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;
@@ -719,23 +719,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);
@@ -746,6 +739,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 8c856af3493..7c8a3486ea7 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 07e5b95782e..831d93c228e 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,10 @@ 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);
+ HeapTupleMarkColumnUpdated(pg_attribute, attname, updated);
+ CatalogTupleUpdate(attrelation, &atttup->t_self, atttup, updated, NULL);
+ bms_free(updated);
InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum);
@@ -4267,6 +4279,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 +4325,12 @@ 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);
+ HeapTupleMarkColumnUpdated(pg_class, relname, updated);
+ CatalogTupleUpdate(relrelation, &otid, reltup, updated, NULL);
+ bms_free(updated);
+
UnlockTuple(relrelation, &otid, InplaceUpdateTupleLock);
InvokeObjectPostAlterHookArg(RelationRelationId, myrelid, 0,
@@ -4357,6 +4373,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 +4385,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 +7242,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 +7302,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 +7406,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 +7873,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 +7887,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 +7968,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 +7992,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 +8016,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 +8265,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 +8346,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 +8461,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 +8520,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 +8569,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 +8833,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 +8887,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 +8941,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 +9046,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 +9086,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 +9118,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 +9189,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 +9224,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 +9244,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 +9261,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 +9455,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 +9472,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 +12689,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 +12749,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 +12776,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 +12898,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 +12908,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 +12917,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 +13049,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 +13146,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 +13179,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 +13253,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 +13283,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 +13360,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 +14242,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 +14379,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 +14399,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 +14817,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 +14994,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 +15013,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 +15102,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
RelationGetRelid(rel), attnum);
/* Cleanup */
+ bms_free(updated);
heap_freetuple(heapTup);
return address;
@@ -15956,9 +16038,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 +16082,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 +16097,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 +16117,7 @@ ATExecAlterColumnGenericOptions(Relation rel,
table_close(attrel, RowExclusiveLock);
+ bms_free(updated);
heap_freetuple(newtuple);
return address;
@@ -16169,13 +16244,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 +16278,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 +16291,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 +16390,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 +16410,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 +16589,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 +16607,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 +16666,7 @@ ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId)
InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
+ bms_free(updated);
heap_freetuple(tuple);
table_close(pg_class, RowExclusiveLock);
}
@@ -16643,9 +16714,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 +16818,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 +16876,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 +17566,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 +17651,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 +17661,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 +17729,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 +17838,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 +17848,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 +17957,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 +17972,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 +18068,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 +18083,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 +18152,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 +18198,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 +18311,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 +18417,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 +18445,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 +18466,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 +18511,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 +18528,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 +18542,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 +18551,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 +18570,7 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid,
*/
CacheInvalidateRelcache(rel);
}
+ bms_free(updated);
heap_freetuple(pg_index_tuple);
}
@@ -18596,6 +18700,7 @@ ATExecSetRowSecurity(Relation rel, bool rls)
Relation pg_class;
Oid relid;
HeapTuple tuple;
+ Bitmapset *updated = NULL;
relid = RelationGetRelid(rel);
@@ -18607,13 +18712,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 +18732,7 @@ ATExecForceNoForceRowSecurity(Relation rel, bool force_rls)
Relation pg_class;
Oid relid;
HeapTuple tuple;
+ Bitmapset *updated = NULL;
relid = RelationGetRelid(rel);
@@ -18636,13 +18743,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 +18765,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 +18787,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 +18802,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 +18824,7 @@ ATExecGenericOptions(Relation rel, List *options)
table_close(ftrel, RowExclusiveLock);
+ bms_free(updated);
heap_freetuple(tuple);
}
@@ -18743,6 +18846,7 @@ ATExecSetCompression(Relation rel,
char *compression;
char cmethod;
ObjectAddress address;
+ Bitmapset *updated = NULL;
compression = strVal(newValue);
@@ -18771,8 +18875,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 +18891,7 @@ ATExecSetCompression(Relation rel,
true, cmethod,
lockmode);
+ bms_free(updated);
heap_freetuple(tuple);
table_close(attrel, RowExclusiveLock);
@@ -19050,6 +19155,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 +19189,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 +21184,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 +21436,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 +21862,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 +21915,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..2678dfe3f70 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);
@@ -1632,8 +1631,8 @@ renametrig_internal(Relation tgrel, Relation targetrel, HeapTuple trigtup,
RelationGetRelationName(targetrel)));
namestrcpy(&tgform->tgname, newname);
-
- CatalogTupleUpdate(tgrel, &tuple->t_self, tuple);
+ HeapTupleMarkColumnUpdated(pg_trigger, tgname, updated);
+ 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 47d5047fe8b..eb20b251f55 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -2623,9 +2623,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;
@@ -2673,10 +2673,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
{
@@ -2691,27 +2689,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,
@@ -2731,6 +2723,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
/* Clean up */
table_close(rel, RowExclusiveLock);
heap_freetuple(newtuple);
+ bms_free(updated);
return address;
}
@@ -2751,6 +2744,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);
@@ -2806,9 +2800,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);
@@ -2817,6 +2811,7 @@ AlterDomainNotNull(List *names, bool notNull)
/* Clean up */
heap_freetuple(tup);
table_close(typrel, RowExclusiveLock);
+ bms_free(updated);
return address;
}
@@ -2842,6 +2837,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);
@@ -2885,8 +2881,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;
@@ -2925,6 +2921,7 @@ AlterDomainDropConstraint(List *names, const char *constrName,
/* Clean up */
table_close(rel, RowExclusiveLock);
+ bms_free(updated);
return address;
}
@@ -2946,6 +2943,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);
@@ -3014,14 +3012,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;
}
@@ -3048,6 +3047,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);
@@ -3113,8 +3113,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);
@@ -3128,6 +3128,7 @@ AlterDomainValidateConstraint(List *names, const char *constrName)
table_close(conrel, RowExclusiveLock);
ReleaseSysCache(tup);
+ bms_free(updated);
return address;
}
@@ -4002,9 +4003,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;
@@ -4016,11 +4017,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,
@@ -4031,14 +4028,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))
@@ -4059,6 +4054,7 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
/* Clean up */
table_close(rel, RowExclusiveLock);
+ bms_free(updated);
}
/*
@@ -4179,6 +4175,7 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,
Oid arrayOid;
bool isCompositeType;
ObjectAddress thisobj;
+ Bitmapset *updated = NULL;
/*
* Make sure we haven't moved this object previously.
@@ -4244,9 +4241,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);
}
/*
@@ -4310,6 +4307,7 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,
true, /* errorOnTableType */
objsMoved);
+ bms_free(updated);
return oldNspOid;
}
@@ -4577,9 +4575,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];
@@ -4589,50 +4587,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,
@@ -4717,4 +4690,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 2380f369578..8095ad31747 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 fa8e3bf969a..495345feed9 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -1652,9 +1652,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 ||
@@ -1667,19 +1667,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..9cd3e35d948 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,9 @@ RenameRewriteRule(RangeVar *relation, const char *oldName,
/* OK, do the update */
namestrcpy(&(ruleform->rulename), newName);
-
- CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup);
+ HeapTupleMarkColumnUpdated(pg_rewrite, rulename, updated);
+ 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 f003d7b4a73..112b55f72a8 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 2bd872d6581..34c48532a30 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -562,9 +562,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);
@@ -610,6 +609,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.
@@ -665,16 +666,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.
@@ -711,11 +707,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++;
@@ -751,9 +747,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);
@@ -840,14 +836,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
{
@@ -879,11 +872,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
On Wed, Dec 03, 2025 at 09:11:03AM -0500, Greg Burd wrote:
On Dec 2 2025, at 11:16 pm, Michael Paquier <michael@paquier.xyz> wrote:
I've looked in the email archives a bit and didn't come up with much
related to catalog upgrades. I don't know if there is much on the
record information on this idea, but from what I've been told the idea
of decoupling heap from catalogs with the goal of getting closer to
making online upgrades possible has been referenced a few times in
hallway tracks at various conferences.
John Naylor has been looking at this problem at some point, if I
recall correctly. Adding him in CC here for comments and opinions, or
perhaps I am just wrong in assuming that he has looked at this area.
I'll see what I can do to extract this piece into a separate patch.
Thanks. I suspect that it would help with the clarity of the changes.
At least I am getting the same impression after reading v2, which is
close enough to v1 except for the various renames.
There are two major paths into heap_update(), one from
heapam_tuple_update() and one from simple_heap_update(). The first is
from the executor side via the table AM API and my other thread [6] that
you referenced is trying to address that. This thread is focused on the
catalog updates that flow into simple_heap_update(). Really that
function should be renamed to catalog_heap_update() as that's the only
purpose AFAICT.
You have a point based on how things are presented in this patch set,
where there is only one caller of simple_heap_update(), versus two on
HEAD.
Does that connect the dots a bit more clearly?
* 0003 Refactor how we form HeapTuples for CatalogTuple(Insert|Update)
This commit is borrowed from the other thread to demonstrate how these
changes impact heap updates. Thanks for your consideration, I
appreciate your time.
Now I see the connection, thanks to 0003 where simple_heap_update()
gains its Bitmapset that tracks the set of updated tuples, for the
business that happens in CatalogTupleUpdate(). All that is going to
need a careful lookup.
--
Michael
On Thu, Dec 4, 2025 at 12:50 PM Michael Paquier <michael@paquier.xyz> wrote:
On Wed, Dec 03, 2025 at 09:11:03AM -0500, Greg Burd wrote:
On Dec 2 2025, at 11:16 pm, Michael Paquier <michael@paquier.xyz> wrote:
I've looked in the email archives a bit and didn't come up with much
related to catalog upgrades. I don't know if there is much on the
record information on this idea, but from what I've been told the idea
of decoupling heap from catalogs with the goal of getting closer to
making online upgrades possible has been referenced a few times in
hallway tracks at various conferences.John Naylor has been looking at this problem at some point, if I
recall correctly. Adding him in CC here for comments and opinions, or
perhaps I am just wrong in assuming that he has looked at this area.
Hmm, I think the decoupling on-disk format from in-memory format was
most directly relevant for the idea of changing the "name" type from a
fixed length type, to a domain over text.
Catalog manipulation as speculated for online upgrades could probably
operate on the values/nulls array.
--
John Naylor
Amazon Web Services