| 408 | } |
| 409 | |
| 410 | static void |
| 411 | get_tuple_info(TupleDesc tupdesc, int *r_ncolumns, format_t **r_myData, char **data, |
| 412 | FunctionCallInfo fcinfo, FormatConfig *format_out_config) |
| 413 | { |
| 414 | HeapTupleData tuple; |
| 415 | HeapTupleHeader rec = PG_GETARG_HEAPTUPLEHEADER(0); |
| 416 | /* Get our internal description of the formatter */ |
| 417 | *r_ncolumns = tupdesc->natts; |
| 418 | int ncolumns = *r_ncolumns; |
| 419 | *r_myData = (format_t *) FORMATTER_GET_USER_CTX(fcinfo); |
| 420 | format_t *myData = *r_myData; |
| 421 | |
| 422 | if (myData == NULL) |
| 423 | { |
| 424 | myData = palloc(sizeof(format_t)); |
| 425 | *r_myData = myData; |
| 426 | |
| 427 | myData->ncols = ncolumns; |
| 428 | myData->values = palloc(sizeof(Datum) * ncolumns); |
| 429 | myData->nulls = palloc(sizeof(bool) * ncolumns); |
| 430 | initStringInfo( &(myData->one_field) ); |
| 431 | |
| 432 | |
| 433 | init_format_out_config(format_out_config, ncolumns, tupdesc, fcinfo); |
| 434 | |
| 435 | /* Determine required buffer size */ |
| 436 | myData->buflen = format_out_config->fields_tot_size + strlen(format_out_config->line_delimiter); |
| 437 | myData->buflen = Max(128, myData->buflen); /* allocate at least 128 bytes */ |
| 438 | myData->buffer = palloc(myData->buflen + VARHDRSZ); |
| 439 | |
| 440 | FORMATTER_SET_USER_CTX(fcinfo, myData); |
| 441 | } |
| 442 | if (myData->ncols != ncolumns) |
| 443 | elog(ERROR, "formatter_export: unexpected change of output record type"); |
| 444 | |
| 445 | /* break the input tuple into fields */ |
| 446 | tuple.t_len = HeapTupleHeaderGetDatumLength(rec); |
| 447 | ItemPointerSetInvalid(&(tuple.t_self)); |
| 448 | tuple.t_data = rec; |
| 449 | heap_deform_tuple(&tuple, tupdesc, myData->values, myData->nulls); |
| 450 | *data = VARDATA(myData->buffer); |
| 451 | |
| 452 | } |
| 453 | |
| 454 | static int |
| 455 | get_actual_line_size(FormatConfig *format_in_config, char *line_start, int cur_size, int tot_size, PG_FUNCTION_ARGS) |
no test coverage detected