=== Applying patches on top of PostgreSQL commit ID 952bab8b74d40fcfd25e1949865c3907e676504e === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Tue Nov 10 11:55:28 UTC 2026 On branch cf/7284 nothing to commit, working tree clean === using 'git am' to apply patch ./v1-0001-Remove-unused-tuple-expansion-and-copying-functio.patch === Applying: Remove unused tuple expansion and copying functions Using index info to reconstruct a base tree... M src/backend/access/common/heaptuple.c M src/include/access/htup_details.h Falling back to patching base and 3-way merge... Auto-merging src/include/access/htup_details.h Auto-merging src/backend/access/common/heaptuple.c CONFLICT (content): Merge conflict in src/backend/access/common/heaptuple.c error: Failed to merge in the changes. hint: Use 'git am --show-current-patch=diff' to see the failed patch Patch failed at 0001 Remove unused tuple expansion and copying functions When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". === using patch(1) to apply patch ./v1-0001-Remove-unused-tuple-expansion-and-copying-functio.patch === patching file src/backend/access/common/heaptuple.c Hunk #1 FAILED at 699. 1 out of 1 hunk FAILED -- saving rejects to file src/backend/access/common/heaptuple.c.rej patching file src/include/access/htup_details.h Hunk #1 succeeded at 975 (offset 169 lines). Hunk #2 succeeded at 1001 (offset 170 lines). patching file src/test/regress/expected/fast_default.out patching file src/test/regress/sql/fast_default.sql Unstaged changes after reset: M src/include/access/htup_details.h M src/test/regress/expected/fast_default.out M src/test/regress/sql/fast_default.sql Removing src/backend/access/common/heaptuple.c.rej === using 'git apply' to apply patch ./v1-0001-Remove-unused-tuple-expansion-and-copying-functio.patch === Applied patch to 'src/backend/access/common/heaptuple.c' with conflicts. Applied patch to 'src/include/access/htup_details.h' cleanly. Applied patch to 'src/test/regress/expected/fast_default.out' cleanly. Applied patch to 'src/test/regress/sql/fast_default.sql' cleanly. U src/backend/access/common/heaptuple.c diff --cc src/backend/access/common/heaptuple.c index 948d62f1888,c6b868d622a..00000000000 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@@ -740,296 -700,6 +740,299 @@@ heap_copytuple(HeapTuple tuple } /* ---------------- ++<<<<<<< ours + * heap_copytuple_with_tuple + * + * copy a tuple into a caller-supplied HeapTuple management struct + * + * Note that after calling this function, the "dest" HeapTuple will not be + * allocated as a single palloc() block (unlike with heap_copytuple()). + * ---------------- + */ +void +heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest) +{ + if (!HeapTupleIsValid(src) || src->t_data == NULL) + { + dest->t_data = NULL; + return; + } + + dest->t_len = src->t_len; + dest->t_self = src->t_self; + dest->t_tableOid = src->t_tableOid; + dest->t_data = (HeapTupleHeader) palloc(src->t_len); + memcpy(dest->t_data, src->t_data, src->t_len); +} + +/* + * Expand a tuple which has fewer attributes than required. For each attribute + * not present in the sourceTuple, if there is a missing value that will be + * used. Otherwise the attribute will be set to NULL. + * + * The source tuple must have fewer attributes than the required number. + * + * Only one of targetHeapTuple and targetMinimalTuple may be supplied. The + * other argument must be NULL. + */ +static void +expand_tuple(HeapTuple *targetHeapTuple, + MinimalTuple *targetMinimalTuple, + HeapTuple sourceTuple, + TupleDesc tupleDesc) +{ + AttrMissing *attrmiss = NULL; + int attnum; + int firstmissingnum; + bool hasNulls = HeapTupleHasNulls(sourceTuple); + HeapTupleHeader targetTHeader; + HeapTupleHeader sourceTHeader = sourceTuple->t_data; + int sourceNatts = HeapTupleHeaderGetNatts(sourceTHeader); + int natts = tupleDesc->natts; + int sourceNullLen; + int targetNullLen; + Size sourceDataLen = sourceTuple->t_len - sourceTHeader->t_hoff; + Size targetDataLen; + Size len; + int hoff; + uint8 *nullBits = NULL; + int bitMask = 0; + char *targetData; + uint16 *infoMask; + + Assert((targetHeapTuple && !targetMinimalTuple) + || (!targetHeapTuple && targetMinimalTuple)); + + if (HeapTupleHeaderIsVersionedDatum(sourceTHeader)) + heap_datum_check(sourceTHeader, tupleDesc); + + Assert(sourceNatts < natts); + + sourceNullLen = (hasNulls ? BITMAPLEN(sourceNatts) : 0); + + targetDataLen = sourceDataLen; + + if (tupleDesc->constr && + tupleDesc->constr->missing) + { + /* + * If there are missing values we want to put them into the tuple. + * Before that we have to compute the extra length for the values + * array and the variable length data. + */ + attrmiss = tupleDesc->constr->missing; + + /* + * Find the first item in attrmiss for which we don't have a value in + * the source. We can ignore all the missing entries before that. + */ + for (firstmissingnum = sourceNatts; + firstmissingnum < natts; + firstmissingnum++) + { + if (attrmiss[firstmissingnum].am_present) + break; + else + hasNulls = true; + } + + /* + * Now walk the missing attributes. If there is a missing value make + * space for it. Otherwise, it's going to be NULL. + */ + for (attnum = firstmissingnum; + attnum < natts; + attnum++) + { + if (attrmiss[attnum].am_present) + { + CompactAttribute *att = TupleDescCompactAttr(tupleDesc, attnum); + + targetDataLen = att_datum_alignby(targetDataLen, + att->attalignby, + att->attlen, + attrmiss[attnum].am_value); + + targetDataLen = att_addlength_datum(targetDataLen, + att->attlen, + attrmiss[attnum].am_value); + + if (!AllocSizeIsValid(targetDataLen)) + ereport(ERROR, + errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("tuple is too big")); + } + else + { + /* no missing value, so it must be null */ + hasNulls = true; + } + } + } /* end if have missing values */ + else + { + /* + * If there are no missing values at all then NULLS must be allowed, + * since some of the attributes are known to be absent. + */ + hasNulls = true; + } + + len = 0; + + if (hasNulls) + { + targetNullLen = BITMAPLEN(natts); + len += targetNullLen; + } + else + targetNullLen = 0; + + /* + * Allocate and zero the space needed. Note that the tuple body and + * HeapTupleData management structure are allocated in one chunk. + */ + if (targetHeapTuple) + { + len += offsetof(HeapTupleHeaderData, t_bits); + hoff = len = MAXALIGN(len); /* align user data safely */ + len += targetDataLen; + + *targetHeapTuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len); + (*targetHeapTuple)->t_data + = targetTHeader + = (HeapTupleHeader) ((char *) *targetHeapTuple + HEAPTUPLESIZE); + (*targetHeapTuple)->t_len = len; + (*targetHeapTuple)->t_tableOid = sourceTuple->t_tableOid; + (*targetHeapTuple)->t_self = sourceTuple->t_self; + + targetTHeader->t_infomask = sourceTHeader->t_infomask; + targetTHeader->t_hoff = hoff; + HeapTupleHeaderSetNatts(targetTHeader, natts); + /* invalidates t_ctid */ + heap_tuple_set_datum(targetTHeader, tupleDesc, len); + + if (targetNullLen > 0) + nullBits = (uint8 *) ((char *) (*targetHeapTuple)->t_data + + offsetof(HeapTupleHeaderData, t_bits)); + targetData = (char *) (*targetHeapTuple)->t_data + hoff; + infoMask = &(targetTHeader->t_infomask); + } + else + { + len += SizeofMinimalTupleHeader; + hoff = len = MAXALIGN(len); /* align user data safely */ + len += targetDataLen; + + *targetMinimalTuple = (MinimalTuple) palloc0(len); + (*targetMinimalTuple)->t_len = len; + (*targetMinimalTuple)->t_hoff = hoff + MINIMAL_TUPLE_OFFSET; + (*targetMinimalTuple)->t_infomask = sourceTHeader->t_infomask; + /* Same macro works for MinimalTuples */ + HeapTupleHeaderSetNatts(*targetMinimalTuple, natts); + + /* like HeapTupleHeaderClearDatum() */ + (*targetMinimalTuple)->t_infomask &= ~HEAP_IS_DATUM; + + if (targetNullLen > 0) + nullBits = (uint8 *) ((char *) *targetMinimalTuple + + offsetof(MinimalTupleData, t_bits)); + targetData = (char *) *targetMinimalTuple + hoff; + infoMask = &((*targetMinimalTuple)->t_infomask); + } + + if (targetNullLen > 0) + { + if (sourceNullLen > 0) + { + /* if bitmap pre-existed copy in - all is set */ + memcpy(nullBits, + ((char *) sourceTHeader) + + offsetof(HeapTupleHeaderData, t_bits), + sourceNullLen); + nullBits += sourceNullLen - 1; + } + else + { + sourceNullLen = BITMAPLEN(sourceNatts); + /* Set NOT NULL for all existing attributes */ + memset(nullBits, 0xff, sourceNullLen); + + nullBits += sourceNullLen - 1; + + if (sourceNatts & 0x07) + { + /* build the mask (inverted!) */ + bitMask = 0xff << (sourceNatts & 0x07); + /* Voila */ + *nullBits = ~bitMask; + } + } + + bitMask = (1 << ((sourceNatts - 1) & 0x07)); + } /* End if have null bitmap */ + + memcpy(targetData, + ((char *) sourceTuple->t_data) + sourceTHeader->t_hoff, + sourceDataLen); + + targetData += sourceDataLen; + + /* Now fill in the missing values */ + for (attnum = sourceNatts; attnum < natts; attnum++) + { + CompactAttribute *attr = TupleDescCompactAttr(tupleDesc, attnum); + + if (attrmiss && attrmiss[attnum].am_present) + { + fill_val(attr, + nullBits ? &nullBits : NULL, + &bitMask, + &targetData, + infoMask, + attrmiss[attnum].am_value, + false); + } + else + { + fill_val(attr, + &nullBits, + &bitMask, + &targetData, + infoMask, + (Datum) 0, + true); + } + } /* end loop over missing attributes */ +} + +/* + * Fill in the missing values for a minimal HeapTuple + */ +MinimalTuple +minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc) +{ + MinimalTuple minimalTuple; + + expand_tuple(NULL, &minimalTuple, sourceTuple, tupleDesc); + return minimalTuple; +} + +/* + * Fill in the missing values for an ordinary HeapTuple + */ +HeapTuple +heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc) +{ + HeapTuple heapTuple; + + expand_tuple(&heapTuple, NULL, sourceTuple, tupleDesc); + return heapTuple; +} + +/* ---------------- ++======= ++>>>>>>> theirs * heap_copy_tuple_as_datum * * copy a tuple as a composite-type Datum