77#define PGSS_DUMP_FILE PGSTAT_STAT_PERMANENT_DIRECTORY "/pg_stat_statements.stat"
82#define PGSS_TEXT_FILE PG_STAT_TMP_DIR "/pgss_query_texts.stat"
91#define USAGE_EXEC(duration) (1.0)
92#define USAGE_INIT (1.0)
93#define ASSUMED_MEDIAN_INIT (10.0)
94#define ASSUMED_LENGTH_INIT 1024
95#define USAGE_DECREASE_FACTOR (0.99)
96#define STICKY_DECREASE_FACTOR (0.50)
97#define USAGE_DEALLOC_PERCENT 5
98#define IS_STICKY(c) ((c.calls[PGSS_PLAN] + c.calls[PGSS_EXEC]) == 0)
129#define PGSS_NUMKIND (PGSS_EXEC + 1)
299#define pgss_enabled(level) \
300 (!IsParallelWorker() && \
301 (pgss_track == PGSS_TRACK_ALL || \
302 (pgss_track == PGSS_TRACK_TOP && (level) == 0)))
304#define record_gc_qtexts() \
306 SpinLockAcquire(&pgss->mutex); \
308 SpinLockRelease(&pgss->mutex); \
332 const char *query_string,
347 int query_location,
int query_len,
349 double total_time,
uint64 rows,
354 int parallel_workers_to_launch,
355 int parallel_workers_launched);
363static bool qtext_store(
const char *query,
int query_len,
364 Size *query_offset,
int *gc_count);
367 char *buffer,
Size buffer_size);
372 int query_loc,
int *query_len_p);
405 "Sets the maximum number of statements tracked by pg_stat_statements.",
418 "Selects which statements are tracked by pg_stat_statements.",
430 "Selects whether utility commands are tracked by pg_stat_statements.",
441 "Selects whether planning duration is tracked by pg_stat_statements.",
452 "Save pg_stat_statements statistics across server shutdowns.",
611 buffer = (
char *)
palloc(buffer_size);
613 if (fread(&header,
sizeof(
uint32), 1, file) != 1 ||
614 fread(&pgver,
sizeof(
uint32), 1, file) != 1 ||
615 fread(&num,
sizeof(
int32), 1, file) != 1)
622 for (
i = 0;
i < num;
i++)
628 if (fread(&temp,
sizeof(
pgssEntry), 1, file) != 1)
639 buffer =
repalloc(buffer, buffer_size);
697 errmsg(
"could not read file \"%s\": %m",
702 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
703 errmsg(
"ignoring invalid data in file \"%s\"",
709 errmsg(
"could not write file \"%s\": %m",
737 char *qbuffer = NULL;
738 Size qbuffer_size = 0;
764 if (fwrite(&num_entries,
sizeof(
int32), 1, file) != 1)
780 qbuffer, qbuffer_size);
785 if (fwrite(entry,
sizeof(
pgssEntry), 1, file) != 1 ||
786 fwrite(qstr, 1,
len + 1, file) !=
len + 1)
820 errmsg(
"could not write file \"%s\": %m",
886 const char *query_string,
942 memset(&walusage, 0,
sizeof(
WalUsage));
947 parse->stmt_location,
1113 int saved_stmt_len = pstmt->
stmt_len;
1198 rows = (qc && (qc->
commandTag == CMDTAG_COPY ||
1201 qc->
commandTag == CMDTAG_REFRESH_MATERIALIZED_VIEW)) ?
1209 memset(&walusage, 0,
sizeof(
WalUsage));
1214 saved_stmt_location,
1279 int query_location,
int query_len,
1281 double total_time,
uint64 rows,
1286 int parallel_workers_to_launch,
1287 int parallel_workers_launched)
1291 char *norm_query = NULL;
1321 key.queryid = queryId;
1354 stored =
qtext_store(norm_query ? norm_query : query, query_len,
1355 &query_offset, &gc_count);
1376 stored =
qtext_store(norm_query ? norm_query : query, query_len,
1377 &query_offset, NULL);
1552#define PG_STAT_STATEMENTS_COLS_V1_0 14
1553#define PG_STAT_STATEMENTS_COLS_V1_1 18
1554#define PG_STAT_STATEMENTS_COLS_V1_2 19
1555#define PG_STAT_STATEMENTS_COLS_V1_3 23
1556#define PG_STAT_STATEMENTS_COLS_V1_8 32
1557#define PG_STAT_STATEMENTS_COLS_V1_9 33
1558#define PG_STAT_STATEMENTS_COLS_V1_10 43
1559#define PG_STAT_STATEMENTS_COLS_V1_11 49
1560#define PG_STAT_STATEMENTS_COLS_V1_12 51
1561#define PG_STAT_STATEMENTS_COLS 51
1664 bool is_allowed_role =
false;
1665 char *qbuffer = NULL;
1666 Size qbuffer_size = 0;
1681 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1682 errmsg(
"pg_stat_statements must be loaded via \"shared_preload_libraries\"")));
1695 elog(
ERROR,
"incorrect number of output arguments");
1700 elog(
ERROR,
"incorrect number of output arguments");
1705 elog(
ERROR,
"incorrect number of output arguments");
1709 elog(
ERROR,
"incorrect number of output arguments");
1713 elog(
ERROR,
"incorrect number of output arguments");
1717 elog(
ERROR,
"incorrect number of output arguments");
1721 elog(
ERROR,
"incorrect number of output arguments");
1725 elog(
ERROR,
"incorrect number of output arguments");
1729 elog(
ERROR,
"incorrect number of output arguments");
1732 elog(
ERROR,
"incorrect number of output arguments");
1786 if (qbuffer == NULL ||
1808 memset(nulls, 0,
sizeof(nulls));
1815 if (is_allowed_role || entry->
key.
userid == userid)
1906 if (tmp.
calls[kind] > 1)
2005#define PG_STAT_STATEMENTS_INFO_COLS 2
2020 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2021 errmsg(
"pg_stat_statements must be loaded via \"shared_preload_libraries\"")));
2025 elog(
ERROR,
"return type must be a row type");
2111 double l_usage = (*(
pgssEntry *
const *) lhs)->counters.usage;
2112 double r_usage = (*(
pgssEntry *
const *) rhs)->counters.usage;
2114 if (l_usage < r_usage)
2116 else if (l_usage > r_usage)
2159 entries[
i++] = entry;
2180 if (nvalidtexts > 0)
2187 nvictims =
Min(nvictims,
i);
2189 for (
i = 0;
i < nvictims;
i++)
2220 Size *query_offset,
int *gc_count)
2237 *query_offset = off;
2256 if (
pg_pwrite(
fd, query, query_len, off) != query_len)
2273 errmsg(
"could not write file \"%s\": %m",
2309 if (errno != ENOENT)
2312 errmsg(
"could not read file \"%s\": %m",
2322 errmsg(
"could not stat file \"%s\": %m",
2336 (
errcode(ERRCODE_OUT_OF_MEMORY),
2338 errdetail(
"Could not allocate enough memory to read file \"%s\".",
2362 if (
read(
fd,
buf + nread, toread) != toread)
2367 errmsg(
"could not read file \"%s\": %m",
2381 *buffer_size = nread;
2393 char *buffer,
Size buffer_size)
2399 if (query_len < 0 ||
2400 query_offset + query_len >= buffer_size)
2403 if (buffer[query_offset + query_len] !=
'\0')
2406 return buffer + query_offset;
2490 if (qbuffer == NULL)
2504 errmsg(
"could not write file \"%s\": %m",
2530 if (fwrite(qry, 1, query_len + 1, qfile) != query_len + 1)
2534 errmsg(
"could not write file \"%s\": %m",
2541 extent += query_len + 1;
2549 if (
ftruncate(fileno(qfile), extent) != 0)
2552 errmsg(
"could not truncate file \"%s\": %m",
2559 errmsg(
"could not write file \"%s\": %m",
2565 elog(
DEBUG1,
"pgss gc of queries file shrunk size from %zu to %zu",
2618 errmsg(
"could not recreate file \"%s\": %m",
2643#define SINGLE_ENTRY_RESET(e) \
2645 if (minmax_only) { \
2647 for (int kind = 0; kind < PGSS_NUMKIND; kind++) \
2649 e->counters.max_time[kind] = 0; \
2650 e->counters.min_time[kind] = 0; \
2652 e->minmax_stats_since = stats_reset; \
2657 hash_search(pgss_hash, &e->key, HASH_REMOVE, NULL); \
2672 long num_remove = 0;
2678 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2679 errmsg(
"pg_stat_statements must be loaded via \"shared_preload_libraries\"")));
2686 if (userid != 0 && dbid != 0 && queryid !=
UINT64CONST(0))
2690 key.userid = userid;
2692 key.queryid = queryid;
2698 key.toplevel =
false;
2704 key.toplevel =
true;
2709 else if (userid != 0 || dbid != 0 || queryid !=
UINT64CONST(0))
2715 if ((!userid || entry->
key.
userid == userid) &&
2716 (!dbid || entry->
key.
dbid == dbid) &&
2734 if (num_entries != num_remove)
2755 errmsg(
"could not create file \"%s\": %m",
2764 errmsg(
"could not truncate file \"%s\": %m",
2801 int query_loc,
int *query_len_p)
2804 int query_len = *query_len_p;
2829 norm_query =
palloc(norm_query_buflen + 1);
2846 len_to_wrt = off - last_off;
2847 len_to_wrt -= last_tok_len;
2850 memcpy(norm_query + n_quer_loc, query + quer_loc, len_to_wrt);
2851 n_quer_loc += len_to_wrt;
2854 n_quer_loc +=
sprintf(norm_query + n_quer_loc,
"$%d",
2857 quer_loc = off + tok_len;
2859 last_tok_len = tok_len;
2866 len_to_wrt = query_len - quer_loc;
2869 memcpy(norm_query + n_quer_loc, query + quer_loc, len_to_wrt);
2870 n_quer_loc += len_to_wrt;
2872 Assert(n_quer_loc <= norm_query_buflen);
2873 norm_query[n_quer_loc] =
'\0';
2875 *query_len_p = n_quer_loc;
2934 yyextra.escape_string_warning =
false;
2947 if (loc <= last_loc)
2965 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_search(HASH_SEQ_STATUS *status)
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_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)
ExecutorRun_hook_type ExecutorRun_hook
void standard_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
void standard_ExecutorEnd(QueryDesc *queryDesc)
void standard_ExecutorFinish(QueryDesc *queryDesc)
void(* ExecutorFinish_hook_type)(QueryDesc *queryDesc)
void(* ExecutorRun_hook_type)(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
void(* ExecutorStart_hook_type)(QueryDesc *queryDesc, int eflags)
void(* ExecutorEnd_hook_type)(QueryDesc *queryDesc)
int durable_rename(const char *oldfile, const char *newfile, int elevel)
int CloseTransientFile(int fd)
FILE * AllocateFile(const char *name, const char *mode)
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
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
LWLockPadded * GetNamedLWLockTranche(const char *tranche_name)
void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)
void LWLockRelease(LWLock *lock)
int GetDatabaseEncoding(void)
char * pg_any_to_server(const char *s, int len, int encoding)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
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 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)
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, int parallel_workers_to_launch, int parallel_workers_launched)
#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
#define PG_STAT_STATEMENTS_COLS_V1_12
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)
#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_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
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
Datum pg_stat_statements_1_12(PG_FUNCTION_ARGS)
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)
const uint16 ScanKeywordTokens[]
int core_yylex(core_YYSTYPE *yylval_param, YYLTYPE *yylloc_param, core_yyscan_t yyscanner)
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Size add_size(Size s1, Size s2)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
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 parallel_workers_launched
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
int64 parallel_workers_to_launch
double shared_blk_read_time
int es_parallel_workers_to_launch
struct JitContext * es_jit
uint64 es_total_processed
MemoryContext es_query_cxt
int es_parallel_workers_launched
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)