1 /*-------------------------------------------------------------------------
2  *
3  * heaptuple.c
4  *	  This file contains heap tuple accessor and mutator routines, as well
5  *	  as various tuple utilities.
6  *
7  * Some notes about varlenas and this code:
8  *
9  * Before Postgres 8.3 varlenas always had a 4-byte length header, and
10  * therefore always needed 4-byte alignment (at least).  This wasted space
11  * for short varlenas, for example CHAR(1) took 5 bytes and could need up to
12  * 3 additional padding bytes for alignment.
13  *
14  * Now, a short varlena (up to 126 data bytes) is reduced to a 1-byte header
15  * and we don't align it.  To hide this from datatype-specific functions that
16  * don't want to deal with it, such a datum is considered "toasted" and will
17  * be expanded back to the normal 4-byte-header format by pg_detoast_datum.
18  * (In performance-critical code paths we can use pg_detoast_datum_packed
19  * and the appropriate access macros to avoid that overhead.)  Note that this
20  * conversion is performed directly in heap_form_tuple, without invoking
21  * tuptoaster.c.
22  *
23  * This change will break any code that assumes it needn't detoast values
24  * that have been put into a tuple but never sent to disk.  Hopefully there
25  * are few such places.
26  *
27  * Varlenas still have alignment 'i' (or 'd') in pg_type/pg_attribute, since
28  * that's the normal requirement for the untoasted format.  But we ignore that
29  * for the 1-byte-header format.  This means that the actual start position
30  * of a varlena datum may vary depending on which format it has.  To determine
31  * what is stored, we have to require that alignment padding bytes be zero.
32  * (Postgres actually has always zeroed them, but now it's required!)  Since
33  * the first byte of a 1-byte-header varlena can never be zero, we can examine
34  * the first byte after the previous datum to tell if it's a pad byte or the
35  * start of a 1-byte-header varlena.
36  *
37  * Note that while formerly we could rely on the first varlena column of a
38  * system catalog to be at the offset suggested by the C struct for the
39  * catalog, this is now risky: it's only safe if the preceding field is
40  * word-aligned, so that there will never be any padding.
41  *
42  * We don't pack varlenas whose attstorage is 'p', since the data type
43  * isn't expecting to have to detoast values.  This is used in particular
44  * by oidvector and int2vector, which are used in the system catalogs
45  * and we'd like to still refer to them via C struct offsets.
46  *
47  *
48  * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
49  * Portions Copyright (c) 1994, Regents of the University of California
clone(&self) -> Self50  *
51  *
52  * IDENTIFICATION
53  *	  src/backend/access/common/heaptuple.c
54  *
55  *-------------------------------------------------------------------------
56  */
57 
58 #include "postgres.h"
59 
60 #include "access/sysattr.h"
61 #include "access/tupdesc_details.h"
62 #include "access/tuptoaster.h"
63 #include "executor/tuptable.h"
64 #include "utils/expandeddatum.h"
65 
66 
67 /* Does att's datatype allow packing into the 1-byte-header varlena format? */
68 #define ATT_IS_PACKABLE(att) \
69 	((att)->attlen == -1 && (att)->attstorage != 'p')
70 /* Use this if it's already known varlena */
71 #define VARLENA_ATT_IS_PACKABLE(att) \
72 	((att)->attstorage != 'p')
73 
74 
75 /* ----------------------------------------------------------------
76  *						misc support routines
77  * ----------------------------------------------------------------
78  */
79 
80 /*
81  * Return the missing value of an attribute, or NULL if there isn't one.
82  */
83 Datum
84 getmissingattr(TupleDesc tupleDesc,
85 			   int attnum, bool *isnull)
86 {
87 	Form_pg_attribute att;
88 
89 	Assert(attnum <= tupleDesc->natts);
90 	Assert(attnum > 0);
91 
92 	att = TupleDescAttr(tupleDesc, attnum - 1);
93 
94 	if (att->atthasmissing)
95 	{
96 		AttrMissing *attrmiss;
97 
98 		Assert(tupleDesc->constr);
99 		Assert(tupleDesc->constr->missing);
100 
101 		attrmiss = tupleDesc->constr->missing + (attnum - 1);
102 
103 		if (attrmiss->am_present)
104 		{
105 			*isnull = false;
106 			return attrmiss->am_value;
107 		}
108 	}
109 
110 	*isnull = true;
111 	return PointerGetDatum(NULL);
112 }
113 
114 /*
115  * Fill in missing values for a TupleTableSlot.
116  *
117  * This is only exposed because it's needed for JIT compiled tuple
118  * deforming. That exception aside, there should be no callers outside of this
119  * file.
120  */
121 void
122 slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
123 {
124 	AttrMissing *attrmiss = NULL;
125 	int			missattnum;
126 
127 	if (slot->tts_tupleDescriptor->constr)
128 		attrmiss = slot->tts_tupleDescriptor->constr->missing;
129 
130 	if (!attrmiss)
clone(&self) -> Self131 	{
132 		/* no missing values array at all, so just fill everything in as NULL */
133 		memset(slot->tts_values + startAttNum, 0,
134 			   (lastAttNum - startAttNum) * sizeof(Datum));
135 		memset(slot->tts_isnull + startAttNum, 1,
136 			   (lastAttNum - startAttNum) * sizeof(bool));
137 	}
138 	else
139 	{
140 		/* if there is a missing values array we must process them one by one */
141 		for (missattnum = startAttNum;
142 			 missattnum < lastAttNum;
143 			 missattnum++)
144 		{
145 			slot->tts_values[missattnum] = attrmiss[missattnum].am_value;
146 			slot->tts_isnull[missattnum] = !attrmiss[missattnum].am_present;
147 		}
148 	}
149 }
150 
151 /*
clone(&self) -> Self152  * heap_compute_data_size
153  *		Determine size of the data area of a tuple to be constructed
154  */
155 Size
156 heap_compute_data_size(TupleDesc tupleDesc,
157 					   Datum *values,
158 					   bool *isnull)
159 {
160 	Size		data_length = 0;
161 	int			i;
162 	int			numberOfAttributes = tupleDesc->natts;
163 
164 	for (i = 0; i < numberOfAttributes; i++)
165 	{
166 		Datum		val;
167 		Form_pg_attribute atti;
168 
169 		if (isnull[i])
170 			continue;
171 
172 		val = values[i];
173 		atti = TupleDescAttr(tupleDesc, i);
174 
175 		if (ATT_IS_PACKABLE(atti) &&
176 			VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
177 		{
178 			/*
179 			 * we're anticipating converting to a short varlena header, so
180 			 * adjust length and don't count any alignment
181 			 */
182 			data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
183 		}
184 		else if (atti->attlen == -1 &&
185 				 VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(val)))
186 		{
187 			/*
188 			 * we want to flatten the expanded value so that the constructed
189 			 * tuple doesn't depend on it
190 			 */
191 			data_length = att_align_nominal(data_length, atti->attalign);
192 			data_length += EOH_get_flat_size(DatumGetEOHP(val));
193 		}
194 		else
195 		{
196 			data_length = att_align_datum(data_length, atti->attalign,
197 										  atti->attlen, val);
198 			data_length = att_addlength_datum(data_length, atti->attlen,
199 											  val);
200 		}
201 	}
202 
203 	return data_length;
204 }
205 
206 /*
207  * Per-attribute helper for heap_fill_tuple and other routines building tuples.
208  *
209  * Fill in either a data value or a bit in the null bitmask
210  */
211 static inline void
212 fill_val(Form_pg_attribute att,
213 		 bits8 **bit,
214 		 int *bitmask,
215 		 char **dataP,
216 		 uint16 *infomask,
217 		 Datum datum,
218 		 bool isnull)
219 {
220 	Size		data_length;
221 	char	   *data = *dataP;
222 
223 	/*
224 	 * If we're building a null bitmap, set the appropriate bit for the
225 	 * current column value here.
226 	 */
227 	if (bit != NULL)
228 	{
229 		if (*bitmask != HIGHBIT)
230 			*bitmask <<= 1;
231 		else
232 		{
233 			*bit += 1;
234 			**bit = 0x0;
235 			*bitmask = 1;
236 		}
237 
238 		if (isnull)
clone(&self) -> Self239 		{
240 			*infomask |= HEAP_HASNULL;
241 			return;
242 		}
243 
default() -> Self244 		**bit |= *bitmask;
245 	}
246 
247 	/*
248 	 * XXX we use the att_align macros on the pointer value itself, not on an
249 	 * offset.  This is a bit of a hack.
250 	 */
251 	if (att->attbyval)
252 	{
253 		/* pass-by-value */
254 		data = (char *) att_align_nominal(data, att->attalign);
255 		store_att_byval(data, datum, att->attlen);
256 		data_length = att->attlen;
257 	}
258 	else if (att->attlen == -1)
259 	{
260 		/* varlena */
261 		Pointer		val = DatumGetPointer(datum);
262 
263 		*infomask |= HEAP_HASVARWIDTH;
264 		if (VARATT_IS_EXTERNAL(val))
265 		{
__va_start(arg1: *mut va_list, ...)266 			if (VARATT_IS_EXTERNAL_EXPANDED(val))
267 			{
268 				/*
269 				 * we want to flatten the expanded value so that the
270 				 * constructed tuple doesn't depend on it
271 				 */
272 				ExpandedObjectHeader *eoh = DatumGetEOHP(datum);
273 
274 				data = (char *) att_align_nominal(data,
275 												  att->attalign);
276 				data_length = EOH_get_flat_size(eoh);
277 				EOH_flatten_into(eoh, data, data_length);
278 			}
_get_errno(_Value: *mut ::std::os::raw::c_int) -> errno_t279 			else
280 			{
281 				*infomask |= HEAP_HASEXTERNAL;
282 				/* no alignment, since it's short by definition */
283 				data_length = VARSIZE_EXTERNAL(val);
284 				memcpy(data, val, data_length);
285 			}
_fgetwchar() -> wint_t286 		}
287 		else if (VARATT_IS_SHORT(val))
288 		{
289 			/* no alignment for short varlenas */
290 			data_length = VARSIZE_SHORT(val);
291 			memcpy(data, val, data_length);
292 		}
293 		else if (VARLENA_ATT_IS_PACKABLE(att) &&
294 				 VARATT_CAN_MAKE_SHORT(val))
fputws(_Buffer: *const wchar_t, _Stream: *mut FILE) -> ::std::os::raw::c_int295 		{
296 			/* convert to short varlena -- no alignment */
297 			data_length = VARATT_CONVERTED_SHORT_SIZE(val);
298 			SET_VARSIZE_SHORT(data, data_length);
299 			memcpy(data + 1, VARDATA(val), data_length - 1);
300 		}
_wfdopen(_FileHandle: ::std::os::raw::c_int, _Mode: *const wchar_t) -> *mut FILE301 		else
302 		{
303 			/* full 4-byte header varlena */
304 			data = (char *) att_align_nominal(data,
305 											  att->attalign);
306 			data_length = VARSIZE(val);
307 			memcpy(data, val, data_length);
308 		}
309 	}
310 	else if (att->attlen == -2)
_wfreopen_s(_Stream: *mut *mut FILE, _FileName: *const wchar_t, _Mode: *const wchar_t, _OldStream: *mut FILE) -> errno_t311 	{
312 		/* cstring ... never needs alignment */
313 		*infomask |= HEAP_HASVARWIDTH;
314 		Assert(att->attalign == 'c');
315 		data_length = strlen(DatumGetCString(datum)) + 1;
316 		memcpy(data, DatumGetPointer(datum), data_length);
317 	}
318 	else
319 	{
_wperror(_ErrorMessage: *const wchar_t)320 		/* fixed-length pass-by-reference */
321 		data = (char *) att_align_nominal(data, att->attalign);
_wremove(_FileName: *const wchar_t) -> ::std::os::raw::c_int322 		Assert(att->attlen > 0);
_wtempnam(_Directory: *const wchar_t, _FilePrefix: *const wchar_t) -> *mut wchar_t323 		data_length = att->attlen;
_wtmpnam_s(_Buffer: *mut wchar_t, _BufferCount: size_t) -> errno_t324 		memcpy(data, DatumGetPointer(datum), data_length);
_wtmpnam(_Buffer: *mut wchar_t) -> *mut wchar_t325 	}
326 
327 	data += data_length;
_getwc_nolock(_Stream: *mut FILE) -> wint_t328 	*dataP = data;
_putwc_nolock(_Character: wchar_t, _Stream: *mut FILE) -> wint_t329 }
330 
331 /*
332  * heap_fill_tuple
333  *		Load data portion of a tuple from values/isnull arrays
334  *
335  * We also fill the null bitmap (if any) and set the infomask bits
336  * that reflect the tuple's data contents.
337  *
338  * NOTE: it is now REQUIRED that the caller have pre-zeroed the data area.
339  */
340 void
341 heap_fill_tuple(TupleDesc tupleDesc,
342 				Datum *values, bool *isnull,
343 				char *data, Size data_size,
344 				uint16 *infomask, bits8 *bit)
345 {
346 	bits8	   *bitP;
347 	int			bitmask;
348 	int			i;
349 	int			numberOfAttributes = tupleDesc->natts;
350 
351 #ifdef USE_ASSERT_CHECKING
352 	char	   *start = data;
353 #endif
354 
355 	if (bit != NULL)
356 	{
357 		bitP = &bit[-1];
358 		bitmask = HIGHBIT;
359 	}
360 	else
361 	{
362 		/* just to keep compiler quiet */
363 		bitP = NULL;
364 		bitmask = 0;
365 	}
366 
367 	*infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTERNAL);
368 
369 	for (i = 0; i < numberOfAttributes; i++)
370 	{
371 		Form_pg_attribute attr = TupleDescAttr(tupleDesc, i);
372 
373 		fill_val(attr,
374 				 bitP ? &bitP : NULL,
375 				 &bitmask,
376 				 &data,
377 				 infomask,
378 				 values ? values[i] : PointerGetDatum(NULL),
379 				 isnull ? isnull[i] : true);
380 	}
381 
382 	Assert((data - start) == data_size);
383 }
384 
vwprintf_s(_Format: *const wchar_t, _ArgList: va_list) -> ::std::os::raw::c_int385 
386 /* ----------------------------------------------------------------
387  *						heap tuple interface
388  * ----------------------------------------------------------------
389  */
390 
391 /* ----------------
392  *		heap_attisnull	- returns true iff tuple attribute is not present
393  * ----------------
394  */
395 bool
396 heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
397 {
398 	/*
399 	 * We allow a NULL tupledesc for relations not expected to have missing
400 	 * values, such as catalog relations and indexes.
401 	 */
402 	Assert(!tupleDesc || attnum <= tupleDesc->natts);
403 	if (attnum > (int) HeapTupleHeaderGetNatts(tup->t_data))
404 	{
405 		if (tupleDesc && TupleDescAttr(tupleDesc, attnum - 1)->atthasmissing)
406 			return false;
407 		else
408 			return true;
409 	}
410 
411 	if (attnum > 0)
412 	{
413 		if (HeapTupleNoNulls(tup))
414 			return false;
415 		return att_isnull(attnum - 1, tup->t_data->t_bits);
416 	}
417 
418 	switch (attnum)
419 	{
420 		case TableOidAttributeNumber:
421 		case SelfItemPointerAttributeNumber:
422 		case ObjectIdAttributeNumber:
423 		case MinTransactionIdAttributeNumber:
424 		case MinCommandIdAttributeNumber:
425 		case MaxTransactionIdAttributeNumber:
426 		case MaxCommandIdAttributeNumber:
427 			/* these are never null */
428 			break;
429 
430 		default:
431 			elog(ERROR, "invalid attnum: %d", attnum);
432 	}
433 
434 	return false;
435 }
436 
437 /* ----------------
438  *		nocachegetattr
_vwscanf_l(_Format: *const wchar_t, _Locale: _locale_t, _ArgList: va_list) -> ::std::os::raw::c_int439  *
440  *		This only gets called from fastgetattr() macro, in cases where
441  *		we can't use a cacheoffset and the value is not null.
442  *
443  *		This caches attribute offsets in the attribute descriptor.
444  *
445  *		An alternative way to speed things up would be to cache offsets
446  *		with the tuple, but that seems more difficult unless you take
447  *		the storage hit of actually putting those offsets into the
448  *		tuple you send to disk.  Yuck.
449  *
450  *		This scheme will be slightly slower than that, but should
451  *		perform well for queries which hit large #'s of tuples.  After
452  *		you cache the offsets once, examining all the other tuples using
453  *		the same attribute descriptor will go much quicker. -cim 5/4/91
454  *
455  *		NOTE: if you need to change this code, see also heap_deform_tuple.
456  *		Also see nocache_index_getattr, which is the same code for index
457  *		tuples.
458  * ----------------
459  */
460 Datum
461 nocachegetattr(HeapTuple tuple,
462 			   int attnum,
463 			   TupleDesc tupleDesc)
464 {
465 	HeapTupleHeader tup = tuple->t_data;
466 	char	   *tp;				/* ptr to data part of tuple */
467 	bits8	   *bp = tup->t_bits;	/* ptr to null bitmap in tuple */
468 	bool		slow = false;	/* do we have to walk attrs? */
469 	int			off;			/* current offset within data */
470 
471 	/* ----------------
472 	 *	 Three cases:
473 	 *
474 	 *	 1: No nulls and no variable-width attributes.
475 	 *	 2: Has a null or a var-width AFTER att.
476 	 *	 3: Has nulls or var-widths BEFORE att.
477 	 * ----------------
478 	 */
479 
480 	attnum--;
481 
482 	if (!HeapTupleNoNulls(tuple))
483 	{
484 		/*
485 		 * there's a null somewhere in the tuple
486 		 *
487 		 * check to see if any preceding bits are null...
488 		 */
489 		int			byte = attnum >> 3;
490 		int			finalbit = attnum & 0x07;
491 
492 		/* check for nulls "before" final bit of last byte */
493 		if ((~bp[byte]) & ((1 << finalbit) - 1))
494 			slow = true;
495 		else
496 		{
497 			/* check for nulls in any "earlier" bytes */
498 			int			i;
499 
500 			for (i = 0; i < byte; i++)
501 			{
502 				if (bp[i] != 0xFF)
503 				{
504 					slow = true;
505 					break;
506 				}
507 			}
508 		}
509 	}
510 
511 	tp = (char *) tup + tup->t_hoff;
512 
513 	if (!slow)
514 	{
515 		Form_pg_attribute att;
516 
517 		/*
518 		 * If we get here, there are no nulls up to and including the target
519 		 * attribute.  If we have a cached offset, we can use it.
520 		 */
521 		att = TupleDescAttr(tupleDesc, attnum);
522 		if (att->attcacheoff >= 0)
523 			return fetchatt(att, tp + att->attcacheoff);
524 
525 		/*
526 		 * Otherwise, check for non-fixed-length attrs up to and including
527 		 * target.  If there aren't any, it's safe to cheaply initialize the
528 		 * cached offsets for these attrs.
529 		 */
530 		if (HeapTupleHasVarWidth(tuple))
531 		{
532 			int			j;
533 
534 			for (j = 0; j <= attnum; j++)
535 			{
536 				if (TupleDescAttr(tupleDesc, j)->attlen <= 0)
537 				{
538 					slow = true;
539 					break;
540 				}
541 			}
542 		}
543 	}
544 
545 	if (!slow)
546 	{
547 		int			natts = tupleDesc->natts;
548 		int			j = 1;
549 
550 		/*
551 		 * If we get here, we have a tuple with no nulls or var-widths up to
552 		 * and including the target attribute, so we can use the cached offset
553 		 * ... only we don't have it yet, or we'd not have got here.  Since
554 		 * it's cheap to compute offsets for fixed-width columns, we take the
555 		 * opportunity to initialize the cached offsets for *all* the leading
556 		 * fixed-width columns, in hope of avoiding future visits to this
557 		 * routine.
558 		 */
559 		TupleDescAttr(tupleDesc, 0)->attcacheoff = 0;
560 
561 		/* we might have set some offsets in the slow path previously */
562 		while (j < natts && TupleDescAttr(tupleDesc, j)->attcacheoff > 0)
563 			j++;
564 
565 		off = TupleDescAttr(tupleDesc, j - 1)->attcacheoff +
566 			TupleDescAttr(tupleDesc, j - 1)->attlen;
567 
568 		for (; j < natts; j++)
569 		{
570 			Form_pg_attribute att = TupleDescAttr(tupleDesc, j);
571 
572 			if (att->attlen <= 0)
573 				break;
574 
575 			off = att_align_nominal(off, att->attalign);
576 
577 			att->attcacheoff = off;
578 
579 			off += att->attlen;
580 		}
581 
582 		Assert(j > attnum);
583 
584 		off = TupleDescAttr(tupleDesc, attnum)->attcacheoff;
585 	}
586 	else
587 	{
588 		bool		usecache = true;
589 		int			i;
590 
591 		/*
592 		 * Now we know that we have to walk the tuple CAREFULLY.  But we still
593 		 * might be able to cache some offsets for next time.
594 		 *
595 		 * Note - This loop is a little tricky.  For each non-null attribute,
596 		 * we have to first account for alignment padding before the attr,
597 		 * then advance over the attr based on its length.  Nulls have no
598 		 * storage and no alignment padding either.  We can use/set
599 		 * attcacheoff until we reach either a null or a var-width attribute.
600 		 */
601 		off = 0;
602 		for (i = 0;; i++)		/* loop exit is at "break" */
603 		{
604 			Form_pg_attribute att = TupleDescAttr(tupleDesc, i);
605 
606 			if (HeapTupleHasNulls(tuple) && att_isnull(i, bp))
607 			{
608 				usecache = false;
609 				continue;		/* this cannot be the target att */
610 			}
611 
612 			/* If we know the next offset, we can skip the rest */
613 			if (usecache && att->attcacheoff >= 0)
614 				off = att->attcacheoff;
615 			else if (att->attlen == -1)
616 			{
617 				/*
618 				 * We can only cache the offset for a varlena attribute if the
619 				 * offset is already suitably aligned, so that there would be
620 				 * no pad bytes in any case: then the offset will be valid for
621 				 * either an aligned or unaligned value.
622 				 */
623 				if (usecache &&
624 					off == att_align_nominal(off, att->attalign))
625 					att->attcacheoff = off;
626 				else
627 				{
628 					off = att_align_pointer(off, att->attalign, -1,
629 											tp + off);
630 					usecache = false;
631 				}
632 			}
633 			else
634 			{
635 				/* not varlena, so safe to use att_align_nominal */
636 				off = att_align_nominal(off, att->attalign);
637 
638 				if (usecache)
639 					att->attcacheoff = off;
640 			}
641 
642 			if (i == attnum)
643 				break;
644 
645 			off = att_addlength_pointer(off, att->attlen, tp + off);
646 
647 			if (usecache && att->attlen <= 0)
648 				usecache = false;
649 		}
650 	}
651 
652 	return fetchatt(TupleDescAttr(tupleDesc, attnum), tp + off);
653 }
654 
_scwprintf_l(_Format: *const wchar_t, _Locale: _locale_t, ...) -> ::std::os::raw::c_int655 /* ----------------
656  *		heap_getsysattr
657  *
658  *		Fetch the value of a system attribute for a tuple.
659  *
660  * This is a support routine for the heap_getattr macro.  The macro
661  * has already determined that the attnum refers to a system attribute.
662  * ----------------
663  */
664 Datum
665 heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
666 {
667 	Datum		result;
668 
669 	Assert(tup);
670 
671 	/* Currently, no sys attribute ever reads as NULL. */
672 	*isnull = false;
673 
674 	switch (attnum)
675 	{
676 		case SelfItemPointerAttributeNumber:
677 			/* pass-by-reference datatype */
678 			result = PointerGetDatum(&(tup->t_self));
679 			break;
680 		case ObjectIdAttributeNumber:
681 			result = ObjectIdGetDatum(HeapTupleGetOid(tup));
682 			break;
683 		case MinTransactionIdAttributeNumber:
684 			result = TransactionIdGetDatum(HeapTupleHeaderGetRawXmin(tup->t_data));
685 			break;
686 		case MaxTransactionIdAttributeNumber:
687 			result = TransactionIdGetDatum(HeapTupleHeaderGetRawXmax(tup->t_data));
688 			break;
689 		case MinCommandIdAttributeNumber:
690 		case MaxCommandIdAttributeNumber:
691 
692 			/*
693 			 * cmin and cmax are now both aliases for the same field, which
694 			 * can in fact also be a combo command id.  XXX perhaps we should
695 			 * return the "real" cmin or cmax if possible, that is if we are
696 			 * inside the originating transaction?
697 			 */
698 			result = CommandIdGetDatum(HeapTupleHeaderGetRawCommandId(tup->t_data));
699 			break;
700 		case TableOidAttributeNumber:
701 			result = ObjectIdGetDatum(tup->t_tableOid);
702 			break;
703 		default:
704 			elog(ERROR, "invalid attnum: %d", attnum);
705 			result = 0;			/* keep compiler quiet */
706 			break;
707 	}
708 	return result;
709 }
swscanf_s(_Buffer: *const wchar_t, _Format: *const wchar_t, ...) -> ::std::os::raw::c_int710 
711 /* ----------------
712  *		heap_copytuple
713  *
714  *		returns a copy of an entire tuple
715  *
716  * The HeapTuple struct, tuple header, and tuple data are all allocated
717  * as a single palloc() block.
718  * ----------------
719  */
720 HeapTuple
721 heap_copytuple(HeapTuple tuple)
722 {
723 	HeapTuple	newTuple;
724 
725 	if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
726 		return NULL;
727 
728 	newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);
729 	newTuple->t_len = tuple->t_len;
730 	newTuple->t_self = tuple->t_self;
731 	newTuple->t_tableOid = tuple->t_tableOid;
732 	newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
733 	memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len);
734 	return newTuple;
735 }
_get_stream_buffer_pointers(_Stream: *mut FILE, _Base: *mut *mut *mut ::std::os::raw::c_char, _Pointer: *mut *mut *mut ::std::os::raw::c_char, _Count: *mut *mut ::std::os::raw::c_int) -> errno_t736 
737 /* ----------------
738  *		heap_copytuple_with_tuple
739  *
740  *		copy a tuple into a caller-supplied HeapTuple management struct
741  *
742  * Note that after calling this function, the "dest" HeapTuple will not be
743  * allocated as a single palloc() block (unlike with heap_copytuple()).
744  * ----------------
745  */
746 void
747 heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
748 {
749 	if (!HeapTupleIsValid(src) || src->t_data == NULL)
750 	{
751 		dest->t_data = NULL;
752 		return;
753 	}
754 
755 	dest->t_len = src->t_len;
756 	dest->t_self = src->t_self;
757 	dest->t_tableOid = src->t_tableOid;
758 	dest->t_data = (HeapTupleHeader) palloc(src->t_len);
759 	memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);
760 }
tmpnam_s(_Buffer: *mut ::std::os::raw::c_char, _Size: rsize_t) -> errno_t761 
762 /*
763  * Expand a tuple which has less attributes than required. For each attribute
764  * not present in the sourceTuple, if there is a missing value that will be
765  * used. Otherwise the attribute will be set to NULL.
766  *
767  * The source tuple must have less attributes than the required number.
768  *
769  * Only one of targetHeapTuple and targetMinimalTuple may be supplied. The
770  * other argument must be NULL.
771  */
772 static void
773 expand_tuple(HeapTuple *targetHeapTuple,
774 			 MinimalTuple *targetMinimalTuple,
775 			 HeapTuple sourceTuple,
776 			 TupleDesc tupleDesc)
777 {
778 	AttrMissing *attrmiss = NULL;
779 	int			attnum;
780 	int			firstmissingnum = 0;
781 	bool		hasNulls = HeapTupleHasNulls(sourceTuple);
782 	HeapTupleHeader targetTHeader;
783 	HeapTupleHeader sourceTHeader = sourceTuple->t_data;
784 	int			sourceNatts = HeapTupleHeaderGetNatts(sourceTHeader);
785 	int			natts = tupleDesc->natts;
786 	int			sourceNullLen;
787 	int			targetNullLen;
788 	Size		sourceDataLen = sourceTuple->t_len - sourceTHeader->t_hoff;
789 	Size		targetDataLen;
790 	Size		len;
791 	int			hoff;
792 	bits8	   *nullBits = NULL;
793 	int			bitMask = 0;
794 	char	   *targetData;
795 	uint16	   *infoMask;
796 
797 	Assert((targetHeapTuple && !targetMinimalTuple)
798 		   || (!targetHeapTuple && targetMinimalTuple));
799 
800 	Assert(sourceNatts < natts);
801 
802 	sourceNullLen = (hasNulls ? BITMAPLEN(sourceNatts) : 0);
803 
804 	targetDataLen = sourceDataLen;
805 
806 	if (tupleDesc->constr &&
807 		tupleDesc->constr->missing)
808 	{
809 		/*
810 		 * If there are missing values we want to put them into the tuple.
811 		 * Before that we have to compute the extra length for the values
812 		 * array and the variable length data.
813 		 */
814 		attrmiss = tupleDesc->constr->missing;
815 
816 		/*
817 		 * Find the first item in attrmiss for which we don't have a value in
818 		 * the source. We can ignore all the missing entries before that.
819 		 */
820 		for (firstmissingnum = sourceNatts;
821 			 firstmissingnum < natts;
822 			 firstmissingnum++)
823 		{
824 			if (attrmiss[firstmissingnum].am_present)
825 				break;
826 			else
827 				hasNulls = true;
828 		}
829 
830 		/*
831 		 * Now walk the missing attributes. If there is a missing value
832 		 * make space for it. Otherwise, it's going to be NULL.
833 		 */
834 		for (attnum = firstmissingnum;
835 			 attnum < natts;
836 			 attnum++)
837 		{
838 			if (attrmiss[attnum].am_present)
839 			{
840 				Form_pg_attribute att = TupleDescAttr(tupleDesc, attnum);
841 
842 				targetDataLen = att_align_datum(targetDataLen,
843 												att->attalign,
844 												att->attlen,
845 												attrmiss[attnum].am_value);
846 
847 				targetDataLen = att_addlength_pointer(targetDataLen,
848 													  att->attlen,
849 													  attrmiss[attnum].am_value);
850 			}
851 			else
852 			{
853 				/* no missing value, so it must be null */
854 				hasNulls = true;
855 			}
856 		}
857 	}							/* end if have missing values */
858 	else
859 	{
860 		/*
861 		 * If there are no missing values at all then NULLS must be allowed,
862 		 * since some of the attributes are known to be absent.
863 		 */
864 		hasNulls = true;
865 	}
866 
867 	len = 0;
868 
869 	if (hasNulls)
870 	{
871 		targetNullLen = BITMAPLEN(natts);
872 		len += targetNullLen;
873 	}
874 	else
875 		targetNullLen = 0;
876 
877 	if (tupleDesc->tdhasoid)
878 		len += sizeof(Oid);
879 
880 	/*
881 	 * Allocate and zero the space needed.  Note that the tuple body and
882 	 * HeapTupleData management structure are allocated in one chunk.
883 	 */
884 	if (targetHeapTuple)
885 	{
886 		len += offsetof(HeapTupleHeaderData, t_bits);
887 		hoff = len = MAXALIGN(len); /* align user data safely */
888 		len += targetDataLen;
889 
890 		*targetHeapTuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
891 		(*targetHeapTuple)->t_data
892 			= targetTHeader
893 			= (HeapTupleHeader) ((char *) *targetHeapTuple + HEAPTUPLESIZE);
894 		(*targetHeapTuple)->t_len = len;
895 		(*targetHeapTuple)->t_tableOid = sourceTuple->t_tableOid;
896 		(*targetHeapTuple)->t_self = sourceTuple->t_self;
897 
898 		targetTHeader->t_infomask = sourceTHeader->t_infomask;
899 		targetTHeader->t_hoff = hoff;
900 		HeapTupleHeaderSetNatts(targetTHeader, natts);
901 		HeapTupleHeaderSetDatumLength(targetTHeader, len);
902 		HeapTupleHeaderSetTypeId(targetTHeader, tupleDesc->tdtypeid);
903 		HeapTupleHeaderSetTypMod(targetTHeader, tupleDesc->tdtypmod);
904 		/* We also make sure that t_ctid is invalid unless explicitly set */
905 		ItemPointerSetInvalid(&(targetTHeader->t_ctid));
906 		if (targetNullLen > 0)
907 			nullBits = (bits8 *) ((char *) (*targetHeapTuple)->t_data
908 								  + offsetof(HeapTupleHeaderData, t_bits));
909 		targetData = (char *) (*targetHeapTuple)->t_data + hoff;
910 		infoMask = &(targetTHeader->t_infomask);
911 	}
912 	else
913 	{
914 		len += SizeofMinimalTupleHeader;
915 		hoff = len = MAXALIGN(len); /* align user data safely */
916 		len += targetDataLen;
917 
918 		*targetMinimalTuple = (MinimalTuple) palloc0(len);
919 		(*targetMinimalTuple)->t_len = len;
920 		(*targetMinimalTuple)->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
921 		(*targetMinimalTuple)->t_infomask = sourceTHeader->t_infomask;
922 		/* Same macro works for MinimalTuples */
923 		HeapTupleHeaderSetNatts(*targetMinimalTuple, natts);
924 		if (targetNullLen > 0)
925 			nullBits = (bits8 *) ((char *) *targetMinimalTuple
926 								  + offsetof(MinimalTupleData, t_bits));
927 		targetData = (char *) *targetMinimalTuple + hoff;
928 		infoMask = &((*targetMinimalTuple)->t_infomask);
929 	}
930 
931 	if (targetNullLen > 0)
932 	{
933 		if (sourceNullLen > 0)
934 		{
935 			/* if bitmap pre-existed copy in - all is set */
936 			memcpy(nullBits,
937 				   ((char *) sourceTHeader)
938 				   + offsetof(HeapTupleHeaderData, t_bits),
939 				   sourceNullLen);
940 			nullBits += sourceNullLen - 1;
941 		}
942 		else
943 		{
944 			sourceNullLen = BITMAPLEN(sourceNatts);
945 			/* Set NOT NULL for all existing attributes */
946 			memset(nullBits, 0xff, sourceNullLen);
947 
948 			nullBits += sourceNullLen - 1;
949 
950 			if (sourceNatts & 0x07)
951 			{
952 				/* build the mask (inverted!) */
953 				bitMask = 0xff << (sourceNatts & 0x07);
954 				/* Voila */
955 				*nullBits = ~bitMask;
956 			}
957 		}
958 
959 		bitMask = (1 << ((sourceNatts - 1) & 0x07));
960 	}							/* End if have null bitmap */
961 
962 	memcpy(targetData,
963 		   ((char *) sourceTuple->t_data) + sourceTHeader->t_hoff,
964 		   sourceDataLen);
965 
966 	targetData += sourceDataLen;
967 
968 	/* Now fill in the missing values */
969 	for (attnum = sourceNatts; attnum < natts; attnum++)
970 	{
971 
972 		Form_pg_attribute attr = TupleDescAttr(tupleDesc, attnum);
973 
974 		if (attrmiss && attrmiss[attnum].am_present)
975 		{
976 			fill_val(attr,
977 					 nullBits ? &nullBits : NULL,
978 					 &bitMask,
979 					 &targetData,
980 					 infoMask,
981 					 attrmiss[attnum].am_value,
982 					 false);
983 		}
984 		else
985 		{
986 			fill_val(attr,
987 					 &nullBits,
988 					 &bitMask,
989 					 &targetData,
990 					 infoMask,
991 					 (Datum) 0,
992 					 true);
993 		}
994 	}							/* end loop over missing attributes */
995 }
996 
printf_s(_Format: *const ::std::os::raw::c_char, ...) -> ::std::os::raw::c_int997 /*
998  * Fill in the missing values for a minimal HeapTuple
999  */
1000 MinimalTuple
1001 minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
1002 {
1003 	MinimalTuple minimalTuple;
1004 
1005 	expand_tuple(NULL, &minimalTuple, sourceTuple, tupleDesc);
1006 	return minimalTuple;
1007 }
1008 
_vfscanf_l(_Stream: *mut FILE, _Format: *const ::std::os::raw::c_char, _Locale: _locale_t, _ArgList: va_list) -> ::std::os::raw::c_int1009 /*
1010  * Fill in the missing values for an ordinary HeapTuple
1011  */
1012 HeapTuple
1013 heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
1014 {
1015 	HeapTuple	heapTuple;
1016 
1017 	expand_tuple(&heapTuple, NULL, sourceTuple, tupleDesc);
1018 	return heapTuple;
1019 }
1020 
1021 /* ----------------
1022  *		heap_copy_tuple_as_datum
vfscanf_s(_Stream: *mut FILE, _Format: *const ::std::os::raw::c_char, _ArgList: va_list) -> ::std::os::raw::c_int1023  *
1024  *		copy a tuple as a composite-type Datum
1025  * ----------------
1026  */
1027 Datum
1028 heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
1029 {
1030 	HeapTupleHeader td;
1031 
1032 	/*
1033 	 * If the tuple contains any external TOAST pointers, we have to inline
1034 	 * those fields to meet the conventions for composite-type Datums.
1035 	 */
1036 	if (HeapTupleHasExternal(tuple))
1037 		return toast_flatten_tuple_to_datum(tuple->t_data,
1038 											tuple->t_len,
1039 											tupleDesc);
1040 
1041 	/*
1042 	 * Fast path for easy case: just make a palloc'd copy and insert the
1043 	 * correct composite-Datum header fields (since those may not be set if
1044 	 * the given tuple came from disk, rather than from heap_form_tuple).
1045 	 */
1046 	td = (HeapTupleHeader) palloc(tuple->t_len);
1047 	memcpy((char *) td, (char *) tuple->t_data, tuple->t_len);
1048 
1049 	HeapTupleHeaderSetDatumLength(td, tuple->t_len);
1050 	HeapTupleHeaderSetTypeId(td, tupleDesc->tdtypeid);
1051 	HeapTupleHeaderSetTypMod(td, tupleDesc->tdtypmod);
1052 
1053 	return PointerGetDatum(td);
1054 }
fscanf_s(_Stream: *mut FILE, _Format: *const ::std::os::raw::c_char, ...) -> ::std::os::raw::c_int1055 
1056 /*
1057  * heap_form_tuple
1058  *		construct a tuple from the given values[] and isnull[] arrays,
1059  *		which are of the length indicated by tupleDescriptor->natts
1060  *
1061  * The result is allocated in the current memory context.
1062  */
1063 HeapTuple
1064 heap_form_tuple(TupleDesc tupleDescriptor,
1065 				Datum *values,
1066 				bool *isnull)
1067 {
1068 	HeapTuple	tuple;			/* return tuple */
1069 	HeapTupleHeader td;			/* tuple data */
1070 	Size		len,
1071 				data_len;
1072 	int			hoff;
1073 	bool		hasnull = false;
1074 	int			numberOfAttributes = tupleDescriptor->natts;
1075 	int			i;
1076 
1077 	if (numberOfAttributes > MaxTupleAttributeNumber)
1078 		ereport(ERROR,
1079 				(errcode(ERRCODE_TOO_MANY_COLUMNS),
1080 				 errmsg("number of columns (%d) exceeds limit (%d)",
1081 						numberOfAttributes, MaxTupleAttributeNumber)));
1082 
1083 	/*
1084 	 * Check for nulls
1085 	 */
1086 	for (i = 0; i < numberOfAttributes; i++)
1087 	{
1088 		if (isnull[i])
1089 		{
1090 			hasnull = true;
1091 			break;
1092 		}
1093 	}
1094 
1095 	/*
1096 	 * Determine total space needed
1097 	 */
1098 	len = offsetof(HeapTupleHeaderData, t_bits);
1099 
1100 	if (hasnull)
1101 		len += BITMAPLEN(numberOfAttributes);
1102 
1103 	if (tupleDescriptor->tdhasoid)
1104 		len += sizeof(Oid);
1105 
1106 	hoff = len = MAXALIGN(len); /* align user data safely */
1107 
1108 	data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1109 
1110 	len += data_len;
1111 
1112 	/*
1113 	 * Allocate and zero the space needed.  Note that the tuple body and
1114 	 * HeapTupleData management structure are allocated in one chunk.
1115 	 */
1116 	tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
1117 	tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
1118 
1119 	/*
1120 	 * And fill in the information.  Note we fill the Datum fields even though
1121 	 * this tuple may never become a Datum.  This lets HeapTupleHeaderGetDatum
1122 	 * identify the tuple type if needed.
1123 	 */
1124 	tuple->t_len = len;
1125 	ItemPointerSetInvalid(&(tuple->t_self));
1126 	tuple->t_tableOid = InvalidOid;
1127 
1128 	HeapTupleHeaderSetDatumLength(td, len);
1129 	HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
1130 	HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
1131 	/* We also make sure that t_ctid is invalid unless explicitly set */
1132 	ItemPointerSetInvalid(&(td->t_ctid));
1133 
1134 	HeapTupleHeaderSetNatts(td, numberOfAttributes);
1135 	td->t_hoff = hoff;
1136 
1137 	if (tupleDescriptor->tdhasoid)	/* else leave infomask = 0 */
1138 		td->t_infomask = HEAP_HASOID;
1139 
1140 	heap_fill_tuple(tupleDescriptor,
1141 					values,
1142 					isnull,
1143 					(char *) td + hoff,
1144 					data_len,
1145 					&td->t_infomask,
1146 					(hasnull ? td->t_bits : NULL));
1147 
1148 	return tuple;
1149 }
1150 
1151 /*
_vsnprintf_s(_Buffer: *mut ::std::os::raw::c_char, _BufferCount: size_t, _MaxCount: size_t, _Format: *const ::std::os::raw::c_char, _ArgList: va_list) -> ::std::os::raw::c_int1152  * heap_modify_tuple
1153  *		form a new tuple from an old tuple and a set of replacement values.
1154  *
1155  * The replValues, replIsnull, and doReplace arrays must be of the length
1156  * indicated by tupleDesc->natts.  The new tuple is constructed using the data
1157  * from replValues/replIsnull at columns where doReplace is true, and using
1158  * the data from the old tuple at columns where doReplace is false.
1159  *
1160  * The result is allocated in the current memory context.
1161  */
1162 HeapTuple
1163 heap_modify_tuple(HeapTuple tuple,
1164 				  TupleDesc tupleDesc,
1165 				  Datum *replValues,
1166 				  bool *replIsnull,
1167 				  bool *doReplace)
1168 {
1169 	int			numberOfAttributes = tupleDesc->natts;
1170 	int			attoff;
1171 	Datum	   *values;
1172 	bool	   *isnull;
1173 	HeapTuple	newTuple;
1174 
1175 	/*
1176 	 * allocate and fill values and isnull arrays from either the tuple or the
1177 	 * repl information, as appropriate.
1178 	 *
1179 	 * NOTE: it's debatable whether to use heap_deform_tuple() here or just
1180 	 * heap_getattr() only the non-replaced columns.  The latter could win if
1181 	 * there are many replaced columns and few non-replaced ones. However,
1182 	 * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
1183 	 * O(N^2) if there are many non-replaced columns, so it seems better to
1184 	 * err on the side of linear cost.
1185 	 */
1186 	values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
1187 	isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
1188 
1189 	heap_deform_tuple(tuple, tupleDesc, values, isnull);
1190 
1191 	for (attoff = 0; attoff < numberOfAttributes; attoff++)
1192 	{
1193 		if (doReplace[attoff])
1194 		{
1195 			values[attoff] = replValues[attoff];
1196 			isnull[attoff] = replIsnull[attoff];
1197 		}
1198 	}
1199 
1200 	/*
1201 	 * create a new tuple from the values and isnull arrays
1202 	 */
1203 	newTuple = heap_form_tuple(tupleDesc, values, isnull);
1204 
1205 	pfree(values);
1206 	pfree(isnull);
1207 
1208 	/*
1209 	 * copy the identification info of the old tuple: t_ctid, t_self, and OID
1210 	 * (if any)
1211 	 */
1212 	newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1213 	newTuple->t_self = tuple->t_self;
1214 	newTuple->t_tableOid = tuple->t_tableOid;
1215 	if (tupleDesc->tdhasoid)
1216 		HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
1217 
1218 	return newTuple;
1219 }
_snprintf_l(_Buffer: *mut ::std::os::raw::c_char, _BufferCount: size_t, _Format: *const ::std::os::raw::c_char, _Locale: _locale_t, ...) -> ::std::os::raw::c_int1220 
1221 /*
1222  * heap_modify_tuple_by_cols
1223  *		form a new tuple from an old tuple and a set of replacement values.
1224  *
1225  * This is like heap_modify_tuple, except that instead of specifying which
1226  * column(s) to replace by a boolean map, an array of target column numbers
1227  * is used.  This is often more convenient when a fixed number of columns
1228  * are to be replaced.  The replCols, replValues, and replIsnull arrays must
1229  * be of length nCols.  Target column numbers are indexed from 1.
1230  *
1231  * The result is allocated in the current memory context.
1232  */
1233 HeapTuple
1234 heap_modify_tuple_by_cols(HeapTuple tuple,
1235 						  TupleDesc tupleDesc,
1236 						  int nCols,
1237 						  int *replCols,
1238 						  Datum *replValues,
1239 						  bool *replIsnull)
1240 {
1241 	int			numberOfAttributes = tupleDesc->natts;
1242 	Datum	   *values;
1243 	bool	   *isnull;
1244 	HeapTuple	newTuple;
1245 	int			i;
1246 
1247 	/*
1248 	 * allocate and fill values and isnull arrays from the tuple, then replace
1249 	 * selected columns from the input arrays.
1250 	 */
1251 	values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
1252 	isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
1253 
1254 	heap_deform_tuple(tuple, tupleDesc, values, isnull);
1255 
1256 	for (i = 0; i < nCols; i++)
1257 	{
1258 		int			attnum = replCols[i];
1259 
1260 		if (attnum <= 0 || attnum > numberOfAttributes)
1261 			elog(ERROR, "invalid column number %d", attnum);
1262 		values[attnum - 1] = replValues[i];
1263 		isnull[attnum - 1] = replIsnull[i];
1264 	}
1265 
1266 	/*
1267 	 * create a new tuple from the values and isnull arrays
1268 	 */
1269 	newTuple = heap_form_tuple(tupleDesc, values, isnull);
1270 
1271 	pfree(values);
1272 	pfree(isnull);
1273 
1274 	/*
1275 	 * copy the identification info of the old tuple: t_ctid, t_self, and OID
1276 	 * (if any)
1277 	 */
1278 	newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1279 	newTuple->t_self = tuple->t_self;
1280 	newTuple->t_tableOid = tuple->t_tableOid;
1281 	if (tupleDesc->tdhasoid)
1282 		HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
1283 
1284 	return newTuple;
1285 }
_vsscanf_s_l(_Buffer: *const ::std::os::raw::c_char, _Format: *const ::std::os::raw::c_char, _Locale: _locale_t, _ArgList: va_list) -> ::std::os::raw::c_int1286 
1287 /*
1288  * heap_deform_tuple
1289  *		Given a tuple, extract data into values/isnull arrays; this is
1290  *		the inverse of heap_form_tuple.
1291  *
1292  *		Storage for the values/isnull arrays is provided by the caller;
1293  *		it should be sized according to tupleDesc->natts not
1294  *		HeapTupleHeaderGetNatts(tuple->t_data).
1295  *
1296  *		Note that for pass-by-reference datatypes, the pointer placed
1297  *		in the Datum will point into the given tuple.
1298  *
1299  *		When all or most of a tuple's fields need to be extracted,
1300  *		this routine will be significantly quicker than a loop around
1301  *		heap_getattr; the loop will become O(N^2) as soon as any
1302  *		noncacheable attribute offsets are involved.
1303  */
1304 void
1305 heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
1306 				  Datum *values, bool *isnull)
1307 {
1308 	HeapTupleHeader tup = tuple->t_data;
1309 	bool		hasnulls = HeapTupleHasNulls(tuple);
1310 	int			tdesc_natts = tupleDesc->natts;
1311 	int			natts;			/* number of atts to extract */
1312 	int			attnum;
1313 	char	   *tp;				/* ptr to tuple data */
1314 	uint32		off;			/* offset in tuple data */
1315 	bits8	   *bp = tup->t_bits;	/* ptr to null bitmap in tuple */
1316 	bool		slow = false;	/* can we use/set attcacheoff? */
1317 
1318 	natts = HeapTupleHeaderGetNatts(tup);
1319 
1320 	/*
1321 	 * In inheritance situations, it is possible that the given tuple actually
1322 	 * has more fields than the caller is expecting.  Don't run off the end of
1323 	 * the caller's arrays.
1324 	 */
1325 	natts = Min(natts, tdesc_natts);
1326 
1327 	tp = (char *) tup + tup->t_hoff;
1328 
1329 	off = 0;
1330 
1331 	for (attnum = 0; attnum < natts; attnum++)
1332 	{
1333 		Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum);
1334 
1335 		if (hasnulls && att_isnull(attnum, bp))
1336 		{
1337 			values[attnum] = (Datum) 0;
1338 			isnull[attnum] = true;
1339 			slow = true;		/* can't use attcacheoff anymore */
1340 			continue;
1341 		}
1342 
1343 		isnull[attnum] = false;
1344 
1345 		if (!slow && thisatt->attcacheoff >= 0)
1346 			off = thisatt->attcacheoff;
1347 		else if (thisatt->attlen == -1)
1348 		{
1349 			/*
1350 			 * We can only cache the offset for a varlena attribute if the
1351 			 * offset is already suitably aligned, so that there would be no
1352 			 * pad bytes in any case: then the offset will be valid for either
1353 			 * an aligned or unaligned value.
1354 			 */
1355 			if (!slow &&
1356 				off == att_align_nominal(off, thisatt->attalign))
1357 				thisatt->attcacheoff = off;
1358 			else
1359 			{
1360 				off = att_align_pointer(off, thisatt->attalign, -1,
1361 										tp + off);
1362 				slow = true;
1363 			}
1364 		}
1365 		else
1366 		{
1367 			/* not varlena, so safe to use att_align_nominal */
1368 			off = att_align_nominal(off, thisatt->attalign);
1369 
1370 			if (!slow)
1371 				thisatt->attcacheoff = off;
1372 		}
1373 
1374 		values[attnum] = fetchatt(thisatt, tp + off);
1375 
1376 		off = att_addlength_pointer(off, thisatt->attlen, tp + off);
1377 
1378 		if (thisatt->attlen <= 0)
1379 			slow = true;		/* can't use attcacheoff anymore */
1380 	}
1381 
1382 	/*
1383 	 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1384 	 * rest as nulls or missing values as appropriate.
1385 	 */
1386 	for (; attnum < tdesc_natts; attnum++)
1387 		values[attnum] = getmissingattr(tupleDesc, attnum + 1, &isnull[attnum]);
1388 }
1389 
1390 /*
clearok(arg1: *mut WINDOW, arg2: _bool) -> ::std::os::raw::c_int1391  * slot_deform_tuple
1392  *		Given a TupleTableSlot, extract data from the slot's physical tuple
1393  *		into its Datum/isnull arrays.  Data is extracted up through the
1394  *		natts'th column (caller must ensure this is a legal column number).
1395  *
1396  *		This is essentially an incremental version of heap_deform_tuple:
1397  *		on each call we extract attributes up to the one needed, without
1398  *		re-computing information about previously extracted attributes.
1399  *		slot->tts_nvalid is the number of attributes already extracted.
1400  */
1401 static void
1402 slot_deform_tuple(TupleTableSlot *slot, int natts)
1403 {
1404 	HeapTuple	tuple = slot->tts_tuple;
1405 	TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
1406 	Datum	   *values = slot->tts_values;
1407 	bool	   *isnull = slot->tts_isnull;
1408 	HeapTupleHeader tup = tuple->t_data;
1409 	bool		hasnulls = HeapTupleHasNulls(tuple);
1410 	int			attnum;
1411 	char	   *tp;				/* ptr to tuple data */
1412 	uint32		off;			/* offset in tuple data */
1413 	bits8	   *bp = tup->t_bits;	/* ptr to null bitmap in tuple */
1414 	bool		slow;			/* can we use/set attcacheoff? */
1415 
1416 	/*
1417 	 * Check whether the first call for this tuple, and initialize or restore
1418 	 * loop state.
1419 	 */
1420 	attnum = slot->tts_nvalid;
1421 	if (attnum == 0)
1422 	{
1423 		/* Start from the first attribute */
1424 		off = 0;
1425 		slow = false;
1426 	}
1427 	else
1428 	{
1429 		/* Restore state from previous execution */
1430 		off = slot->tts_off;
1431 		slow = slot->tts_slow;
1432 	}
1433 
1434 	tp = (char *) tup + tup->t_hoff;
1435 
1436 	for (; attnum < natts; attnum++)
1437 	{
1438 		Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum);
1439 
1440 		if (hasnulls && att_isnull(attnum, bp))
1441 		{
1442 			values[attnum] = (Datum) 0;
1443 			isnull[attnum] = true;
1444 			slow = true;		/* can't use attcacheoff anymore */
1445 			continue;
1446 		}
1447 
1448 		isnull[attnum] = false;
1449 
1450 		if (!slow && thisatt->attcacheoff >= 0)
1451 			off = thisatt->attcacheoff;
1452 		else if (thisatt->attlen == -1)
1453 		{
1454 			/*
1455 			 * We can only cache the offset for a varlena attribute if the
1456 			 * offset is already suitably aligned, so that there would be no
1457 			 * pad bytes in any case: then the offset will be valid for either
1458 			 * an aligned or unaligned value.
1459 			 */
1460 			if (!slow &&
1461 				off == att_align_nominal(off, thisatt->attalign))
1462 				thisatt->attcacheoff = off;
1463 			else
1464 			{
1465 				off = att_align_pointer(off, thisatt->attalign, -1,
1466 										tp + off);
1467 				slow = true;
1468 			}
1469 		}
1470 		else
1471 		{
1472 			/* not varlena, so safe to use att_align_nominal */
1473 			off = att_align_nominal(off, thisatt->attalign);
1474 
1475 			if (!slow)
1476 				thisatt->attcacheoff = off;
1477 		}
1478 
1479 		values[attnum] = fetchatt(thisatt, tp + off);
1480 
1481 		off = att_addlength_pointer(off, thisatt->attlen, tp + off);
1482 
1483 		if (thisatt->attlen <= 0)
1484 			slow = true;		/* can't use attcacheoff anymore */
1485 	}
1486 
1487 	/*
1488 	 * Save state for next execution
1489 	 */
1490 	slot->tts_nvalid = attnum;
1491 	slot->tts_off = off;
1492 	slot->tts_slow = slow;
1493 }
1494 
1495 /*
1496  * slot_getattr
1497  *		This function fetches an attribute of the slot's current tuple.
mvaddchstr(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: *const chtype) -> ::std::os::raw::c_int1498  *		It is functionally equivalent to heap_getattr, but fetches of
1499  *		multiple attributes of the same tuple will be optimized better,
1500  *		because we avoid O(N^2) behavior from multiple calls of
1501  *		nocachegetattr(), even when attcacheoff isn't usable.
1502  *
1503  *		A difference from raw heap_getattr is that attnums beyond the
1504  *		slot's tupdesc's last attribute will be considered NULL even
1505  *		when the physical tuple is longer than the tupdesc.
1506  */
1507 Datum
1508 slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
1509 {
1510 	HeapTuple	tuple = slot->tts_tuple;
1511 	TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
1512 	HeapTupleHeader tup;
1513 
1514 	/*
1515 	 * system attributes are handled by heap_getsysattr
1516 	 */
1517 	if (attnum <= 0)
1518 	{
1519 		if (tuple == NULL)		/* internal error */
1520 			elog(ERROR, "cannot extract system attribute from virtual tuple");
1521 		if (tuple == &(slot->tts_minhdr))	/* internal error */
1522 			elog(ERROR, "cannot extract system attribute from minimal tuple");
1523 		return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
1524 	}
1525 
1526 	/*
1527 	 * fast path if desired attribute already cached
1528 	 */
1529 	if (attnum <= slot->tts_nvalid)
1530 	{
1531 		*isnull = slot->tts_isnull[attnum - 1];
1532 		return slot->tts_values[attnum - 1];
1533 	}
1534 
1535 	/*
1536 	 * return NULL if attnum is out of range according to the tupdesc
1537 	 */
1538 	if (attnum > tupleDesc->natts)
1539 	{
1540 		*isnull = true;
1541 		return (Datum) 0;
1542 	}
1543 
1544 	/*
1545 	 * otherwise we had better have a physical tuple (tts_nvalid should equal
1546 	 * natts in all virtual-tuple cases)
1547 	 */
1548 	if (tuple == NULL)			/* internal error */
1549 		elog(ERROR, "cannot extract attribute from empty tuple slot");
1550 
1551 	/*
1552 	 * return NULL or missing value if attnum is out of range according to the
1553 	 * tuple
1554 	 *
1555 	 * (We have to check this separately because of various inheritance and
1556 	 * table-alteration scenarios: the tuple could be either longer or shorter
1557 	 * than the tupdesc.)
1558 	 */
1559 	tup = tuple->t_data;
1560 	if (attnum > HeapTupleHeaderGetNatts(tup))
1561 		return getmissingattr(slot->tts_tupleDescriptor, attnum, isnull);
1562 
1563 	/*
1564 	 * check if target attribute is null: no point in groveling through tuple
1565 	 */
1566 	if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
1567 	{
1568 		*isnull = true;
1569 		return (Datum) 0;
1570 	}
1571 
1572 	/*
1573 	 * If the attribute's column has been dropped, we force a NULL result.
1574 	 * This case should not happen in normal use, but it could happen if we
1575 	 * are executing a plan cached before the column was dropped.
1576 	 */
1577 	if (TupleDescAttr(tupleDesc, attnum - 1)->attisdropped)
1578 	{
1579 		*isnull = true;
1580 		return (Datum) 0;
1581 	}
1582 
1583 	/*
1584 	 * Extract the attribute, along with any preceding attributes.
1585 	 */
1586 	slot_deform_tuple(slot, attnum);
1587 
1588 	/*
1589 	 * The result is acquired from tts_values array.
1590 	 */
1591 	*isnull = slot->tts_isnull[attnum - 1];
1592 	return slot->tts_values[attnum - 1];
1593 }
mvwaddchnstr(arg1: *mut WINDOW, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *const chtype, arg5: ::std::os::raw::c_int) -> ::std::os::raw::c_int1594 
1595 /*
1596  * slot_getallattrs
1597  *		This function forces all the entries of the slot's Datum/isnull
1598  *		arrays to be valid.  The caller may then extract data directly
1599  *		from those arrays instead of using slot_getattr.
1600  */
1601 void
1602 slot_getallattrs(TupleTableSlot *slot)
1603 {
1604 	int			tdesc_natts = slot->tts_tupleDescriptor->natts;
1605 	int			attnum;
1606 	HeapTuple	tuple;
1607 
1608 	/* Quick out if we have 'em all already */
1609 	if (slot->tts_nvalid == tdesc_natts)
1610 		return;
1611 
1612 	/*
1613 	 * otherwise we had better have a physical tuple (tts_nvalid should equal
1614 	 * natts in all virtual-tuple cases)
1615 	 */
1616 	tuple = slot->tts_tuple;
1617 	if (tuple == NULL)			/* internal error */
1618 		elog(ERROR, "cannot extract attribute from empty tuple slot");
1619 
1620 	/*
1621 	 * load up any slots available from physical tuple
1622 	 */
1623 	attnum = HeapTupleHeaderGetNatts(tuple->t_data);
1624 	attnum = Min(attnum, tdesc_natts);
1625 
1626 	slot_deform_tuple(slot, attnum);
1627 
1628 	attnum = slot->tts_nvalid;
1629 
1630 	/*
1631 	 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1632 	 * rest as NULLS or missing values.
1633 	 */
1634 	if (attnum < tdesc_natts)
1635 		slot_getmissingattrs(slot, attnum, tdesc_natts);
1636 
1637 	slot->tts_nvalid = tdesc_natts;
1638 }
1639 
1640 /*
1641  * slot_getsomeattrs
1642  *		This function forces the entries of the slot's Datum/isnull
mvwgetstr(arg1: *mut WINDOW, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *mut ::std::os::raw::c_char) -> ::std::os::raw::c_int1643  *		arrays to be valid at least up through the attnum'th entry.
1644  */
1645 void
1646 slot_getsomeattrs(TupleTableSlot *slot, int attnum)
1647 {
1648 	HeapTuple	tuple;
1649 	int			attno;
1650 
1651 	/* Quick out if we have 'em all already */
1652 	if (slot->tts_nvalid >= attnum)
1653 		return;
1654 
1655 	/* Check for caller error */
1656 	if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
1657 		elog(ERROR, "invalid attribute number %d", attnum);
1658 
1659 	/*
1660 	 * otherwise we had better have a physical tuple (tts_nvalid should equal
1661 	 * natts in all virtual-tuple cases)
1662 	 */
1663 	tuple = slot->tts_tuple;
1664 	if (tuple == NULL)			/* internal error */
1665 		elog(ERROR, "cannot extract attribute from empty tuple slot");
1666 
1667 	/*
1668 	 * load up any slots available from physical tuple
1669 	 */
1670 	attno = HeapTupleHeaderGetNatts(tuple->t_data);
1671 	attno = Min(attno, attnum);
1672 
1673 	slot_deform_tuple(slot, attno);
1674 
1675 	attno = slot->tts_nvalid;
1676 
1677 	/*
1678 	 * If tuple doesn't have all the atts indicated by attnum, read the rest
1679 	 * as NULLs or missing values
1680 	 */
1681 	if (attno < attnum)
1682 		slot_getmissingattrs(slot, attno, attnum);
1683 
1684 	slot->tts_nvalid = attnum;
1685 }
mvwinsstr(arg1: *mut WINDOW, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int1686 
1687 /*
1688  * slot_attisnull
1689  *		Detect whether an attribute of the slot is null, without
1690  *		actually fetching it.
1691  */
1692 bool
1693 slot_attisnull(TupleTableSlot *slot, int attnum)
1694 {
1695 	HeapTuple	tuple = slot->tts_tuple;
1696 	TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
1697 
1698 	/*
1699 	 * system attributes are handled by heap_attisnull
1700 	 */
1701 	if (attnum <= 0)
1702 	{
1703 		if (tuple == NULL)		/* internal error */
1704 			elog(ERROR, "cannot extract system attribute from virtual tuple");
1705 		if (tuple == &(slot->tts_minhdr))	/* internal error */
1706 			elog(ERROR, "cannot extract system attribute from minimal tuple");
1707 		return heap_attisnull(tuple, attnum, tupleDesc);
1708 	}
1709 
1710 	/*
1711 	 * fast path if desired attribute already cached
1712 	 */
1713 	if (attnum <= slot->tts_nvalid)
1714 		return slot->tts_isnull[attnum - 1];
1715 
1716 	/*
1717 	 * return NULL if attnum is out of range according to the tupdesc
1718 	 */
1719 	if (attnum > tupleDesc->natts)
1720 		return true;
1721 
1722 	/*
1723 	 * otherwise we had better have a physical tuple (tts_nvalid should equal
1724 	 * natts in all virtual-tuple cases)
1725 	 */
1726 	if (tuple == NULL)			/* internal error */
1727 		elog(ERROR, "cannot extract attribute from empty tuple slot");
1728 
1729 	/* and let the tuple tell it */
1730 	return heap_attisnull(tuple, attnum, tupleDesc);
1731 }
noecho() -> ::std::os::raw::c_int1732 
1733 /*
1734  * slot_getsysattr
1735  *		This function fetches a system attribute of the slot's current tuple.
1736  *		Unlike slot_getattr, if the slot does not contain system attributes,
1737  *		this will return false (with a NULL attribute value) instead of
1738  *		throwing an error.
1739  */
1740 bool
1741 slot_getsysattr(TupleTableSlot *slot, int attnum,
1742 				Datum *value, bool *isnull)
1743 {
1744 	HeapTuple	tuple = slot->tts_tuple;
1745 
1746 	Assert(attnum < 0);			/* else caller error */
1747 	if (tuple == NULL ||
1748 		tuple == &(slot->tts_minhdr))
1749 	{
1750 		/* No physical tuple, or minimal tuple, so fail */
1751 		*value = (Datum) 0;
1752 		*isnull = true;
1753 		return false;
1754 	}
1755 	*value = heap_getsysattr(tuple, attnum, slot->tts_tupleDescriptor, isnull);
1756 	return true;
1757 }
1758 
1759 /*
printw(arg1: *const ::std::os::raw::c_char, ...) -> ::std::os::raw::c_int1760  * heap_freetuple
1761  */
1762 void
1763 heap_freetuple(HeapTuple htup)
1764 {
1765 	pfree(htup);
1766 }
reset_shell_mode() -> ::std::os::raw::c_int1767 
1768 
1769 /*
1770  * heap_form_minimal_tuple
1771  *		construct a MinimalTuple from the given values[] and isnull[] arrays,
1772  *		which are of the length indicated by tupleDescriptor->natts
1773  *
1774  * This is exactly like heap_form_tuple() except that the result is a
1775  * "minimal" tuple lacking a HeapTupleData header as well as room for system
1776  * columns.
1777  *
1778  * The result is allocated in the current memory context.
1779  */
1780 MinimalTuple
1781 heap_form_minimal_tuple(TupleDesc tupleDescriptor,
1782 						Datum *values,
1783 						bool *isnull)
1784 {
1785 	MinimalTuple tuple;			/* return tuple */
1786 	Size		len,
1787 				data_len;
1788 	int			hoff;
1789 	bool		hasnull = false;
1790 	int			numberOfAttributes = tupleDescriptor->natts;
1791 	int			i;
1792 
1793 	if (numberOfAttributes > MaxTupleAttributeNumber)
1794 		ereport(ERROR,
1795 				(errcode(ERRCODE_TOO_MANY_COLUMNS),
1796 				 errmsg("number of columns (%d) exceeds limit (%d)",
1797 						numberOfAttributes, MaxTupleAttributeNumber)));
1798 
1799 	/*
1800 	 * Check for nulls
1801 	 */
1802 	for (i = 0; i < numberOfAttributes; i++)
1803 	{
1804 		if (isnull[i])
1805 		{
1806 			hasnull = true;
1807 			break;
1808 		}
1809 	}
1810 
1811 	/*
1812 	 * Determine total space needed
1813 	 */
1814 	len = SizeofMinimalTupleHeader;
1815 
1816 	if (hasnull)
1817 		len += BITMAPLEN(numberOfAttributes);
1818 
1819 	if (tupleDescriptor->tdhasoid)
1820 		len += sizeof(Oid);
1821 
1822 	hoff = len = MAXALIGN(len); /* align user data safely */
1823 
1824 	data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1825 
1826 	len += data_len;
1827 
1828 	/*
1829 	 * Allocate and zero the space needed.
1830 	 */
1831 	tuple = (MinimalTuple) palloc0(len);
1832 
1833 	/*
1834 	 * And fill in the information.
1835 	 */
1836 	tuple->t_len = len;
1837 	HeapTupleHeaderSetNatts(tuple, numberOfAttributes);
1838 	tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
1839 
1840 	if (tupleDescriptor->tdhasoid)	/* else leave infomask = 0 */
1841 		tuple->t_infomask = HEAP_HASOID;
1842 
1843 	heap_fill_tuple(tupleDescriptor,
1844 					values,
1845 					isnull,
1846 					(char *) tuple + hoff,
1847 					data_len,
1848 					&tuple->t_infomask,
1849 					(hasnull ? tuple->t_bits : NULL));
1850 
1851 	return tuple;
1852 }
1853 
vline(arg1: chtype, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int1854 /*
1855  * heap_free_minimal_tuple
1856  */
1857 void
1858 heap_free_minimal_tuple(MinimalTuple mtup)
1859 {
1860 	pfree(mtup);
1861 }
1862 
vw_scanw(arg1: *mut WINDOW, arg2: *const ::std::os::raw::c_char, arg3: va_list) -> ::std::os::raw::c_int1863 /*
1864  * heap_copy_minimal_tuple
1865  *		copy a MinimalTuple
1866  *
1867  * The result is allocated in the current memory context.
1868  */
1869 MinimalTuple
1870 heap_copy_minimal_tuple(MinimalTuple mtup)
1871 {
1872 	MinimalTuple result;
1873 
1874 	result = (MinimalTuple) palloc(mtup->t_len);
1875 	memcpy(result, mtup, mtup->t_len);
1876 	return result;
1877 }
1878 
1879 /*
1880  * heap_tuple_from_minimal_tuple
waddstr(arg1: *mut WINDOW, arg2: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int1881  *		create a HeapTuple by copying from a MinimalTuple;
1882  *		system columns are filled with zeroes
1883  *
1884  * The result is allocated in the current memory context.
1885  * The HeapTuple struct, tuple header, and tuple data are all allocated
1886  * as a single palloc() block.
1887  */
1888 HeapTuple
1889 heap_tuple_from_minimal_tuple(MinimalTuple mtup)
1890 {
1891 	HeapTuple	result;
1892 	uint32		len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
1893 
1894 	result = (HeapTuple) palloc(HEAPTUPLESIZE + len);
1895 	result->t_len = len;
1896 	ItemPointerSetInvalid(&(result->t_self));
1897 	result->t_tableOid = InvalidOid;
1898 	result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
1899 	memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
1900 	memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
1901 	return result;
1902 }
1903 
1904 /*
wbkgdset(arg1: *mut WINDOW, arg2: chtype)1905  * minimal_tuple_from_heap_tuple
1906  *		create a MinimalTuple by copying from a HeapTuple
1907  *
1908  * The result is allocated in the current memory context.
1909  */
1910 MinimalTuple
1911 minimal_tuple_from_heap_tuple(HeapTuple htup)
1912 {
1913 	MinimalTuple result;
1914 	uint32		len;
1915 
1916 	Assert(htup->t_len > MINIMAL_TUPLE_OFFSET);
1917 	len = htup->t_len - MINIMAL_TUPLE_OFFSET;
1918 	result = (MinimalTuple) palloc(len);
1919 	memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
1920 	result->t_len = len;
1921 	return result;
1922 }
wclear(arg1: *mut WINDOW) -> ::std::os::raw::c_int1923 
1924 /*
1925  * This mainly exists so JIT can inline the definition, but it's also
1926  * sometimes useful in debugging sessions.
1927  */
1928 size_t
1929 varsize_any(void *p)
1930 {
1931 	return VARSIZE_ANY(p);
1932 }
wechochar(arg1: *mut WINDOW, arg2: chtype) -> ::std::os::raw::c_int1933