@@ -507,99 +507,117 @@ PG_FUNCTION_INFO_V1(heap_tuple_infomask_flags);
507
507
Datum
508
508
heap_tuple_infomask_flags (PG_FUNCTION_ARGS )
509
509
{
510
+ #define HEAP_TUPLE_INFOMASK_COLS 2
511
+ Datum values [HEAP_TUPLE_INFOMASK_COLS ];
512
+ bool nulls [HEAP_TUPLE_INFOMASK_COLS ];
510
513
uint16 t_infomask = PG_GETARG_INT16 (0 );
511
514
uint16 t_infomask2 = PG_GETARG_INT16 (1 );
512
- bool decode_combined = PG_GETARG_BOOL (2 );
513
515
int cnt = 0 ;
514
516
ArrayType * a ;
515
517
int bitcnt ;
516
- Datum * d ;
518
+ Datum * flags ;
519
+ TupleDesc tupdesc ;
520
+ HeapTuple tuple ;
517
521
518
522
if (!superuser ())
519
523
ereport (ERROR ,
520
524
(errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
521
525
errmsg ("must be superuser to use raw page functions" )));
522
526
527
+ /* Build a tuple descriptor for our result type */
528
+ if (get_call_result_type (fcinfo , NULL , & tupdesc ) != TYPEFUNC_COMPOSITE )
529
+ elog (ERROR , "return type must be a row type" );
530
+
523
531
bitcnt = pg_popcount ((const char * ) & t_infomask , sizeof (uint16 )) +
524
532
pg_popcount ((const char * ) & t_infomask2 , sizeof (uint16 ));
525
533
526
- /* If no flags, return an empty array */
534
+ /* Initialize values and NULL flags arrays */
535
+ MemSet (values , 0 , sizeof (values ));
536
+ MemSet (nulls , 0 , sizeof (nulls ));
537
+
538
+ /* If no flags, return a set of empty arrays */
527
539
if (bitcnt <= 0 )
528
- PG_RETURN_POINTER (construct_empty_array (TEXTOID ));
540
+ {
541
+ values [0 ] = PointerGetDatum (construct_empty_array (TEXTOID ));
542
+ values [1 ] = PointerGetDatum (construct_empty_array (TEXTOID ));
543
+ tuple = heap_form_tuple (tupdesc , values , nulls );
544
+ PG_RETURN_DATUM (HeapTupleGetDatum (tuple ));
545
+ }
529
546
530
- d = (Datum * ) palloc0 (sizeof (Datum ) * bitcnt );
547
+ /* build set of raw flags */
548
+ flags = (Datum * ) palloc0 (sizeof (Datum ) * bitcnt );
531
549
532
550
/* decode t_infomask */
533
551
if ((t_infomask & HEAP_HASNULL ) != 0 )
534
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_HASNULL" );
552
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_HASNULL" );
535
553
if ((t_infomask & HEAP_HASVARWIDTH ) != 0 )
536
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_HASVARWIDTH" );
554
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_HASVARWIDTH" );
537
555
if ((t_infomask & HEAP_HASEXTERNAL ) != 0 )
538
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_HASEXTERNAL" );
556
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_HASEXTERNAL" );
539
557
if ((t_infomask & HEAP_HASOID_OLD ) != 0 )
540
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_HASOID_OLD" );
558
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_HASOID_OLD" );
559
+ if ((t_infomask & HEAP_XMAX_KEYSHR_LOCK ) != 0 )
560
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_KEYSHR_LOCK" );
541
561
if ((t_infomask & HEAP_COMBOCID ) != 0 )
542
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_COMBOCID" );
562
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_COMBOCID" );
563
+ if ((t_infomask & HEAP_XMAX_EXCL_LOCK ) != 0 )
564
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_EXCL_LOCK" );
565
+ if ((t_infomask & HEAP_XMAX_LOCK_ONLY ) != 0 )
566
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_LOCK_ONLY" );
567
+ if ((t_infomask & HEAP_XMIN_COMMITTED ) != 0 )
568
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_XMIN_COMMITTED" );
569
+ if ((t_infomask & HEAP_XMIN_INVALID ) != 0 )
570
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_XMIN_INVALID" );
543
571
if ((t_infomask & HEAP_XMAX_COMMITTED ) != 0 )
544
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_COMMITTED" );
572
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_COMMITTED" );
545
573
if ((t_infomask & HEAP_XMAX_INVALID ) != 0 )
546
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_INVALID" );
574
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_INVALID" );
575
+ if ((t_infomask & HEAP_XMAX_IS_MULTI ) != 0 )
576
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_IS_MULTI" );
547
577
if ((t_infomask & HEAP_UPDATED ) != 0 )
548
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_UPDATED" );
549
-
550
- /* decode combined masks of t_infomaks */
551
- if (decode_combined && (t_infomask & HEAP_XMAX_SHR_LOCK ) != 0 )
552
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_SHR_LOCK" );
553
- else
554
- {
555
- if ((t_infomask & HEAP_XMAX_EXCL_LOCK ) != 0 )
556
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_EXCL_LOCK" );
557
- if ((t_infomask & HEAP_XMAX_KEYSHR_LOCK ) != 0 )
558
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_KEYSHR_LOCK" );
559
- }
560
-
561
- if (decode_combined && (t_infomask & HEAP_XMIN_FROZEN ) != 0 )
562
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_XMIN_FROZEN" );
563
- else
564
- {
565
- if ((t_infomask & HEAP_XMIN_COMMITTED ) != 0 )
566
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_XMIN_COMMITTED" );
567
- if ((t_infomask & HEAP_XMIN_INVALID ) != 0 )
568
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_XMIN_INVALID" );
569
- }
570
-
571
- if (decode_combined && (t_infomask & HEAP_MOVED ) != 0 )
572
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_MOVED" );
573
- else
574
- {
575
- if ((t_infomask & HEAP_MOVED_IN ) != 0 )
576
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_MOVED_IN" );
577
- if ((t_infomask & HEAP_MOVED_OFF ) != 0 )
578
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_MOVED_OFF" );
579
- }
580
-
581
- if (decode_combined && HEAP_LOCKED_UPGRADED (t_infomask ))
582
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_LOCKED_UPGRADED" );
583
- else
584
- {
585
- if (HEAP_XMAX_IS_LOCKED_ONLY (t_infomask ))
586
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_LOCK_ONLY" );
587
- if ((t_infomask & HEAP_XMAX_IS_MULTI ) != 0 )
588
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_IS_MULTI" );
589
- }
578
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_UPDATED" );
579
+ if ((t_infomask & HEAP_MOVED_OFF ) != 0 )
580
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_MOVED_OFF" );
581
+ if ((t_infomask & HEAP_MOVED_IN ) != 0 )
582
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_MOVED_IN" );
590
583
591
584
/* decode t_infomask2 */
592
585
if ((t_infomask2 & HEAP_KEYS_UPDATED ) != 0 )
593
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_KEYS_UPDATED" );
586
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_KEYS_UPDATED" );
594
587
if ((t_infomask2 & HEAP_HOT_UPDATED ) != 0 )
595
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_HOT_UPDATED" );
588
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_HOT_UPDATED" );
596
589
if ((t_infomask2 & HEAP_ONLY_TUPLE ) != 0 )
597
- d [cnt ++ ] = CStringGetTextDatum ("HEAP_ONLY_TUPLE" );
590
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_ONLY_TUPLE" );
598
591
592
+ /* build value */
599
593
Assert (cnt <= bitcnt );
600
- a = construct_array (d , cnt , TEXTOID , -1 , false, 'i' );
594
+ a = construct_array (flags , cnt , TEXTOID , -1 , false, 'i' );
595
+ values [0 ] = PointerGetDatum (a );
601
596
602
- pfree (d );
597
+ /*
598
+ * Build set of combined flags. Use the same array as previously, this
599
+ * keeps the code simple.
600
+ */
601
+ cnt = 0 ;
602
+ MemSet (flags , 0 , sizeof (Datum ) * bitcnt );
603
+
604
+ /* decode combined masks of t_infomask */
605
+ if ((t_infomask & HEAP_XMAX_SHR_LOCK ) == HEAP_XMAX_SHR_LOCK )
606
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_XMAX_SHR_LOCK" );
607
+ if ((t_infomask & HEAP_XMIN_FROZEN ) == HEAP_XMIN_FROZEN )
608
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_XMIN_FROZEN" );
609
+ if ((t_infomask & HEAP_MOVED ) == HEAP_MOVED )
610
+ flags [cnt ++ ] = CStringGetTextDatum ("HEAP_MOVED" );
611
+
612
+ /* Build an empty array if there are no combined flags */
613
+ if (cnt == 0 )
614
+ a = construct_empty_array (TEXTOID );
615
+ else
616
+ a = construct_array (flags , cnt , TEXTOID , -1 , false, 'i' );
617
+ pfree (flags );
618
+ values [1 ] = PointerGetDatum (a );
603
619
604
- PG_RETURN_POINTER (a );
620
+ /* Returns the record as Datum */
621
+ tuple = heap_form_tuple (tupdesc , values , nulls );
622
+ PG_RETURN_DATUM (HeapTupleGetDatum (tuple ));
605
623
}
0 commit comments