PG-194: PostgreSQL-14 support added.
parent
67b3d961ca
commit
f470ba591a
|
@ -110,7 +110,13 @@ static int pg_get_application_name(char* application_name);
|
||||||
static PgBackendStatus *pg_get_backend_status(void);
|
static PgBackendStatus *pg_get_backend_status(void);
|
||||||
static Datum intarray_get_datum(int32 arr[], int len);
|
static Datum intarray_get_datum(int32 arr[], int len);
|
||||||
|
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM < 140000
|
||||||
static void pgss_post_parse_analyze(ParseState *pstate, Query *query);
|
static void pgss_post_parse_analyze(ParseState *pstate, Query *query);
|
||||||
|
#else
|
||||||
|
static void pgss_post_parse_analyze(ParseState *pstate, Query *query, JumbleState *jstate);
|
||||||
|
#endif
|
||||||
|
|
||||||
static void pgss_ExecutorStart(QueryDesc *queryDesc, int eflags);
|
static void pgss_ExecutorStart(QueryDesc *queryDesc, int eflags);
|
||||||
static void pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once);
|
static void pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once);
|
||||||
static void pgss_ExecutorFinish(QueryDesc *queryDesc);
|
static void pgss_ExecutorFinish(QueryDesc *queryDesc);
|
||||||
|
@ -163,21 +169,24 @@ static void pgss_store(uint64 queryid,
|
||||||
uint64 rows,
|
uint64 rows,
|
||||||
BufferUsage *bufusage,
|
BufferUsage *bufusage,
|
||||||
WalUsage *walusage,
|
WalUsage *walusage,
|
||||||
pgssJumbleState *jstate,
|
JumbleState *jstate,
|
||||||
pgssStoreKind kind);
|
pgssStoreKind kind);
|
||||||
|
|
||||||
static void pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
static void pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
||||||
bool showtext);
|
bool showtext);
|
||||||
|
|
||||||
static void AppendJumble(pgssJumbleState *jstate,
|
#if PG_VERSION_NUM < 140000
|
||||||
|
static void AppendJumble(JumbleState *jstate,
|
||||||
const unsigned char *item, Size size);
|
const unsigned char *item, Size size);
|
||||||
static void JumbleQuery(pgssJumbleState *jstate, Query *query);
|
static void JumbleQuery(JumbleState *jstate, Query *query);
|
||||||
static void JumbleRangeTable(pgssJumbleState *jstate, List *rtable);
|
static void JumbleRangeTable(JumbleState *jstate, List *rtable);
|
||||||
static void JumbleExpr(pgssJumbleState *jstate, Node *node);
|
static void JumbleExpr(JumbleState *jstate, Node *node);
|
||||||
static void RecordConstLocation(pgssJumbleState *jstate, int location);
|
static void RecordConstLocation(JumbleState *jstate, int location);
|
||||||
static char *generate_normalized_query(pgssJumbleState *jstate, const char *query,
|
#endif
|
||||||
|
|
||||||
|
static char *generate_normalized_query(JumbleState *jstate, const char *query,
|
||||||
int query_loc, int *query_len_p, int encoding);
|
int query_loc, int *query_len_p, int encoding);
|
||||||
static void fill_in_constant_lengths(pgssJumbleState *jstate, const char *query, int query_loc);
|
static void fill_in_constant_lengths(JumbleState *jstate, const char *query, int query_loc);
|
||||||
static int comp_location(const void *a, const void *b);
|
static int comp_location(const void *a, const void *b);
|
||||||
|
|
||||||
static uint64 get_next_wbucket(pgssSharedState *pgss);
|
static uint64 get_next_wbucket(pgssSharedState *pgss);
|
||||||
|
@ -188,11 +197,16 @@ pgss_store_query(uint64 queryid,
|
||||||
CmdType cmd_type,
|
CmdType cmd_type,
|
||||||
int query_location,
|
int query_location,
|
||||||
int query_len,
|
int query_len,
|
||||||
pgssJumbleState *jstate,
|
#if PG_VERSION_NUM > 130000
|
||||||
|
JumbleState *jstate,
|
||||||
|
#else
|
||||||
|
JumbleState *jstate,
|
||||||
|
#endif
|
||||||
pgssStoreKind kind);
|
pgssStoreKind kind);
|
||||||
|
|
||||||
static uint64 get_query_id(pgssJumbleState *jstate, Query *query);
|
#if PG_VERSION_NUM < 140000
|
||||||
|
static uint64 get_query_id(JumbleState *jstate, Query *query);
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* Module load callback
|
* Module load callback
|
||||||
*/
|
*/
|
||||||
|
@ -217,6 +231,14 @@ _PG_init(void)
|
||||||
/* Inilize the GUC variables */
|
/* Inilize the GUC variables */
|
||||||
init_guc();
|
init_guc();
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= 140000
|
||||||
|
/*
|
||||||
|
* Inform the postmaster that we want to enable query_id calculation if
|
||||||
|
* compute_query_id is set to auto.
|
||||||
|
*/
|
||||||
|
EnableQueryId();
|
||||||
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < PGSM_MAX_BUCKETS; i++)
|
for (i = 0; i < PGSM_MAX_BUCKETS; i++)
|
||||||
{
|
{
|
||||||
char file_name[1024];
|
char file_name[1024];
|
||||||
|
@ -309,13 +331,59 @@ pg_stat_monitor_version(PG_FUNCTION_ARGS)
|
||||||
PG_RETURN_TEXT_P(cstring_to_text(BUILD_VERSION));
|
PG_RETURN_TEXT_P(cstring_to_text(BUILD_VERSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= 140000
|
||||||
|
/*
|
||||||
|
* Post-parse-analysis hook: mark query with a queryId
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
pgss_post_parse_analyze(ParseState *pstate, Query *query, JumbleState *jstate)
|
||||||
|
{
|
||||||
|
pgssStoreKind kind = PGSS_PARSE;
|
||||||
|
|
||||||
|
if (prev_post_parse_analyze_hook)
|
||||||
|
prev_post_parse_analyze_hook(pstate, query, jstate);
|
||||||
|
|
||||||
|
/* Safety check... */
|
||||||
|
if (!IsSystemInitialized())
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear queryId for prepared statements related utility, as those will
|
||||||
|
* inherit from the underlying statement's one (except DEALLOCATE which is
|
||||||
|
* entirely untracked).
|
||||||
|
*/
|
||||||
|
if (query->utilityStmt)
|
||||||
|
{
|
||||||
|
query->queryId = UINT64CONST(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If query jumbling were able to identify any ignorable constants, we
|
||||||
|
* immediately create a hash table entry for the query, so that we can
|
||||||
|
* record the normalized form of the query string. If there were no such
|
||||||
|
* constants, the normalized string would be the same as the query text
|
||||||
|
* anyway, so there's no need for an early entry.
|
||||||
|
*/
|
||||||
|
if (jstate == NULL || jstate->clocations_count <= 0)
|
||||||
|
return;
|
||||||
|
pgss_store_query(query->queryId, /* queryid */
|
||||||
|
pstate->p_sourcetext, /* query */
|
||||||
|
query->commandType, /* CmdType */
|
||||||
|
query->stmt_location, /* Query Location */
|
||||||
|
query->stmt_len, /* Query Len */
|
||||||
|
jstate, /* JumbleState */
|
||||||
|
kind); /*pgssStoreKind */
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Post-parse-analysis hook: mark query with a queryId
|
* Post-parse-analysis hook: mark query with a queryId
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
pgss_post_parse_analyze(ParseState *pstate, Query *query)
|
pgss_post_parse_analyze(ParseState *pstate, Query *query)
|
||||||
{
|
{
|
||||||
pgssJumbleState jstate;
|
JumbleState jstate;
|
||||||
pgssStoreKind kind = PGSS_PARSE;
|
pgssStoreKind kind = PGSS_PARSE;
|
||||||
|
|
||||||
if (prev_post_parse_analyze_hook)
|
if (prev_post_parse_analyze_hook)
|
||||||
|
@ -356,9 +424,10 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query)
|
||||||
query->commandType, /* CmdType */
|
query->commandType, /* CmdType */
|
||||||
query->stmt_location, /* Query Location */
|
query->stmt_location, /* Query Location */
|
||||||
query->stmt_len, /* Query Len */
|
query->stmt_len, /* Query Len */
|
||||||
&jstate, /* pgssJumbleState */
|
&jstate, /* JumbleState */
|
||||||
kind); /*pgssStoreKind */
|
kind); /*pgssStoreKind */
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ExecutorStart hook: start up tracking if needed
|
* ExecutorStart hook: start up tracking if needed
|
||||||
|
@ -393,7 +462,11 @@ pgss_ExecutorStart(QueryDesc *queryDesc, int eflags)
|
||||||
MemoryContext oldcxt;
|
MemoryContext oldcxt;
|
||||||
|
|
||||||
oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt);
|
oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt);
|
||||||
|
#if PG_VERSION_NUM < 140000
|
||||||
queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL);
|
queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL);
|
||||||
|
#else
|
||||||
|
queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL, false);
|
||||||
|
#endif
|
||||||
MemoryContextSwitchTo(oldcxt);
|
MemoryContextSwitchTo(oldcxt);
|
||||||
}
|
}
|
||||||
pgss_store(queryId, /* query id */
|
pgss_store(queryId, /* query id */
|
||||||
|
@ -656,7 +729,7 @@ pgss_planner_hook(Query *parse, const char *query_string, int cursorOptions, Par
|
||||||
0, /* rows */
|
0, /* rows */
|
||||||
&bufusage, /* bufusage */
|
&bufusage, /* bufusage */
|
||||||
&walusage, /* walusage */
|
&walusage, /* walusage */
|
||||||
NULL, /* pgssJumbleState */
|
NULL, /* JumbleState */
|
||||||
PGSS_PLAN); /* pgssStoreKind */
|
PGSS_PLAN); /* pgssStoreKind */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1073,7 +1146,11 @@ pgss_store_query(uint64 queryid,
|
||||||
CmdType cmd_type,
|
CmdType cmd_type,
|
||||||
int query_location,
|
int query_location,
|
||||||
int query_len,
|
int query_len,
|
||||||
pgssJumbleState *jstate,
|
#if PG_VERSION_NUM > 130000
|
||||||
|
JumbleState *jstate,
|
||||||
|
#else
|
||||||
|
JumbleState *jstate,
|
||||||
|
#endif
|
||||||
pgssStoreKind kind)
|
pgssStoreKind kind)
|
||||||
{
|
{
|
||||||
char *norm_query = NULL;
|
char *norm_query = NULL;
|
||||||
|
@ -1125,7 +1202,7 @@ pgss_store_query(uint64 queryid,
|
||||||
0, /* rows */
|
0, /* rows */
|
||||||
NULL, /* bufusage */
|
NULL, /* bufusage */
|
||||||
NULL, /* walusage */
|
NULL, /* walusage */
|
||||||
jstate, /* pgssJumbleState */
|
jstate, /* JumbleState */
|
||||||
kind); /* pgssStoreKind */
|
kind); /* pgssStoreKind */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1150,7 +1227,7 @@ pgss_store_error(uint64 queryid,
|
||||||
0, /* rows */
|
0, /* rows */
|
||||||
NULL, /* bufusage */
|
NULL, /* bufusage */
|
||||||
NULL, /* walusage */
|
NULL, /* walusage */
|
||||||
NULL, /* pgssJumbleState */
|
NULL, /* JumbleState */
|
||||||
PGSS_ERROR); /* pgssStoreKind */
|
PGSS_ERROR); /* pgssStoreKind */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1173,7 +1250,7 @@ pgss_store_utility(const char *query,
|
||||||
rows, /* rows */
|
rows, /* rows */
|
||||||
bufusage, /* bufusage */
|
bufusage, /* bufusage */
|
||||||
walusage, /* walusage */
|
walusage, /* walusage */
|
||||||
NULL, /* pgssJumbleState */
|
NULL, /* JumbleState */
|
||||||
PGSS_FINISHED); /* pgssStoreKind */
|
PGSS_FINISHED); /* pgssStoreKind */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,7 +1275,7 @@ pgss_store(uint64 queryid,
|
||||||
uint64 rows,
|
uint64 rows,
|
||||||
BufferUsage *bufusage,
|
BufferUsage *bufusage,
|
||||||
WalUsage *walusage,
|
WalUsage *walusage,
|
||||||
pgssJumbleState *jstate,
|
JumbleState *jstate,
|
||||||
pgssStoreKind kind)
|
pgssStoreKind kind)
|
||||||
{
|
{
|
||||||
pgssEntry *entry;
|
pgssEntry *entry;
|
||||||
|
@ -1402,9 +1479,11 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
||||||
uint64 planid = entry->key.planid;
|
uint64 planid = entry->key.planid;
|
||||||
unsigned char *buf = pgss_qbuf[bucketid];
|
unsigned char *buf = pgss_qbuf[bucketid];
|
||||||
char *query_txt = (char*) malloc(PGSM_QUERY_MAX_LEN);
|
char *query_txt = (char*) malloc(PGSM_QUERY_MAX_LEN);
|
||||||
|
#if PG_VERSION_NUM < 140000
|
||||||
bool is_allowed_role = is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS);
|
bool is_allowed_role = is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS);
|
||||||
|
#else
|
||||||
|
bool is_allowed_role = is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS);
|
||||||
|
#endif
|
||||||
query_entry = hash_find_query_entry(bucketid, queryid, dbid, userid, ip);
|
query_entry = hash_find_query_entry(bucketid, queryid, dbid, userid, ip);
|
||||||
if (query_entry == NULL)
|
if (query_entry == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1722,12 +1801,13 @@ get_next_wbucket(pgssSharedState *pgss)
|
||||||
return pgss->current_wbucket;
|
return pgss->current_wbucket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM < 140000
|
||||||
/*
|
/*
|
||||||
* AppendJumble: Append a value that is substantive in a given query to
|
* AppendJumble: Append a value that is substantive in a given query to
|
||||||
* the current jumble.
|
* the current jumble.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
AppendJumble(pgssJumbleState *jstate, const unsigned char *item, Size size)
|
AppendJumble(JumbleState *jstate, const unsigned char *item, Size size)
|
||||||
{
|
{
|
||||||
unsigned char *jumble = jstate->jumble;
|
unsigned char *jumble = jstate->jumble;
|
||||||
Size jumble_len = jstate->jumble_len;
|
Size jumble_len = jstate->jumble_len;
|
||||||
|
@ -1778,7 +1858,7 @@ AppendJumble(pgssJumbleState *jstate, const unsigned char *item, Size size)
|
||||||
* of information).
|
* of information).
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
JumbleQuery(pgssJumbleState *jstate, Query *query)
|
JumbleQuery(JumbleState *jstate, Query *query)
|
||||||
{
|
{
|
||||||
Assert(IsA(query, Query));
|
Assert(IsA(query, Query));
|
||||||
Assert(query->utilityStmt == NULL);
|
Assert(query->utilityStmt == NULL);
|
||||||
|
@ -1807,7 +1887,7 @@ JumbleQuery(pgssJumbleState *jstate, Query *query)
|
||||||
* Jumble a range table
|
* Jumble a range table
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
JumbleRangeTable(pgssJumbleState *jstate, List *rtable)
|
JumbleRangeTable(JumbleState *jstate, List *rtable)
|
||||||
{
|
{
|
||||||
ListCell *lc = NULL;
|
ListCell *lc = NULL;
|
||||||
|
|
||||||
|
@ -1871,7 +1951,7 @@ JumbleRangeTable(pgssJumbleState *jstate, List *rtable)
|
||||||
* about any unrecognized node type.
|
* about any unrecognized node type.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
JumbleExpr(pgssJumbleState *jstate, Node *node)
|
JumbleExpr(JumbleState *jstate, Node *node)
|
||||||
{
|
{
|
||||||
ListCell *temp;
|
ListCell *temp;
|
||||||
|
|
||||||
|
@ -2356,13 +2436,12 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Record location of constant within query string of query tree
|
* Record location of constant within query string of query tree
|
||||||
* that is currently being walked.
|
* that is currently being walked.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
RecordConstLocation(pgssJumbleState *jstate, int location)
|
RecordConstLocation(JumbleState *jstate, int location)
|
||||||
{
|
{
|
||||||
/* -1 indicates unknown or undefined location */
|
/* -1 indicates unknown or undefined location */
|
||||||
if (location >= 0)
|
if (location >= 0)
|
||||||
|
@ -2371,10 +2450,10 @@ RecordConstLocation(pgssJumbleState *jstate, int location)
|
||||||
if (jstate->clocations_count >= jstate->clocations_buf_size)
|
if (jstate->clocations_count >= jstate->clocations_buf_size)
|
||||||
{
|
{
|
||||||
jstate->clocations_buf_size *= 2;
|
jstate->clocations_buf_size *= 2;
|
||||||
jstate->clocations = (pgssLocationLen *)
|
jstate->clocations = (LocationLen *)
|
||||||
repalloc(jstate->clocations,
|
repalloc(jstate->clocations,
|
||||||
jstate->clocations_buf_size *
|
jstate->clocations_buf_size *
|
||||||
sizeof(pgssLocationLen));
|
sizeof(LocationLen));
|
||||||
}
|
}
|
||||||
jstate->clocations[jstate->clocations_count].location = location;
|
jstate->clocations[jstate->clocations_count].location = location;
|
||||||
/* initialize lengths to -1 to simplify fill_in_constant_lengths */
|
/* initialize lengths to -1 to simplify fill_in_constant_lengths */
|
||||||
|
@ -2382,6 +2461,7 @@ RecordConstLocation(pgssJumbleState *jstate, int location)
|
||||||
jstate->clocations_count++;
|
jstate->clocations_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate a normalized version of the query string that will be used to
|
* Generate a normalized version of the query string that will be used to
|
||||||
|
@ -2403,7 +2483,7 @@ RecordConstLocation(pgssJumbleState *jstate, int location)
|
||||||
* Returns a palloc'd string.
|
* Returns a palloc'd string.
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
generate_normalized_query(pgssJumbleState *jstate, const char *query,
|
generate_normalized_query(JumbleState *jstate, const char *query,
|
||||||
int query_loc, int *query_len_p, int encoding)
|
int query_loc, int *query_len_p, int encoding)
|
||||||
{
|
{
|
||||||
char *norm_query;
|
char *norm_query;
|
||||||
|
@ -2510,10 +2590,10 @@ generate_normalized_query(pgssJumbleState *jstate, const char *query,
|
||||||
* reason for a constant to start with a '-'.
|
* reason for a constant to start with a '-'.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
fill_in_constant_lengths(pgssJumbleState *jstate, const char *query,
|
fill_in_constant_lengths(JumbleState *jstate, const char *query,
|
||||||
int query_loc)
|
int query_loc)
|
||||||
{
|
{
|
||||||
pgssLocationLen *locs;
|
LocationLen *locs;
|
||||||
core_yyscan_t yyscanner;
|
core_yyscan_t yyscanner;
|
||||||
core_yy_extra_type yyextra;
|
core_yy_extra_type yyextra;
|
||||||
core_YYSTYPE yylval;
|
core_YYSTYPE yylval;
|
||||||
|
@ -2527,7 +2607,7 @@ fill_in_constant_lengths(pgssJumbleState *jstate, const char *query,
|
||||||
*/
|
*/
|
||||||
if (jstate->clocations_count > 1)
|
if (jstate->clocations_count > 1)
|
||||||
qsort(jstate->clocations, jstate->clocations_count,
|
qsort(jstate->clocations, jstate->clocations_count,
|
||||||
sizeof(pgssLocationLen), comp_location);
|
sizeof(LocationLen), comp_location);
|
||||||
locs = jstate->clocations;
|
locs = jstate->clocations;
|
||||||
|
|
||||||
/* initialize the flex scanner --- should match raw_parser() */
|
/* initialize the flex scanner --- should match raw_parser() */
|
||||||
|
@ -2611,13 +2691,13 @@ fill_in_constant_lengths(pgssJumbleState *jstate, const char *query,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* comp_location: comparator for qsorting pgssLocationLen structs by location
|
* comp_location: comparator for qsorting LocationLen structs by location
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
comp_location(const void *a, const void *b)
|
comp_location(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
int l = ((const pgssLocationLen *) a)->location;
|
int l = ((const LocationLen *) a)->location;
|
||||||
int r = ((const pgssLocationLen *) b)->location;
|
int r = ((const LocationLen *) b)->location;
|
||||||
|
|
||||||
if (l < r)
|
if (l < r)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2780,24 +2860,6 @@ SaveQueryText(uint64 bucketid, uint64 queryid, unsigned char *buf, const char *q
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64
|
|
||||||
get_query_id(pgssJumbleState *jstate, Query *query)
|
|
||||||
{
|
|
||||||
uint64 queryid;
|
|
||||||
|
|
||||||
/* Set up workspace for query jumbling */
|
|
||||||
jstate->jumble = (unsigned char *) palloc(JUMBLE_SIZE);
|
|
||||||
jstate->jumble_len = 0;
|
|
||||||
jstate->clocations_buf_size = 32;
|
|
||||||
jstate->clocations = (pgssLocationLen *) palloc(jstate->clocations_buf_size * sizeof(pgssLocationLen));
|
|
||||||
jstate->clocations_count = 0;
|
|
||||||
jstate->highest_extern_param_id = 0;
|
|
||||||
|
|
||||||
/* Compute query ID and mark the Query node with it */
|
|
||||||
JumbleQuery(jstate, query);
|
|
||||||
queryid = DatumGetUInt64(hash_any_extended(jstate->jumble, jstate->jumble_len, 0));
|
|
||||||
return queryid;
|
|
||||||
}
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
pg_stat_monitor_settings(PG_FUNCTION_ARGS)
|
pg_stat_monitor_settings(PG_FUNCTION_ARGS)
|
||||||
|
@ -3086,3 +3148,23 @@ extract_query_comments(const char *query)
|
||||||
regfree(&preg);
|
regfree(&preg);
|
||||||
return comments;
|
return comments;
|
||||||
}
|
}
|
||||||
|
#if PG_VERSION_NUM < 140000
|
||||||
|
static uint64
|
||||||
|
get_query_id(JumbleState *jstate, Query *query)
|
||||||
|
{
|
||||||
|
uint64 queryid;
|
||||||
|
|
||||||
|
/* Set up workspace for query jumbling */
|
||||||
|
jstate->jumble = (unsigned char *) palloc(JUMBLE_SIZE);
|
||||||
|
jstate->jumble_len = 0;
|
||||||
|
jstate->clocations_buf_size = 32;
|
||||||
|
jstate->clocations = (LocationLen *) palloc(jstate->clocations_buf_size * sizeof(LocationLen));
|
||||||
|
jstate->clocations_count = 0;
|
||||||
|
jstate->highest_extern_param_id = 0;
|
||||||
|
|
||||||
|
/* Compute query ID and mark the Query node with it */
|
||||||
|
JumbleQuery(jstate, query);
|
||||||
|
queryid = DatumGetUInt64(hash_any_extended(jstate->jumble, jstate->jumble_len, 0));
|
||||||
|
return queryid;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -323,20 +323,21 @@ do { \
|
||||||
memset(&x->bucket_entry, 0, MAX_BUCKETS * sizeof(uint64)); \
|
memset(&x->bucket_entry, 0, MAX_BUCKETS * sizeof(uint64)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM < 140000
|
||||||
/*
|
/*
|
||||||
* Struct for tracking locations/lengths of constants during normalization
|
* Struct for tracking locations/lengths of constants during normalization
|
||||||
*/
|
*/
|
||||||
typedef struct pgssLocationLen
|
typedef struct LocationLen
|
||||||
{
|
{
|
||||||
int location; /* start offset in query text */
|
int location; /* start offset in query text */
|
||||||
int length; /* length in bytes, or -1 to ignore */
|
int length; /* length in bytes, or -1 to ignore */
|
||||||
} pgssLocationLen;
|
} LocationLen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Working state for computing a query jumble and producing a normalized
|
* Working state for computing a query jumble and producing a normalized
|
||||||
* query string
|
* query string
|
||||||
*/
|
*/
|
||||||
typedef struct pgssJumbleState
|
typedef struct JumbleState
|
||||||
{
|
{
|
||||||
/* Jumble of current query tree */
|
/* Jumble of current query tree */
|
||||||
unsigned char *jumble;
|
unsigned char *jumble;
|
||||||
|
@ -345,7 +346,7 @@ typedef struct pgssJumbleState
|
||||||
Size jumble_len;
|
Size jumble_len;
|
||||||
|
|
||||||
/* Array of locations of constants that should be removed */
|
/* Array of locations of constants that should be removed */
|
||||||
pgssLocationLen *clocations;
|
LocationLen *clocations;
|
||||||
|
|
||||||
/* Allocated length of clocations array */
|
/* Allocated length of clocations array */
|
||||||
int clocations_buf_size;
|
int clocations_buf_size;
|
||||||
|
@ -355,7 +356,8 @@ typedef struct pgssJumbleState
|
||||||
|
|
||||||
/* highest Param id we've seen, in order to start normalization correctly */
|
/* highest Param id we've seen, in order to start normalization correctly */
|
||||||
int highest_extern_param_id;
|
int highest_extern_param_id;
|
||||||
} pgssJumbleState;
|
} JumbleState;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Links to shared memory state */
|
/* Links to shared memory state */
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
CREATE EXTENSION pg_stat_monitor;
|
||||||
|
SELECT pg_stat_monitor_reset();
|
||||||
|
pg_stat_monitor_reset
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 1/0; -- divide by zero
|
||||||
|
ERROR: division by zero
|
||||||
|
SELECT * FROM unknown; -- unknown table
|
||||||
|
ERROR: relation "unknown" does not exist
|
||||||
|
LINE 1: SELECT * FROM unknown;
|
||||||
|
^
|
||||||
|
ELECET * FROM unknown; -- syntax error
|
||||||
|
ERROR: syntax error at or near "ELECET"
|
||||||
|
LINE 1: ELECET * FROM unknown;
|
||||||
|
^
|
||||||
|
do $$
|
||||||
|
BEGIN
|
||||||
|
RAISE WARNING 'warning message';
|
||||||
|
END $$;
|
||||||
|
WARNING: warning message
|
||||||
|
SELECT query, elevel, sqlcode, message FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||||
|
query | elevel | sqlcode | message
|
||||||
|
-----------------------------------------------------------------------------------------+--------+---------+-----------------------------------
|
||||||
|
ELECET * FROM unknown; | 21 | 42601 | syntax error at or near "ELECET"
|
||||||
|
SELECT * FROM unknown; | 21 | 42P01 | relation "unknown" does not exist
|
||||||
|
SELECT 1/0; | 21 | 22012 | division by zero
|
||||||
|
SELECT pg_stat_monitor_reset(); | 0 | |
|
||||||
|
SELECT query, elevel, sqlcode, message FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 0 | |
|
||||||
|
do $$ +| 19 | 01000 | warning message
|
||||||
|
BEGIN +| | |
|
||||||
|
RAISE WARNING 'warning message'; +| | |
|
||||||
|
END $$; | | |
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
SELECT pg_stat_monitor_reset();
|
||||||
|
pg_stat_monitor_reset
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
DROP EXTENSION pg_stat_monitor;
|
|
@ -8545,7 +8545,7 @@ SELECT query, rows_retrieved FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||||
-------------------------------------------------------------------------------+----------------
|
-------------------------------------------------------------------------------+----------------
|
||||||
SELECT * FROM t1 LIMIT $1 | 10
|
SELECT * FROM t1 LIMIT $1 | 10
|
||||||
SELECT * FROM t1; | 1000
|
SELECT * FROM t1; | 1000
|
||||||
SELECT b FROM t2 FOR UPDATE; | 5000
|
SELECT * FROM t2; | 5000
|
||||||
SELECT pg_stat_monitor_reset(); | 1
|
SELECT pg_stat_monitor_reset(); | 1
|
||||||
SELECT query, rows_retrieved FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 0
|
SELECT query, rows_retrieved FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 0
|
||||||
SELECt * FROM t2 WHERE b % $1 = $2 | 2500
|
SELECt * FROM t2 WHERE b % $1 = $2 | 2500
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,51 @@
|
||||||
|
CREATE EXTENSION pg_stat_monitor;
|
||||||
|
SELECT pg_stat_monitor_reset();
|
||||||
|
pg_stat_monitor_reset
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return (select $1 + $2);
|
||||||
|
END; $$ language plpgsql;
|
||||||
|
CREATE OR REPLACE function add2(int, int) RETURNS int as
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return add($1,$2);
|
||||||
|
END;
|
||||||
|
$$ language plpgsql;
|
||||||
|
SELECT add2(1,2);
|
||||||
|
add2
|
||||||
|
------
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||||
|
query | top_query
|
||||||
|
--------------------------------------------------------------------------+--------------------
|
||||||
|
(select $1 + $2) | SELECT add2($1,$2)
|
||||||
|
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS +|
|
||||||
|
$$ +|
|
||||||
|
BEGIN +|
|
||||||
|
return (select $1 + $2); +|
|
||||||
|
END; $$ language plpgsql; |
|
||||||
|
CREATE OR REPLACE function add2(int, int) RETURNS int as +|
|
||||||
|
$$ +|
|
||||||
|
BEGIN +|
|
||||||
|
return add($1,$2); +|
|
||||||
|
END; +|
|
||||||
|
$$ language plpgsql; |
|
||||||
|
SELECT add2($1,$2) |
|
||||||
|
SELECT pg_stat_monitor_reset(); |
|
||||||
|
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C"; |
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
SELECT pg_stat_monitor_reset();
|
||||||
|
pg_stat_monitor_reset
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
DROP EXTENSION pg_stat_monitor;
|
Loading…
Reference in New Issue