aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/common/tupconvert.c22
-rw-r--r--src/backend/executor/execExprInterp.c34
2 files changed, 34 insertions, 22 deletions
diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c
index a4012525d80..392a49b522d 100644
--- a/src/backend/access/common/tupconvert.c
+++ b/src/backend/access/common/tupconvert.c
@@ -138,13 +138,14 @@ convert_tuples_by_position(TupleDesc indesc,
nincols, noutcols)));
/*
- * Check to see if the map is one-to-one, in which case we need not do
- * the tuple conversion. That's not enough though if either source or
- * destination (tuples) contains OIDs; we'd need conversion in that case
- * to inject the right OID into the tuple datum.
+ * Check to see if the map is one-to-one, in which case we need not do a
+ * tuple conversion. We must also insist that both tupdescs either
+ * specify or don't specify an OID column, else we need a conversion to
+ * add/remove space for that. (For some callers, presence or absence of
+ * an OID column perhaps would not really matter, but let's be safe.)
*/
if (indesc->natts == outdesc->natts &&
- !indesc->tdhasoid && !outdesc->tdhasoid)
+ indesc->tdhasoid == outdesc->tdhasoid)
{
for (i = 0; i < n; i++)
{
@@ -215,13 +216,14 @@ convert_tuples_by_name(TupleDesc indesc,
attrMap = convert_tuples_by_name_map(indesc, outdesc, msg);
/*
- * Check to see if the map is one-to-one, in which case we need not do
- * the tuple conversion. That's not enough though if either source or
- * destination (tuples) contains OIDs; we'd need conversion in that case
- * to inject the right OID into the tuple datum.
+ * Check to see if the map is one-to-one, in which case we need not do a
+ * tuple conversion. We must also insist that both tupdescs either
+ * specify or don't specify an OID column, else we need a conversion to
+ * add/remove space for that. (For some callers, presence or absence of
+ * an OID column perhaps would not really matter, but let's be safe.)
*/
if (indesc->natts == outdesc->natts &&
- !indesc->tdhasoid && !outdesc->tdhasoid)
+ indesc->tdhasoid == outdesc->tdhasoid)
{
same = true;
for (i = 0; i < n; i++)
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 22eb81edadf..fed0052fc6d 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -2840,21 +2840,31 @@ ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext
MemoryContextSwitchTo(old_cxt);
}
- /*
- * No-op if no conversion needed (not clear this can happen here).
- */
- if (op->d.convert_rowtype.map == NULL)
- return;
-
- /*
- * do_convert_tuple needs a HeapTuple not a bare HeapTupleHeader.
- */
+ /* Following steps need a HeapTuple not a bare HeapTupleHeader */
tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
tmptup.t_data = tuple;
- result = do_convert_tuple(&tmptup, op->d.convert_rowtype.map);
-
- *op->resvalue = HeapTupleGetDatum(result);
+ if (op->d.convert_rowtype.map != NULL)
+ {
+ /* Full conversion with attribute rearrangement needed */
+ result = do_convert_tuple(&tmptup, op->d.convert_rowtype.map);
+ /* Result already has appropriate composite-datum header fields */
+ *op->resvalue = HeapTupleGetDatum(result);
+ }
+ else
+ {
+ /*
+ * The tuple is physically compatible as-is, but we need to insert the
+ * destination rowtype OID in its composite-datum header field, so we
+ * have to copy it anyway. heap_copy_tuple_as_datum() is convenient
+ * for this since it will both make the physical copy and insert the
+ * correct composite header fields. Note that we aren't expecting to
+ * have to flatten any toasted fields: the input was a composite
+ * datum, so it shouldn't contain any. So heap_copy_tuple_as_datum()
+ * is overkill here, but its check for external fields is cheap.
+ */
+ *op->resvalue = heap_copy_tuple_as_datum(&tmptup, outdesc);
+ }
}
/*