From 58bb2cba9b7d2340cebd7f08461080b579cf2532 Mon Sep 17 00:00:00 2001 From: Dilip Kumar Date: Thu, 4 Mar 2021 13:30:47 +0530 Subject: [PATCH v37 1/6] Get datum from tuple which doesn't contain external data Currently, we use HeapTupleGetDatum and HeapTupleHeaderGetDatum whenever we need to convert a tuple to datum. Introduce another version of these routine HeapTupleGetRawDatum and HeapTupleHeaderGetRawDatum respectively so that all the callers who doesn't expect any external data in the tuple can call these new routines. Likewise similar treatment for heap_copy_tuple_as_datum and PG_RETURN_HEAPTUPLEHEADER as well. This is the base patch for the optimization in the next patch therein we can try to optimize the caller of the functions where we expect external varlena by flattening any external toast pointer before forming the tuple. Dilip Kumar based on the idea by Robert Haas --- contrib/dblink/dblink.c | 2 +- contrib/hstore/hstore_io.c | 4 ++-- contrib/hstore/hstore_op.c | 2 +- contrib/old_snapshot/time_mapping.c | 2 +- contrib/pageinspect/brinfuncs.c | 2 +- contrib/pageinspect/btreefuncs.c | 6 +++--- contrib/pageinspect/ginfuncs.c | 6 +++--- contrib/pageinspect/gistfuncs.c | 2 +- contrib/pageinspect/hashfuncs.c | 8 ++++---- contrib/pageinspect/heapfuncs.c | 6 +++--- contrib/pageinspect/rawpage.c | 2 +- contrib/pg_buffercache/pg_buffercache_pages.c | 2 +- contrib/pg_stat_statements/pg_stat_statements.c | 3 ++- contrib/pg_visibility/pg_visibility.c | 13 ++++++++----- contrib/pgcrypto/pgp-pgsql.c | 2 +- contrib/pgstattuple/pgstatapprox.c | 2 +- contrib/pgstattuple/pgstatindex.c | 6 +++--- contrib/pgstattuple/pgstattuple.c | 2 +- contrib/sslinfo/sslinfo.c | 2 +- src/backend/access/common/heaptuple.c | 20 ++++++++++++++++++-- src/backend/access/transam/commit_ts.c | 4 ++-- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlogfuncs.c | 2 +- src/backend/catalog/objectaddress.c | 6 +++--- src/backend/commands/sequence.c | 2 +- src/backend/executor/execExprInterp.c | 15 ++++++++++----- src/backend/replication/slotfuncs.c | 8 ++++---- src/backend/replication/walreceiver.c | 3 ++- src/backend/statistics/mcv.c | 2 +- src/backend/tsearch/wparser.c | 4 ++-- src/backend/utils/adt/acl.c | 2 +- src/backend/utils/adt/datetime.c | 2 +- src/backend/utils/adt/genfile.c | 2 +- src/backend/utils/adt/lockfuncs.c | 4 ++-- src/backend/utils/adt/misc.c | 4 ++-- src/backend/utils/adt/partitionfuncs.c | 2 +- src/backend/utils/adt/pgstatfuncs.c | 6 ++++-- src/backend/utils/adt/rowtypes.c | 4 ++-- src/backend/utils/adt/tsvector_op.c | 4 ++-- src/backend/utils/misc/guc.c | 2 +- src/backend/utils/misc/pg_controldata.c | 8 ++++---- src/include/access/htup_details.h | 1 + src/include/fmgr.h | 5 +++++ src/include/funcapi.h | 15 ++++++++++++++- src/pl/plperl/plperl.c | 4 ++-- src/pl/tcl/pltcl.c | 4 ++-- src/test/modules/test_predtest/test_predtest.c | 3 ++- 48 files changed, 132 insertions(+), 84 deletions(-) diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index 3a0beaa..5a41116 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -1630,7 +1630,7 @@ dblink_get_pkey(PG_FUNCTION_ARGS) tuple = BuildTupleFromCStrings(attinmeta, values); /* make the tuple into a datum */ - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c index b3304ff..cc7a8e0 100644 --- a/contrib/hstore/hstore_io.c +++ b/contrib/hstore/hstore_io.c @@ -1137,14 +1137,14 @@ hstore_populate_record(PG_FUNCTION_ARGS) * check domain constraints before deciding we're done. */ if (argtype != tupdesc->tdtypeid) - domain_check(HeapTupleGetDatum(rettuple), false, + domain_check(HeapTupleGetRawDatum(rettuple), false, argtype, &my_extra->domain_info, fcinfo->flinfo->fn_mcxt); ReleaseTupleDesc(tupdesc); - PG_RETURN_DATUM(HeapTupleGetDatum(rettuple)); + PG_RETURN_HEAPTUPLEHEADER_RAW(rettuple->t_data); } diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c index dd79d01..d466f6c 100644 --- a/contrib/hstore/hstore_op.c +++ b/contrib/hstore/hstore_op.c @@ -1067,7 +1067,7 @@ hstore_each(PG_FUNCTION_ARGS) } tuple = heap_form_tuple(funcctx->tuple_desc, dvalues, nulls); - res = HeapTupleGetDatum(tuple); + res = HeapTupleGetRawDatum(tuple); SRF_RETURN_NEXT(funcctx, PointerGetDatum(res)); } diff --git a/contrib/old_snapshot/time_mapping.c b/contrib/old_snapshot/time_mapping.c index 3df0717..5d517c8 100644 --- a/contrib/old_snapshot/time_mapping.c +++ b/contrib/old_snapshot/time_mapping.c @@ -72,7 +72,7 @@ pg_old_snapshot_time_mapping(PG_FUNCTION_ARGS) tuple = MakeOldSnapshotTimeMappingTuple(funcctx->tuple_desc, mapping); ++mapping->current_index; - SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); + SRF_RETURN_NEXT(funcctx, HeapTupleGetRawDatum(tuple)); } SRF_RETURN_DONE(funcctx); diff --git a/contrib/pageinspect/brinfuncs.c b/contrib/pageinspect/brinfuncs.c index 0e3c2de..6262946 100644 --- a/contrib/pageinspect/brinfuncs.c +++ b/contrib/pageinspect/brinfuncs.c @@ -366,7 +366,7 @@ brin_metapage_info(PG_FUNCTION_ARGS) htup = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + PG_RETURN_HEAPTUPLEHEADER_RAW(htup->t_data); } /* diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c index b7725b5..f0028e4 100644 --- a/contrib/pageinspect/btreefuncs.c +++ b/contrib/pageinspect/btreefuncs.c @@ -263,7 +263,7 @@ bt_page_stats_internal(PG_FUNCTION_ARGS, enum pageinspect_version ext_version) tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc), values); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); PG_RETURN_DATUM(result); } @@ -436,7 +436,7 @@ bt_page_print_tuples(struct user_args *uargs) /* Build and return the result tuple */ tuple = heap_form_tuple(uargs->tupd, values, nulls); - return HeapTupleGetDatum(tuple); + return HeapTupleGetRawDatum(tuple); } /*------------------------------------------------------- @@ -766,7 +766,7 @@ bt_metap(PG_FUNCTION_ARGS) tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc), values); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); UnlockReleaseBuffer(buffer); relation_close(rel, AccessShareLock); diff --git a/contrib/pageinspect/ginfuncs.c b/contrib/pageinspect/ginfuncs.c index e425cbc..77dd559 100644 --- a/contrib/pageinspect/ginfuncs.c +++ b/contrib/pageinspect/ginfuncs.c @@ -82,7 +82,7 @@ gin_metapage_info(PG_FUNCTION_ARGS) /* Build and return the result tuple. */ resultTuple = heap_form_tuple(tupdesc, values, nulls); - return HeapTupleGetDatum(resultTuple); + return HeapTupleGetRawDatum(resultTuple); } @@ -150,7 +150,7 @@ gin_page_opaque_info(PG_FUNCTION_ARGS) /* Build and return the result tuple. */ resultTuple = heap_form_tuple(tupdesc, values, nulls); - return HeapTupleGetDatum(resultTuple); + return HeapTupleGetRawDatum(resultTuple); } typedef struct gin_leafpage_items_state @@ -254,7 +254,7 @@ gin_leafpage_items(PG_FUNCTION_ARGS) /* Build and return the result tuple. */ resultTuple = heap_form_tuple(inter_call_data->tupd, values, nulls); - result = HeapTupleGetDatum(resultTuple); + result = HeapTupleGetRawDatum(resultTuple); inter_call_data->seg = GinNextPostingListSegment(cur); diff --git a/contrib/pageinspect/gistfuncs.c b/contrib/pageinspect/gistfuncs.c index eb9f630..dbf34f8 100644 --- a/contrib/pageinspect/gistfuncs.c +++ b/contrib/pageinspect/gistfuncs.c @@ -89,7 +89,7 @@ gist_page_opaque_info(PG_FUNCTION_ARGS) /* Build and return the result tuple. */ resultTuple = heap_form_tuple(tupdesc, values, nulls); - return HeapTupleGetDatum(resultTuple); + return HeapTupleGetRawDatum(resultTuple); } Datum diff --git a/contrib/pageinspect/hashfuncs.c b/contrib/pageinspect/hashfuncs.c index ff01119..957ee5b 100644 --- a/contrib/pageinspect/hashfuncs.c +++ b/contrib/pageinspect/hashfuncs.c @@ -273,7 +273,7 @@ hash_page_stats(PG_FUNCTION_ARGS) tuple = heap_form_tuple(tupleDesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); + PG_RETURN_HEAPTUPLEHEADER_RAW(tuple->t_data); } /* @@ -368,7 +368,7 @@ hash_page_items(PG_FUNCTION_ARGS) values[j] = Int64GetDatum((int64) hashkey); tuple = heap_form_tuple(fctx->attinmeta->tupdesc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); uargs->offset = uargs->offset + 1; @@ -499,7 +499,7 @@ hash_bitmap_info(PG_FUNCTION_ARGS) tuple = heap_form_tuple(tupleDesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); + PG_RETURN_HEAPTUPLEHEADER_RAW(tuple->t_data); } /* ------------------------------------------------ @@ -577,5 +577,5 @@ hash_metapage_info(PG_FUNCTION_ARGS) tuple = heap_form_tuple(tupleDesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); + PG_RETURN_HEAPTUPLEHEADER_RAW(tuple->t_data); } diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c index f6760eb..3a050ee 100644 --- a/contrib/pageinspect/heapfuncs.c +++ b/contrib/pageinspect/heapfuncs.c @@ -282,7 +282,7 @@ heap_page_items(PG_FUNCTION_ARGS) /* Build and return the result tuple. */ resultTuple = heap_form_tuple(inter_call_data->tupd, values, nulls); - result = HeapTupleGetDatum(resultTuple); + result = HeapTupleGetRawDatum(resultTuple); inter_call_data->offset++; @@ -540,7 +540,7 @@ heap_tuple_infomask_flags(PG_FUNCTION_ARGS) values[0] = PointerGetDatum(construct_empty_array(TEXTOID)); values[1] = PointerGetDatum(construct_empty_array(TEXTOID)); tuple = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); + PG_RETURN_HEAPTUPLEHEADER_RAW(tuple->t_data); } /* build set of raw flags */ @@ -618,5 +618,5 @@ heap_tuple_infomask_flags(PG_FUNCTION_ARGS) /* Returns the record as Datum */ tuple = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); + PG_RETURN_HEAPTUPLEHEADER_RAW(tuple->t_data); } diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c index 7272b21..e7aab86 100644 --- a/contrib/pageinspect/rawpage.c +++ b/contrib/pageinspect/rawpage.c @@ -328,7 +328,7 @@ page_header(PG_FUNCTION_ARGS) memset(nulls, 0, sizeof(nulls)); tuple = heap_form_tuple(tupdesc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); PG_RETURN_DATUM(result); } diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c index 1bd579f..1fd405e 100644 --- a/contrib/pg_buffercache/pg_buffercache_pages.c +++ b/contrib/pg_buffercache/pg_buffercache_pages.c @@ -230,7 +230,7 @@ pg_buffercache_pages(PG_FUNCTION_ARGS) /* Build and return the tuple. */ tuple = heap_form_tuple(fctx->tupdesc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbf..7eb80d5 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1922,7 +1922,8 @@ pg_stat_statements_info(PG_FUNCTION_ARGS) values[0] = Int64GetDatum(stats.dealloc); values[1] = TimestampTzGetDatum(stats.stats_reset); - PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); + PG_RETURN_HEAPTUPLEHEADER_RAW( + heap_form_tuple(tupdesc, values, nulls)->t_data); } /* diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c index dd0c124..43bb2ab 100644 --- a/contrib/pg_visibility/pg_visibility.c +++ b/contrib/pg_visibility/pg_visibility.c @@ -97,7 +97,8 @@ pg_visibility_map(PG_FUNCTION_ARGS) relation_close(rel, AccessShareLock); - PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); + PG_RETURN_HEAPTUPLEHEADER_RAW( + heap_form_tuple(tupdesc, values, nulls)->t_data); } /* @@ -156,7 +157,8 @@ pg_visibility(PG_FUNCTION_ARGS) relation_close(rel, AccessShareLock); - PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); + PG_RETURN_HEAPTUPLEHEADER_RAW( + heap_form_tuple(tupdesc, values, nulls)->t_data); } /* @@ -197,7 +199,7 @@ pg_visibility_map_rel(PG_FUNCTION_ARGS) info->next++; tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); + SRF_RETURN_NEXT(funcctx, HeapTupleGetRawDatum(tuple)); } SRF_RETURN_DONE(funcctx); @@ -243,7 +245,7 @@ pg_visibility_rel(PG_FUNCTION_ARGS) info->next++; tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); + SRF_RETURN_NEXT(funcctx, HeapTupleGetRawDatum(tuple)); } SRF_RETURN_DONE(funcctx); @@ -303,7 +305,8 @@ pg_visibility_map_summary(PG_FUNCTION_ARGS) values[0] = Int64GetDatum(all_visible); values[1] = Int64GetDatum(all_frozen); - PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); + PG_RETURN_HEAPTUPLEHEADER_RAW( + heap_form_tuple(tupdesc, values, nulls)->t_data); } /* diff --git a/contrib/pgcrypto/pgp-pgsql.c b/contrib/pgcrypto/pgp-pgsql.c index 0536bfb..333f7fd 100644 --- a/contrib/pgcrypto/pgp-pgsql.c +++ b/contrib/pgcrypto/pgp-pgsql.c @@ -973,7 +973,7 @@ pgp_armor_headers(PG_FUNCTION_ARGS) /* build a tuple */ tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); - SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); + SRF_RETURN_NEXT(funcctx, HeapTupleGetRawDatum(tuple)); } } diff --git a/contrib/pgstattuple/pgstatapprox.c b/contrib/pgstattuple/pgstatapprox.c index 1fe193b..147c8d2 100644 --- a/contrib/pgstattuple/pgstatapprox.c +++ b/contrib/pgstattuple/pgstatapprox.c @@ -314,5 +314,5 @@ pgstattuple_approx_internal(Oid relid, FunctionCallInfo fcinfo) values[i++] = Float8GetDatum(stat.free_percent); ret = heap_form_tuple(tupdesc, values, nulls); - return HeapTupleGetDatum(ret); + return HeapTupleGetRawDatum(ret); } diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c index 5368bb3..7d74c31 100644 --- a/contrib/pgstattuple/pgstatindex.c +++ b/contrib/pgstattuple/pgstatindex.c @@ -362,7 +362,7 @@ pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo) tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc), values); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); } return result; @@ -571,7 +571,7 @@ pgstatginindex_internal(Oid relid, FunctionCallInfo fcinfo) * Build and return the tuple */ tuple = heap_form_tuple(tupleDesc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); return result; } @@ -727,7 +727,7 @@ pgstathashindex(PG_FUNCTION_ARGS) values[7] = Float8GetDatum(free_percent); tuple = heap_form_tuple(tupleDesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); + PG_RETURN_HEAPTUPLEHEADER_RAW(tuple->t_data); } /* ------------------------------------------------- diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c index 21fdeff..70b8bf0 100644 --- a/contrib/pgstattuple/pgstattuple.c +++ b/contrib/pgstattuple/pgstattuple.c @@ -147,7 +147,7 @@ build_pgstattuple_type(pgstattuple_type *stat, FunctionCallInfo fcinfo) tuple = BuildTupleFromCStrings(attinmeta, values); /* make the tuple into a datum */ - return HeapTupleGetDatum(tuple); + return HeapTupleGetRawDatum(tuple); } /* ---------- diff --git a/contrib/sslinfo/sslinfo.c b/contrib/sslinfo/sslinfo.c index 30cae0b..53801e9 100644 --- a/contrib/sslinfo/sslinfo.c +++ b/contrib/sslinfo/sslinfo.c @@ -460,7 +460,7 @@ ssl_extension_info(PG_FUNCTION_ARGS) /* Build tuple */ tuple = heap_form_tuple(fctx->tupdesc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); if (BIO_free(membuf) != 1) elog(ERROR, "could not free OpenSSL BIO structure"); diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index 0b56b0f..6061376 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -983,8 +983,6 @@ heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc) Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc) { - HeapTupleHeader td; - /* * If the tuple contains any external TOAST pointers, we have to inline * those fields to meet the conventions for composite-type Datums. @@ -993,6 +991,24 @@ heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc) return toast_flatten_tuple_to_datum(tuple->t_data, tuple->t_len, tupleDesc); + else + return heap_copy_tuple_as_raw_datum(tuple, tupleDesc); +} + +/* ---------------- + * heap_copy_tuple_as_raw_datum + * + * copy a tuple as a composite-type Datum, but the input tuple should not + * contain any external data. + * ---------------- + */ +Datum +heap_copy_tuple_as_raw_datum(HeapTuple tuple, TupleDesc tupleDesc) +{ + HeapTupleHeader td; + + /* the tuple should not contains any external TOAST pointers */ + Assert(!HeapTupleHasExternal(tuple)); /* * Fast path for easy case: just make a palloc'd copy and insert the diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c index 48e8d66..015c841 100644 --- a/src/backend/access/transam/commit_ts.c +++ b/src/backend/access/transam/commit_ts.c @@ -469,7 +469,7 @@ pg_last_committed_xact(PG_FUNCTION_ARGS) htup = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + PG_RETURN_HEAPTUPLEHEADER_RAW(htup->t_data); } /* @@ -518,7 +518,7 @@ pg_xact_commit_timestamp_origin(PG_FUNCTION_ARGS) htup = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + PG_RETURN_HEAPTUPLEHEADER_RAW(htup->t_data); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1..b44066a 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -3399,7 +3399,7 @@ pg_get_multixact_members(PG_FUNCTION_ARGS) multi->iter++; pfree(values[0]); - SRF_RETURN_NEXT(funccxt, HeapTupleGetDatum(tuple)); + SRF_RETURN_NEXT(funccxt, HeapTupleGetRawDatum(tuple)); } SRF_RETURN_DONE(funccxt); diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 6023e7c..3f48597 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -787,7 +787,7 @@ pg_prepared_xact(PG_FUNCTION_ARGS) values[4] = ObjectIdGetDatum(proc->databaseId); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c index f363a4c..f60d6f1 100644 --- a/src/backend/access/transam/xlogfuncs.c +++ b/src/backend/access/transam/xlogfuncs.c @@ -487,7 +487,7 @@ pg_walfile_name_offset(PG_FUNCTION_ARGS) */ resultHeapTuple = heap_form_tuple(resultTupleDesc, values, isnull); - result = HeapTupleGetDatum(resultHeapTuple); + result = HeapTupleGetRawDatum(resultHeapTuple); PG_RETURN_DATUM(result); } diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 6d88b69..7cd62e7 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -2355,7 +2355,7 @@ pg_get_object_address(PG_FUNCTION_ARGS) htup = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + PG_RETURN_HEAPTUPLEHEADER_RAW(htup->t_data); } /* @@ -4233,7 +4233,7 @@ pg_identify_object(PG_FUNCTION_ARGS) htup = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + PG_RETURN_HEAPTUPLEHEADER_RAW(htup->t_data); } /* @@ -4304,7 +4304,7 @@ pg_identify_object_as_address(PG_FUNCTION_ARGS) htup = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + PG_RETURN_HEAPTUPLEHEADER_RAW(htup->t_data); } /* diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 0415df9..f566e1e 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -1834,7 +1834,7 @@ pg_sequence_parameters(PG_FUNCTION_ARGS) ReleaseSysCache(pgstuple); - return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull)); + return HeapTupleGetRawDatum(heap_form_tuple(tupdesc, values, isnull)); } /* diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 6308286..e47ab1e 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -3169,8 +3169,13 @@ ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext { /* Full conversion with attribute rearrangement needed */ result = execute_attr_map_tuple(&tmptup, op->d.convert_rowtype.map); - /* Result already has appropriate composite-datum header fields */ - *op->resvalue = HeapTupleGetDatum(result); + + /* + * Result already has appropriate composite-datum header fields. The + * input was a composite type so we aren't expecting to have to + * flatten any toasted fields so directly call HeapTupleGetRawDatum. + */ + *op->resvalue = HeapTupleGetRawDatum(result); } else { @@ -3181,10 +3186,10 @@ ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext * for this since it will both make the physical copy and insert the * correct composite header fields. Note that we aren't expecting to * have to flatten any toasted fields: the input was a composite - * datum, so it shouldn't contain any. So heap_copy_tuple_as_datum() - * is overkill here, but its check for external fields is cheap. + * datum, so it shouldn't contain any. So we can directly call + * heap_copy_tuple_as_raw_datum(). */ - *op->resvalue = heap_copy_tuple_as_datum(&tmptup, outdesc); + *op->resvalue = heap_copy_tuple_as_raw_datum(&tmptup, outdesc); } } diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c index 9817b44..f92628b 100644 --- a/src/backend/replication/slotfuncs.c +++ b/src/backend/replication/slotfuncs.c @@ -106,7 +106,7 @@ pg_create_physical_replication_slot(PG_FUNCTION_ARGS) nulls[1] = true; tuple = heap_form_tuple(tupdesc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); ReplicationSlotRelease(); @@ -205,7 +205,7 @@ pg_create_logical_replication_slot(PG_FUNCTION_ARGS) memset(nulls, 0, sizeof(nulls)); tuple = heap_form_tuple(tupdesc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); /* ok, slot is now fully created, mark it as persistent if needed */ if (!temporary) @@ -689,7 +689,7 @@ pg_replication_slot_advance(PG_FUNCTION_ARGS) nulls[1] = false; tuple = heap_form_tuple(tupdesc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); PG_RETURN_DATUM(result); } @@ -911,7 +911,7 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot) nulls[1] = true; tuple = heap_form_tuple(tupdesc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); ReplicationSlotRelease(); diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index 8532296..f5425a3 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -1423,5 +1423,6 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS) } /* Returns the record as Datum */ - PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); + PG_RETURN_HEAPTUPLEHEADER_RAW( + heap_form_tuple(tupdesc, values, nulls)->t_data); } diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c index abbc1f1..115131c 100644 --- a/src/backend/statistics/mcv.c +++ b/src/backend/statistics/mcv.c @@ -1450,7 +1450,7 @@ pg_stats_ext_mcvlist_items(PG_FUNCTION_ARGS) tuple = heap_form_tuple(funcctx->attinmeta->tupdesc, values, nulls); /* make the tuple into a datum */ - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } diff --git a/src/backend/tsearch/wparser.c b/src/backend/tsearch/wparser.c index 71882dc..633c90d 100644 --- a/src/backend/tsearch/wparser.c +++ b/src/backend/tsearch/wparser.c @@ -97,7 +97,7 @@ tt_process_call(FuncCallContext *funcctx) values[2] = st->list[st->cur].descr; tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); pfree(values[1]); pfree(values[2]); @@ -236,7 +236,7 @@ prs_process_call(FuncCallContext *funcctx) sprintf(tid, "%d", st->list[st->cur].type); values[1] = st->list[st->cur].lexeme; tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); pfree(values[1]); st->cur++; diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index c7f029e..5871c0b 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -1804,7 +1804,7 @@ aclexplode(PG_FUNCTION_ARGS) MemSet(nulls, 0, sizeof(nulls)); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 350b0c5..ce11554 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -4776,7 +4776,7 @@ pg_timezone_abbrevs(PG_FUNCTION_ARGS) (*pindex)++; tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c index 169ddf8..d3d386b 100644 --- a/src/backend/utils/adt/genfile.c +++ b/src/backend/utils/adt/genfile.c @@ -454,7 +454,7 @@ pg_stat_file(PG_FUNCTION_ARGS) pfree(filename); - PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); + PG_RETURN_HEAPTUPLEHEADER_RAW(tuple->t_data); } /* diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c index 97f0265..0818449 100644 --- a/src/backend/utils/adt/lockfuncs.c +++ b/src/backend/utils/adt/lockfuncs.c @@ -344,7 +344,7 @@ pg_lock_status(PG_FUNCTION_ARGS) nulls[15] = true; tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } @@ -415,7 +415,7 @@ pg_lock_status(PG_FUNCTION_ARGS) nulls[15] = true; tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index 634f574..57e0ea0 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -484,7 +484,7 @@ pg_get_keywords(PG_FUNCTION_ARGS) tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); - SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); + SRF_RETURN_NEXT(funcctx, HeapTupleGetRawDatum(tuple)); } SRF_RETURN_DONE(funcctx); @@ -562,7 +562,7 @@ pg_get_catalog_foreign_keys(PG_FUNCTION_ARGS) tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); + SRF_RETURN_NEXT(funcctx, HeapTupleGetRawDatum(tuple)); } SRF_RETURN_DONE(funcctx); diff --git a/src/backend/utils/adt/partitionfuncs.c b/src/backend/utils/adt/partitionfuncs.c index 03660d5..6915939 100644 --- a/src/backend/utils/adt/partitionfuncs.c +++ b/src/backend/utils/adt/partitionfuncs.c @@ -159,7 +159,7 @@ pg_partition_tree(PG_FUNCTION_ARGS) values[3] = Int32GetDatum(level); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 5102227..b93ad73 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -1856,7 +1856,8 @@ pg_stat_get_wal(PG_FUNCTION_ARGS) values[8] = TimestampTzGetDatum(wal_stats->stat_reset_timestamp); /* Returns the record as Datum */ - PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); + PG_RETURN_HEAPTUPLEHEADER_RAW( + heap_form_tuple(tupdesc, values, nulls)->t_data); } /* @@ -2272,7 +2273,8 @@ pg_stat_get_archiver(PG_FUNCTION_ARGS) values[6] = TimestampTzGetDatum(archiver_stats->stat_reset_timestamp); /* Returns the record as Datum */ - PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); + PG_RETURN_HEAPTUPLEHEADER_RAW( + heap_form_tuple(tupdesc, values, nulls)->t_data); } /* Get the statistics for the replication slots */ diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c index 23787a6..079a5af 100644 --- a/src/backend/utils/adt/rowtypes.c +++ b/src/backend/utils/adt/rowtypes.c @@ -293,7 +293,7 @@ record_in(PG_FUNCTION_ARGS) pfree(nulls); ReleaseTupleDesc(tupdesc); - PG_RETURN_HEAPTUPLEHEADER(result); + PG_RETURN_HEAPTUPLEHEADER_RAW(result); } /* @@ -660,7 +660,7 @@ record_recv(PG_FUNCTION_ARGS) pfree(nulls); ReleaseTupleDesc(tupdesc); - PG_RETURN_HEAPTUPLEHEADER(result); + PG_RETURN_HEAPTUPLEHEADER_RAW(result); } /* diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c index 9236ebc..6679493 100644 --- a/src/backend/utils/adt/tsvector_op.c +++ b/src/backend/utils/adt/tsvector_op.c @@ -707,7 +707,7 @@ tsvector_unnest(PG_FUNCTION_ARGS) } tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); + SRF_RETURN_NEXT(funcctx, HeapTupleGetRawDatum(tuple)); } else { @@ -2385,7 +2385,7 @@ ts_process_call(FuncCallContext *funcctx) values[2] = nentry; tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); pfree(values[0]); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index b263e34..6b2d9d6 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -9805,7 +9805,7 @@ show_all_settings(PG_FUNCTION_ARGS) tuple = BuildTupleFromCStrings(attinmeta, values); /* make the tuple into a datum */ - result = HeapTupleGetDatum(tuple); + result = HeapTupleGetRawDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c index 209a20a..195c127 100644 --- a/src/backend/utils/misc/pg_controldata.c +++ b/src/backend/utils/misc/pg_controldata.c @@ -73,7 +73,7 @@ pg_control_system(PG_FUNCTION_ARGS) htup = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + PG_RETURN_HEAPTUPLEHEADER_RAW(htup->t_data); } Datum @@ -204,7 +204,7 @@ pg_control_checkpoint(PG_FUNCTION_ARGS) htup = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + PG_RETURN_HEAPTUPLEHEADER_RAW(htup->t_data); } Datum @@ -257,7 +257,7 @@ pg_control_recovery(PG_FUNCTION_ARGS) htup = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + PG_RETURN_HEAPTUPLEHEADER_RAW(htup->t_data); } Datum @@ -340,5 +340,5 @@ pg_control_init(PG_FUNCTION_ARGS) htup = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + PG_RETURN_HEAPTUPLEHEADER_RAW(htup->t_data); } diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h index 7c62852..7ac3c23 100644 --- a/src/include/access/htup_details.h +++ b/src/include/access/htup_details.h @@ -790,6 +790,7 @@ extern Datum getmissingattr(TupleDesc tupleDesc, extern HeapTuple heap_copytuple(HeapTuple tuple); extern void heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest); extern Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc); +extern Datum heap_copy_tuple_as_raw_datum(HeapTuple tuple, TupleDesc tupleDesc); extern HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull); extern HeapTuple heap_modify_tuple(HeapTuple tuple, diff --git a/src/include/fmgr.h b/src/include/fmgr.h index ab7b85c..cb70c05 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -373,6 +373,11 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena *datum); #define PG_RETURN_BPCHAR_P(x) PG_RETURN_POINTER(x) #define PG_RETURN_VARCHAR_P(x) PG_RETURN_POINTER(x) #define PG_RETURN_HEAPTUPLEHEADER(x) return HeapTupleHeaderGetDatum(x) +/* + * same as PG_RETURN_HEAPTUPLEHEADER but the input tuple should not contain any + * external varlena. + */ +#define PG_RETURN_HEAPTUPLEHEADER_RAW(x) return HeapTupleHeaderGetRawDatum(x) /*------------------------------------------------------------------------- diff --git a/src/include/funcapi.h b/src/include/funcapi.h index 83e6bc2..8ba7ae2 100644 --- a/src/include/funcapi.h +++ b/src/include/funcapi.h @@ -205,8 +205,13 @@ extern TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple); * Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple) - convert a * HeapTupleHeader to a Datum. * - * Macro declarations: + * Macro declarations/inline functions: + * HeapTupleHeaderGetRawDatum(HeapTupleHeader tuple) - same as + * HeapTupleHeaderGetDatum but the input tuple should not contain + * external varlena * HeapTupleGetDatum(HeapTuple tuple) - convert a HeapTuple to a Datum. + * HeapTupleGetRawDatum(HeapTuple tuple) - same as HeapTupleGetDatum + * but the input tuple should not contain external varlena * * Obsolete routines and macros: * TupleDesc RelationNameGetTupleDesc(const char *relname) - Use to get a @@ -218,7 +223,15 @@ extern TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple); *---------- */ +static inline Datum +HeapTupleHeaderGetRawDatum(HeapTupleHeader tuple) +{ + Assert(!HeapTupleHeaderHasExternal(tuple)); + return PointerGetDatum(tuple); +} + #define HeapTupleGetDatum(tuple) HeapTupleHeaderGetDatum((tuple)->t_data) +#define HeapTupleGetRawDatum(tuple) HeapTupleHeaderGetRawDatum((tuple)->t_data) /* obsolete version of above */ #define TupleGetDatum(_slot, _tuple) HeapTupleGetDatum(_tuple) diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index 6299adf..cdf79f7 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -1127,7 +1127,7 @@ plperl_hash_to_datum(SV *src, TupleDesc td) { HeapTuple tup = plperl_build_tuple_result((HV *) SvRV(src), td); - return HeapTupleGetDatum(tup); + return HeapTupleGetRawDatum(tup); } /* @@ -3334,7 +3334,7 @@ plperl_return_next_internal(SV *sv) current_call_data->ret_tdesc); if (OidIsValid(current_call_data->cdomain_oid)) - domain_check(HeapTupleGetDatum(tuple), false, + domain_check(HeapTupleGetRawDatum(tuple), false, current_call_data->cdomain_oid, ¤t_call_data->cdomain_info, rsi->econtext->ecxt_per_query_memory); diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index e118375..b4e710a 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -1024,7 +1024,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, tup = pltcl_build_tuple_result(interp, resultObjv, resultObjc, call_state); - retval = HeapTupleGetDatum(tup); + retval = HeapTupleGetRawDatum(tup); } else retval = InputFunctionCall(&prodesc->result_in_func, @@ -3235,7 +3235,7 @@ pltcl_build_tuple_result(Tcl_Interp *interp, Tcl_Obj **kvObjv, int kvObjc, /* if result type is domain-over-composite, check domain constraints */ if (call_state->prodesc->fn_retisdomain) - domain_check(HeapTupleGetDatum(tuple), false, + domain_check(HeapTupleGetRawDatum(tuple), false, call_state->prodesc->result_typid, &call_state->prodesc->domain_info, call_state->prodesc->fn_cxt); diff --git a/src/test/modules/test_predtest/test_predtest.c b/src/test/modules/test_predtest/test_predtest.c index 9c0aadd..ec83645 100644 --- a/src/test/modules/test_predtest/test_predtest.c +++ b/src/test/modules/test_predtest/test_predtest.c @@ -214,5 +214,6 @@ test_predtest(PG_FUNCTION_ARGS) values[6] = BoolGetDatum(s_r_holds); values[7] = BoolGetDatum(w_r_holds); - PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); + PG_RETURN_HEAPTUPLEHEADER_RAW( + heap_form_tuple(tupdesc, values, nulls)->t_data); } -- 1.8.3.1