-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION pg_plan_advice" to load this file. \quit
--- Show visibility map information for each block in a relation.
CREATE FUNCTION pg_get_collected_local_advice(
OUT id bigint,
OUT userid oid,
RETURNS SETOF record
AS 'MODULE_PATHNAME', 'pg_get_collected_local_advice'
LANGUAGE C STRICT;
+
+CREATE FUNCTION pg_get_collected_shared_advice(
+ OUT id bigint,
+ OUT userid oid,
+ OUT dbid oid,
+ OUT queryid bigint,
+ OUT collection_time timestamptz,
+ OUT query text,
+ OUT advice text
+)
+RETURNS SETOF record
+AS 'MODULE_PATHNAME', 'pg_get_collected_shared_advice'
+LANGUAGE C STRICT;
#include "utils/timestamp.h"
PG_FUNCTION_INFO_V1(pg_get_collected_local_advice);
+PG_FUNCTION_INFO_V1(pg_get_collected_shared_advice);
#define ADVICE_CHUNK_SIZE 1024
#define ADVICE_CHUNK_ARRAY_SIZE 64
return (Datum) 0;
}
+
+/*
+ * SQL-callable SRF to return locally collected advice
+ */
+Datum
+pg_get_collected_shared_advice(PG_FUNCTION_ARGS)
+{
+ ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+ pgpa_shared_state *state = pg_plan_advice_attach();
+ dsa_area *area = pg_plan_advice_dsa_area();
+ pgpa_shared_advice *sa = shared_collector;
+
+ InitMaterializedSRF(fcinfo, 0);
+
+ /* Lock the shared state. */
+ LWLockAcquire(&state->lock, LW_SHARED);
+
+ /*
+ * If we're not attached to the shared advice collector yet, fix that now;
+ * but if the collector doesn't even exist, we can return without doing
+ * anything else.
+ */
+ if (sa == NULL)
+ {
+ if (state->shared_collector == InvalidDsaPointer)
+ {
+ LWLockRelease(&state->lock);
+ return (Datum) 0;
+ }
+ shared_collector = sa = dsa_get_address(area, state->shared_collector);
+ }
+
+ for (uint64 id = sa->oldest_id; id < sa->next_id; ++id)
+ {
+ uint64 chunk_number;
+ uint64 chunk_offset;
+ dsa_pointer *chunk_array;
+ pgpa_shared_advice_chunk *chunk;
+ pgpa_collected_advice *ca;
+ Datum values[PG_GET_ADVICE_COLUMNS];
+ bool nulls[PG_GET_ADVICE_COLUMNS] = {0};
+
+ chunk_number = (id - sa->base_id) / ADVICE_CHUNK_SIZE;
+ chunk_offset = (id - sa->base_id) % ADVICE_CHUNK_SIZE;
+
+ chunk_array = dsa_get_address(area, sa->chunks);
+ chunk = dsa_get_address(area, chunk_array[chunk_number]);
+ ca = dsa_get_address(area, chunk->entries[chunk_offset]);
+
+ values[0] = UInt64GetDatum(id);
+ values[1] = ObjectIdGetDatum(ca->userid);
+ values[2] = ObjectIdGetDatum(ca->dbid);
+ values[3] = UInt64GetDatum(ca->queryid);
+ values[4] = TimestampGetDatum(ca->timestamp);
+ values[5] = CStringGetTextDatum(query_string(ca));
+ values[6] = CStringGetTextDatum(advice_string(ca));
+
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
+ }
+
+ /* Release lock on shared state. */
+ LWLockRelease(&state->lock);
+
+ return (Datum) 0;
+}