483{
484 HeapTupleHeader td;
485 Oid tupType;
487 TupleDesc tupdesc;
488 HeapTupleData tmptup,
489 *tuple;
490 int i;
491 bool needsep = false;
492 const char *sep;
493
494 sep = use_line_feeds ? ",\n " : ",";
495
496 td = DatumGetHeapTupleHeader(composite);
497
498
499 tupType = HeapTupleHeaderGetTypeId(td);
500 tupTypmod = HeapTupleHeaderGetTypMod(td);
501 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
502
503
504 tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
505 tmptup.t_data = td;
506 tuple = &tmptup;
507
508 appendStringInfoChar(result, '{');
509
510 for (i = 0; i < tupdesc->natts; i++)
511 {
512 Datum val;
513 bool isnull;
514 char *attname;
516 Oid outfuncoid;
517 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
518
519 if (att->attisdropped)
520 continue;
521
522 if (needsep)
523 appendStringInfoString(result, sep);
524 needsep = true;
525
526 attname = NameStr(att->attname);
527 escape_json(result, attname);
528 appendStringInfoChar(result, ':');
529
530 val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
531
532 if (isnull)
533 {
535 outfuncoid = InvalidOid;
536 }
537 else
539
540 datum_to_json(val, isnull, result, tcategory, outfuncoid,
false);
541 }
542
543 appendStringInfoChar(result, '}');
544 ReleaseTupleDesc(tupdesc);
545}
static void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)