1/*-------------------------------------------------------------------------
4 * Explain DestReceiver to measure serialization overhead
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994-5, Regents of the University of California
10 * src/backend/commands/explain_dr.c
12 *-------------------------------------------------------------------------
25 * DestReceiver functions for SERIALIZE option
27 * A DestReceiver for query tuples, that serializes passed rows into RowData
28 * messages while measuring the resources expended and total serialized size,
29 * while never sending the data to the client. This allows measuring the
30 * overhead of deTOASTing and datatype out/sendfuncs, which are not otherwise
31 * exercisable without actually hitting the network.
39 int nattrs;
/* current number of columns */
47 * Get the function lookup info that we'll need for output.
49 * This is a subset of what printtup_prepare_info() does. We don't need to
50 * cope with format choices varying across columns, so it's slightly simpler.
56 /* get rid of any old data */
68 for (
int i = 0;
i < nattrs;
i++)
78 /* wire protocol format text */
84 else if (receiver->
format == 1)
86 /* wire protocol format binary */
94 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
95 errmsg(
"unsupported format code: %d", receiver->
format)));
100 * serializeAnalyzeReceive - collect tuples for EXPLAIN (SERIALIZE)
102 * This should match printtup() in printtup.c as closely as possible,
103 * except for the addition of measurement code.
112 int natts = typeinfo->
natts;
117 /* only measure time, buffers if requested */
123 /* Set or update my derived attribute info, if needed */
127 /* Make sure the tuple is fully deconstructed */
130 /* Switch into per-row context so we can recover memory below */
134 * Prepare a DataRow message (note buffer is in per-query context)
136 * Note that we fill a StringInfo buffer the same as printtup() does, so
137 * as to capture the costs of manipulating the strings accurately.
144 * send the attributes of this tuple
146 for (
int i = 0;
i < natts;
i++)
178 * We mustn't call pq_endmessage_reuse(), since that would actually send
179 * the data to the client. Just count the data, instead. We can leave
180 * the buffer alone; it'll be reset on the next iteration (as would also
181 * happen in printtup()).
185 /* Return to caller's context, and flush row's temporary memory */
189 /* Update timing data */
196 /* Update buffer metrics */
206 * serializeAnalyzeStartup - start up the serializeAnalyze receiver
221 receiver->
format = 0;
/* wire protocol format text */
224 receiver->
format = 1;
/* wire protocol format binary */
228 /* Create per-row temporary memory context */
230 "SerializeTupleReceive",
233 /* The output buffer is re-used across rows, as in printtup.c */
236 /* Initialize results counters */
242 * serializeAnalyzeShutdown - shut down the serializeAnalyze receiver
263 * serializeAnalyzeDestroy - destroy the serializeAnalyze receiver
272 * Build a DestReceiver for EXPLAIN (SERIALIZE) instrumentation.
293 * GetSerializationMetrics - collect metrics
295 * We have to be careful here since the receiver could be an IntoRel
296 * receiver if the subject statement is CREATE TABLE AS. In that
297 * case, return all-zeroes stats.
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
static void serializeAnalyzeStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
SerializeMetrics GetSerializationMetrics(DestReceiver *dest)
static void serialize_prepare_info(SerializeDestReceiver *receiver, TupleDesc typeinfo, int nattrs)
static void serializeAnalyzeDestroy(DestReceiver *self)
static bool serializeAnalyzeReceive(TupleTableSlot *slot, DestReceiver *self)
struct SerializeDestReceiver SerializeDestReceiver
DestReceiver * CreateExplainSerializeDestReceiver(ExplainState *es)
static void serializeAnalyzeShutdown(DestReceiver *self)
@ EXPLAIN_SERIALIZE_BINARY
void fmgr_info(Oid functionId, FmgrInfo *finfo)
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Assert(PointerIsAligned(start, uint64))
#define INSTR_TIME_SET_CURRENT(t)
#define INSTR_TIME_SET_ZERO(t)
#define INSTR_TIME_ACCUM_DIFF(x, y, z)
BufferUsage pgBufferUsage
void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub)
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
void MemoryContextReset(MemoryContext context)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
FormData_pg_attribute * Form_pg_attribute
void initStringInfo(StringInfo str)
ExplainSerializeOption serialize
TupleDesc tts_tupleDescriptor
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
void(* rShutdown)(DestReceiver *self)
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
void(* rDestroy)(DestReceiver *self)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
static void slot_getallattrs(TupleTableSlot *slot)
static Size VARSIZE(const void *PTR)
static char * VARDATA(const void *PTR)