80 #define PGSS_DUMP_FILE PGSTAT_STAT_PERMANENT_DIRECTORY "/pg_stat_statements.stat"
85 #define PGSS_TEXT_FILE PG_STAT_TMP_DIR "/pgss_query_texts.stat"
94 #define USAGE_EXEC(duration) (1.0)
95 #define USAGE_INIT (1.0)
96 #define ASSUMED_MEDIAN_INIT (10.0)
97 #define ASSUMED_LENGTH_INIT 1024
98 #define USAGE_DECREASE_FACTOR (0.99)
99 #define STICKY_DECREASE_FACTOR (0.50)
100 #define USAGE_DEALLOC_PERCENT 5
101 #define IS_STICKY(c) ((c.calls[PGSS_PLAN] + c.calls[PGSS_EXEC]) == 0)
297 #define pgss_enabled(level) \
298 (!IsParallelWorker() && \
299 (pgss_track == PGSS_TRACK_ALL || \
300 (pgss_track == PGSS_TRACK_TOP && (level) == 0)))
302 #define record_gc_qtexts() \
304 SpinLockAcquire(&pgss->mutex); \
306 SpinLockRelease(&pgss->mutex); \
329 const char *query_string,
335 uint64 count,
bool execute_once);
343 static void pgss_store(
const char *query, uint64 queryId,
344 int query_location,
int query_len,
346 double total_time, uint64 rows,
358 static bool qtext_store(
const char *query,
int query_len,
359 Size *query_offset,
int *gc_count);
362 char *buffer,
Size buffer_size);
367 int query_loc,
int *query_len_p);
400 "Sets the maximum number of statements tracked by pg_stat_statements.",
413 "Selects which statements are tracked by pg_stat_statements.",
425 "Selects whether utility commands are tracked by pg_stat_statements.",
436 "Selects whether planning duration is tracked by pg_stat_statements.",
447 "Save pg_stat_statements statistics across server shutdowns.",
606 buffer = (
char *)
palloc(buffer_size);
608 if (fread(&header,
sizeof(
uint32), 1, file) != 1 ||
609 fread(&pgver,
sizeof(
uint32), 1, file) != 1 ||
610 fread(&num,
sizeof(
int32), 1, file) != 1)
617 for (
i = 0;
i < num;
i++)
623 if (fread(&temp,
sizeof(
pgssEntry), 1, file) != 1)
634 buffer =
repalloc(buffer, buffer_size);
692 errmsg(
"could not read file \"%s\": %m",
697 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
698 errmsg(
"ignoring invalid data in file \"%s\"",
704 errmsg(
"could not write file \"%s\": %m",
732 char *qbuffer = NULL;
733 Size qbuffer_size = 0;
759 if (fwrite(&num_entries,
sizeof(
int32), 1, file) != 1)
775 qbuffer, qbuffer_size);
780 if (fwrite(entry,
sizeof(
pgssEntry), 1, file) != 1 ||
781 fwrite(qstr, 1,
len + 1, file) !=
len + 1)
815 errmsg(
"could not write file \"%s\": %m",
847 query->queryId = UINT64CONST(0);
879 const char *query_string,
892 &&
parse->queryId != UINT64CONST(0))
935 memset(&walusage, 0,
sizeof(
WalUsage));
940 parse->stmt_location,
1062 if (queryId != UINT64CONST(0) && queryDesc->
totaltime &&
1101 uint64 saved_queryId = pstmt->
queryId;
1103 int saved_stmt_len = pstmt->
stmt_len;
1121 pstmt->
queryId = UINT64CONST(0);
1188 rows = (qc && (qc->
commandTag == CMDTAG_COPY ||
1191 qc->
commandTag == CMDTAG_REFRESH_MATERIALIZED_VIEW)) ?
1199 memset(&walusage, 0,
sizeof(
WalUsage));
1204 saved_stmt_location,
1267 int query_location,
int query_len,
1269 double total_time, uint64 rows,
1277 char *norm_query = NULL;
1290 if (queryId == UINT64CONST(0))
1307 key.queryid = queryId;
1340 stored =
qtext_store(norm_query ? norm_query : query, query_len,
1341 &query_offset, &gc_count);
1362 stored =
qtext_store(norm_query ? norm_query : query, query_len,
1363 &query_offset, NULL);
1534 #define PG_STAT_STATEMENTS_COLS_V1_0 14
1535 #define PG_STAT_STATEMENTS_COLS_V1_1 18
1536 #define PG_STAT_STATEMENTS_COLS_V1_2 19
1537 #define PG_STAT_STATEMENTS_COLS_V1_3 23
1538 #define PG_STAT_STATEMENTS_COLS_V1_8 32
1539 #define PG_STAT_STATEMENTS_COLS_V1_9 33
1540 #define PG_STAT_STATEMENTS_COLS_V1_10 43
1541 #define PG_STAT_STATEMENTS_COLS_V1_11 49
1542 #define PG_STAT_STATEMENTS_COLS 49
1635 bool is_allowed_role =
false;
1636 char *qbuffer = NULL;
1637 Size qbuffer_size = 0;
1652 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1653 errmsg(
"pg_stat_statements must be loaded via \"shared_preload_libraries\"")));
1666 elog(
ERROR,
"incorrect number of output arguments");
1671 elog(
ERROR,
"incorrect number of output arguments");
1676 elog(
ERROR,
"incorrect number of output arguments");
1680 elog(
ERROR,
"incorrect number of output arguments");
1684 elog(
ERROR,
"incorrect number of output arguments");
1688 elog(
ERROR,
"incorrect number of output arguments");
1692 elog(
ERROR,
"incorrect number of output arguments");
1696 elog(
ERROR,
"incorrect number of output arguments");
1699 elog(
ERROR,
"incorrect number of output arguments");
1753 if (qbuffer == NULL ||
1775 memset(nulls, 0,
sizeof(nulls));
1782 if (is_allowed_role || entry->
key.
userid == userid)
1868 if (tmp.
calls[kind] > 1)
1958 #define PG_STAT_STATEMENTS_INFO_COLS 2
1973 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1974 errmsg(
"pg_stat_statements must be loaded via \"shared_preload_libraries\"")));
1978 elog(
ERROR,
"return type must be a row type");
2064 double l_usage = (*(
pgssEntry *
const *) lhs)->counters.usage;
2065 double r_usage = (*(
pgssEntry *
const *) rhs)->counters.usage;
2067 if (l_usage < r_usage)
2069 else if (l_usage > r_usage)
2112 entries[
i++] = entry;
2133 if (nvalidtexts > 0)
2140 nvictims =
Min(nvictims,
i);
2142 for (
i = 0;
i < nvictims;
i++)
2173 Size *query_offset,
int *gc_count)
2190 *query_offset = off;
2209 if (
pg_pwrite(
fd, query, query_len, off) != query_len)
2226 errmsg(
"could not write file \"%s\": %m",
2262 if (errno != ENOENT)
2265 errmsg(
"could not read file \"%s\": %m",
2275 errmsg(
"could not stat file \"%s\": %m",
2289 (
errcode(ERRCODE_OUT_OF_MEMORY),
2291 errdetail(
"Could not allocate enough memory to read file \"%s\".",
2315 if (
read(
fd,
buf + nread, toread) != toread)
2320 errmsg(
"could not read file \"%s\": %m",
2334 *buffer_size = nread;
2346 char *buffer,
Size buffer_size)
2352 if (query_len < 0 ||
2353 query_offset + query_len >= buffer_size)
2356 if (buffer[query_offset + query_len] !=
'\0')
2359 return buffer + query_offset;
2384 if ((uint64) extent < (uint64) 512 *
pgss_max)
2443 if (qbuffer == NULL)
2457 errmsg(
"could not write file \"%s\": %m",
2483 if (fwrite(qry, 1, query_len + 1, qfile) != query_len + 1)
2487 errmsg(
"could not write file \"%s\": %m",
2494 extent += query_len + 1;
2502 if (
ftruncate(fileno(qfile), extent) != 0)
2505 errmsg(
"could not truncate file \"%s\": %m",
2512 errmsg(
"could not write file \"%s\": %m",
2518 elog(
DEBUG1,
"pgss gc of queries file shrunk size from %zu to %zu",
2571 errmsg(
"could not recreate file \"%s\": %m",
2596 #define SINGLE_ENTRY_RESET(e) \
2598 if (minmax_only) { \
2600 for (int kind = 0; kind < PGSS_NUMKIND; kind++) \
2602 e->counters.max_time[kind] = 0; \
2603 e->counters.min_time[kind] = 0; \
2605 e->minmax_stats_since = stats_reset; \
2610 hash_search(pgss_hash, &e->key, HASH_REMOVE, NULL); \
2625 long num_remove = 0;
2631 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2632 errmsg(
"pg_stat_statements must be loaded via \"shared_preload_libraries\"")));
2639 if (userid != 0 && dbid != 0 && queryid != UINT64CONST(0))
2643 key.userid = userid;
2645 key.queryid = queryid;
2651 key.toplevel =
false;
2657 key.toplevel =
true;
2662 else if (userid != 0 || dbid != 0 || queryid != UINT64CONST(0))
2668 if ((!userid || entry->
key.
userid == userid) &&
2669 (!dbid || entry->
key.
dbid == dbid) &&
2687 if (num_entries != num_remove)
2708 errmsg(
"could not create file \"%s\": %m",
2717 errmsg(
"could not truncate file \"%s\": %m",
2754 int query_loc,
int *query_len_p)
2757 int query_len = *query_len_p;
2782 norm_query =
palloc(norm_query_buflen + 1);
2799 len_to_wrt = off - last_off;
2800 len_to_wrt -= last_tok_len;
2803 memcpy(norm_query + n_quer_loc, query + quer_loc, len_to_wrt);
2804 n_quer_loc += len_to_wrt;
2807 n_quer_loc +=
sprintf(norm_query + n_quer_loc,
"$%d",
2810 quer_loc = off + tok_len;
2812 last_tok_len = tok_len;
2819 len_to_wrt = query_len - quer_loc;
2822 memcpy(norm_query + n_quer_loc, query + quer_loc, len_to_wrt);
2823 n_quer_loc += len_to_wrt;
2825 Assert(n_quer_loc <= norm_query_buflen);
2826 norm_query[n_quer_loc] =
'\0';
2828 *query_len_p = n_quer_loc;
2900 if (loc <= last_loc)
2918 if (query[loc] ==
'-')
bool has_privs_of_role(Oid member, Oid role)
void(* post_parse_analyze_hook_type)(ParseState *pstate, Query *query, JumbleState *jstate)
Datum numeric_in(PG_FUNCTION_ARGS)
TimestampTz GetCurrentTimestamp(void)
static Datum values[MAXATTR]
#define CStringGetTextDatum(s)
#define Assert(condition)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
void hash_seq_term(HASH_SEQ_STATUS *status)
long hash_get_num_entries(HTAB *hashp)
Size hash_estimate_size(long num_entries, Size entrysize)
void * hash_seq_search(HASH_SEQ_STATUS *status)
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
int errcode_for_file_access(void)
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
ExecutorEnd_hook_type ExecutorEnd_hook
ExecutorFinish_hook_type ExecutorFinish_hook
ExecutorStart_hook_type ExecutorStart_hook
void standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
void standard_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
ExecutorRun_hook_type ExecutorRun_hook
void standard_ExecutorEnd(QueryDesc *queryDesc)
void standard_ExecutorFinish(QueryDesc *queryDesc)
void(* ExecutorRun_hook_type)(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
void(* ExecutorFinish_hook_type)(QueryDesc *queryDesc)
void(* ExecutorStart_hook_type)(QueryDesc *queryDesc, int eflags)
void(* ExecutorEnd_hook_type)(QueryDesc *queryDesc)
FILE * AllocateFile(const char *name, const char *mode)
int durable_rename(const char *oldfile, const char *newfile, int elevel)
int CloseTransientFile(int fd)
int OpenTransientFile(const char *fileName, int fileFlags)
Datum Int64GetDatum(int64 X)
#define PG_GETARG_INT64(n)
#define PG_GETARG_BOOL(n)
#define PG_RETURN_DATUM(x)
#define DirectFunctionCall3(func, arg1, arg2, arg3)
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
void DefineCustomEnumVariable(const char *name, const char *short_desc, const char *long_desc, int *valueAddr, int bootValue, const struct config_enum_entry *options, GucContext context, int flags, GucEnumCheckHook check_hook, GucEnumAssignHook assign_hook, GucShowHook show_hook)
void DefineCustomBoolVariable(const char *name, const char *short_desc, const char *long_desc, bool *valueAddr, bool bootValue, GucContext context, int flags, GucBoolCheckHook check_hook, GucBoolAssignHook assign_hook, GucShowHook show_hook)
void MarkGUCPrefixReserved(const char *className)
void DefineCustomIntVariable(const char *name, const char *short_desc, const char *long_desc, int *valueAddr, int bootValue, int minValue, int maxValue, GucContext context, int flags, GucIntCheckHook check_hook, GucIntAssignHook assign_hook, GucShowHook show_hook)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
#define INSTR_TIME_SET_CURRENT(t)
#define INSTR_TIME_SUBTRACT(x, y)
#define INSTR_TIME_GET_MILLISEC(t)
void InstrEndLoop(Instrumentation *instr)
Instrumentation * InstrAlloc(int n, int instrument_options, bool async_mode)
void WalUsageAccumDiff(WalUsage *dst, const WalUsage *add, const WalUsage *sub)
BufferUsage pgBufferUsage
void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub)
static int pg_cmp_s32(int32 a, int32 b)
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
void(* shmem_startup_hook_type)(void)
shmem_startup_hook_type shmem_startup_hook
void RequestAddinShmemSpace(Size size)
PGDLLIMPORT const ScanKeywordList ScanKeywords
LWLockPadded * GetNamedLWLockTranche(const char *tranche_name)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)
void LWLockRelease(LWLock *lock)
char * pg_any_to_server(const char *s, int len, int encoding)
int GetDatabaseEncoding(void)
void pfree(void *pointer)
void * repalloc(void *pointer, Size size)
void(* shmem_request_hook_type)(void)
shmem_request_hook_type shmem_request_hook
bool process_shared_preload_libraries_in_progress
#define IsA(nodeptr, _type_)
post_parse_analyze_hook_type post_parse_analyze_hook
static int entry_cmp(const void *lhs, const void *rhs)
#define PG_STAT_STATEMENTS_COLS_V1_0
static planner_hook_type prev_planner_hook
#define SINGLE_ENTRY_RESET(e)
static bool pgss_track_planning
#define ASSUMED_MEDIAN_INIT
#define PG_STAT_STATEMENTS_INFO_COLS
PG_FUNCTION_INFO_V1(pg_stat_statements_reset)
static ExecutorRun_hook_type prev_ExecutorRun
struct pgssSharedState pgssSharedState
static void pgss_store(const char *query, uint64 queryId, int query_location, int query_len, pgssStoreKind kind, double total_time, uint64 rows, const BufferUsage *bufusage, const WalUsage *walusage, const struct JitInstrumentation *jitusage, JumbleState *jstate)
static void pg_stat_statements_internal(FunctionCallInfo fcinfo, pgssVersion api_version, bool showtext)
#define record_gc_qtexts()
Datum pg_stat_statements_reset_1_7(PG_FUNCTION_ARGS)
static PlannedStmt * pgss_planner(Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams)
static void gc_qtexts(void)
#define PG_STAT_STATEMENTS_COLS_V1_8
static int comp_location(const void *a, const void *b)
Datum pg_stat_statements_1_11(PG_FUNCTION_ARGS)
#define PG_STAT_STATEMENTS_COLS
Datum pg_stat_statements_1_9(PG_FUNCTION_ARGS)
static char * qtext_fetch(Size query_offset, int query_len, char *buffer, Size buffer_size)
#define USAGE_DEALLOC_PERCENT
static bool qtext_store(const char *query, int query_len, Size *query_offset, int *gc_count)
Datum pg_stat_statements_1_10(PG_FUNCTION_ARGS)
#define USAGE_EXEC(duration)
#define PG_STAT_STATEMENTS_COLS_V1_11
#define STICKY_DECREASE_FACTOR
static const struct config_enum_entry track_options[]
#define PG_STAT_STATEMENTS_COLS_V1_2
Datum pg_stat_statements_reset(PG_FUNCTION_ARGS)
static void pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
static char * qtext_load_file(Size *buffer_size)
static post_parse_analyze_hook_type prev_post_parse_analyze_hook
static bool need_gc_qtexts(void)
#define pgss_enabled(level)
static shmem_startup_hook_type prev_shmem_startup_hook
static shmem_request_hook_type prev_shmem_request_hook
static void pgss_shmem_request(void)
static TimestampTz entry_reset(Oid userid, Oid dbid, uint64 queryid, bool minmax_only)
static void pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
#define ASSUMED_LENGTH_INIT
#define PG_STAT_STATEMENTS_COLS_V1_3
static Size pgss_memsize(void)
static void pgss_shmem_startup(void)
struct pgssGlobalStats pgssGlobalStats
static const uint32 PGSS_PG_MAJOR_VERSION
Datum pg_stat_statements_1_2(PG_FUNCTION_ARGS)
struct pgssEntry pgssEntry
#define USAGE_DECREASE_FACTOR
static ExecutorStart_hook_type prev_ExecutorStart
Datum pg_stat_statements(PG_FUNCTION_ARGS)
Datum pg_stat_statements_info(PG_FUNCTION_ARGS)
static void entry_dealloc(void)
#define PG_STAT_STATEMENTS_COLS_V1_10
static pgssSharedState * pgss
Datum pg_stat_statements_1_3(PG_FUNCTION_ARGS)
static void pgss_ExecutorFinish(QueryDesc *queryDesc)
static ProcessUtility_hook_type prev_ProcessUtility
#define PG_STAT_STATEMENTS_COLS_V1_1
Datum pg_stat_statements_1_8(PG_FUNCTION_ARGS)
static void pgss_post_parse_analyze(ParseState *pstate, Query *query, JumbleState *jstate)
struct pgssHashKey pgssHashKey
Datum pg_stat_statements_reset_1_11(PG_FUNCTION_ARGS)
static pgssEntry * entry_alloc(pgssHashKey *key, Size query_offset, int query_len, int encoding, bool sticky)
static void fill_in_constant_lengths(JumbleState *jstate, const char *query, int query_loc)
static bool pgss_track_utility
static ExecutorEnd_hook_type prev_ExecutorEnd
#define PG_STAT_STATEMENTS_COLS_V1_9
static void pgss_ExecutorEnd(QueryDesc *queryDesc)
static char * generate_normalized_query(JumbleState *jstate, const char *query, int query_loc, int *query_len_p)
static void pgss_ExecutorStart(QueryDesc *queryDesc, int eflags)
static const uint32 PGSS_FILE_HEADER
static void pgss_shmem_shutdown(int code, Datum arg)
static ExecutorFinish_hook_type prev_ExecutorFinish
#define PG_VALID_BE_ENCODING(_enc)
static core_yyscan_t yyscanner
planner_hook_type planner_hook
PlannedStmt * standard_planner(Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams)
PlannedStmt *(* planner_hook_type)(Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams)
#define qsort(a, b, c, d)
#define Int64GetDatumFast(X)
#define Float8GetDatumFast(X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static Datum CStringGetDatum(const char *X)
static Datum Int32GetDatum(int32 X)
static int fd(const char *x, int i)
const char * CleanQuerytext(const char *query, int *location, int *len)
MemoryContextSwitchTo(old_ctx)
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
core_yyscan_t scanner_init(const char *str, core_yy_extra_type *yyext, const ScanKeywordList *keywordlist, const uint16 *keyword_tokens)
void scanner_finish(core_yyscan_t yyscanner)
PGDLLIMPORT const uint16 ScanKeywordTokens[]
int core_yylex(core_YYSTYPE *yylval_param, YYLTYPE *yylloc_param, core_yyscan_t yyscanner)
Size add_size(Size s1, Size s2)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
static pg_noinline void Size size
#define SpinLockInit(lock)
#define SpinLockRelease(lock)
#define SpinLockAcquire(lock)
instr_time local_blk_read_time
int64 shared_blks_dirtied
instr_time temp_blk_write_time
instr_time shared_blk_read_time
instr_time shared_blk_write_time
instr_time temp_blk_read_time
instr_time local_blk_write_time
int64 shared_blks_written
int64 calls[PGSS_NUMKIND]
int64 shared_blks_written
double jit_generation_time
double min_time[PGSS_NUMKIND]
double sum_var_time[PGSS_NUMKIND]
double temp_blk_read_time
double local_blk_write_time
double local_blk_read_time
double jit_optimization_time
double shared_blk_write_time
int64 jit_optimization_count
double total_time[PGSS_NUMKIND]
double max_time[PGSS_NUMKIND]
int64 shared_blks_dirtied
double mean_time[PGSS_NUMKIND]
double temp_blk_write_time
double shared_blk_read_time
struct JitContext * es_jit
uint64 es_total_processed
MemoryContext es_query_cxt
instr_time generation_counter
instr_time optimization_counter
instr_time deform_counter
instr_time emission_counter
instr_time inlining_counter
int highest_extern_param_id
const char * p_sourcetext
PlannedStmt * plannedstmt
struct Instrumentation * totaltime
Tuplestorestate * setResult
TimestampTz minmax_stats_since
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
void standard_ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
ProcessUtility_hook_type ProcessUtility_hook
void(* ProcessUtility_hook_type)(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
static Datum TimestampTzGetDatum(TimestampTz X)
#define PG_RETURN_TIMESTAMPTZ(x)