diff options
Diffstat (limited to 'contrib/pg_stat_statements/pg_stat_statements.c')
-rw-r--r-- | contrib/pg_stat_statements/pg_stat_statements.c | 96 |
1 files changed, 84 insertions, 12 deletions
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 9131991b837..f177ebaa2c6 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -290,6 +290,7 @@ void _PG_init(void); void _PG_fini(void); PG_FUNCTION_INFO_V1(pg_stat_statements_reset); +PG_FUNCTION_INFO_V1(pg_stat_statements_reset_1_7); PG_FUNCTION_INFO_V1(pg_stat_statements_1_2); PG_FUNCTION_INFO_V1(pg_stat_statements_1_3); PG_FUNCTION_INFO_V1(pg_stat_statements); @@ -327,7 +328,7 @@ static char *qtext_fetch(Size query_offset, int query_len, char *buffer, Size buffer_size); static bool need_gc_qtexts(void); static void gc_qtexts(void); -static void entry_reset(void); +static void entry_reset(Oid userid, Oid dbid, uint64 queryid); static void AppendJumble(pgssJumbleState *jstate, const unsigned char *item, Size size); static void JumbleQuery(pgssJumbleState *jstate, Query *query); @@ -1148,8 +1149,17 @@ pgss_store(const char *query, uint64 queryId, * For utility statements, we just hash the query string to get an ID. */ if (queryId == UINT64CONST(0)) + { queryId = pgss_hash_string(query, query_len); + /* + * If we are unlucky enough to get a hash of zero(invalid), use queryID + * as 2 instead, queryID 1 is already in use for normal statements. + */ + if (queryId == UINT64CONST(0)) + queryId = UINT64CONST(2); + } + /* Set up key for hashtable search */ key.userid = GetUserId(); key.dbid = MyDatabaseId; @@ -1293,16 +1303,32 @@ done: } /* - * Reset all statement statistics. + * Reset statement statistics corresponding to userid, dbid, and queryid. + */ +Datum +pg_stat_statements_reset_1_7(PG_FUNCTION_ARGS) +{ + Oid userid; + Oid dbid; + uint64 queryid; + + userid = PG_GETARG_OID(0); + dbid = PG_GETARG_OID(1); + queryid = (uint64) PG_GETARG_INT64(2); + + entry_reset(userid, dbid, queryid); + + PG_RETURN_VOID(); +} + +/* + * Reset statement statistics. */ Datum pg_stat_statements_reset(PG_FUNCTION_ARGS) { - if (!pgss || !pgss_hash) - ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("pg_stat_statements must be loaded via shared_preload_libraries"))); - entry_reset(); + entry_reset(0, 0, 0); + PG_RETURN_VOID(); } @@ -2229,23 +2255,68 @@ gc_fail: } /* - * Release all entries. + * Release entries corresponding to parameters passed. */ static void -entry_reset(void) +entry_reset(Oid userid, Oid dbid, uint64 queryid) { HASH_SEQ_STATUS hash_seq; pgssEntry *entry; FILE *qfile; + long num_entries; + long num_remove = 0; + pgssHashKey key; + + if (!pgss || !pgss_hash) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("pg_stat_statements must be loaded via shared_preload_libraries"))); LWLockAcquire(pgss->lock, LW_EXCLUSIVE); + num_entries = hash_get_num_entries(pgss_hash); - hash_seq_init(&hash_seq, pgss_hash); - while ((entry = hash_seq_search(&hash_seq)) != NULL) + if (userid != 0 && dbid != 0 && queryid != UINT64CONST(0)) + { + /* If all the parameters are available, use the fast path. */ + key.userid = userid; + key.dbid = dbid; + key.queryid = queryid; + + /* Remove the key if exists */ + entry = (pgssEntry *) hash_search(pgss_hash, &key, HASH_REMOVE, NULL); + if (entry) /* found */ + num_remove++; + } + else if (userid != 0 || dbid != 0 || queryid != UINT64CONST(0)) { - hash_search(pgss_hash, &entry->key, HASH_REMOVE, NULL); + /* Remove entries corresponding to valid parameters. */ + hash_seq_init(&hash_seq, pgss_hash); + while ((entry = hash_seq_search(&hash_seq)) != NULL) + { + if ((!userid || entry->key.userid == userid) && + (!dbid || entry->key.dbid == dbid) && + (!queryid || entry->key.queryid == queryid)) + { + hash_search(pgss_hash, &entry->key, HASH_REMOVE, NULL); + num_remove++; + } + } + } + else + { + /* Remove all entries. */ + hash_seq_init(&hash_seq, pgss_hash); + while ((entry = hash_seq_search(&hash_seq)) != NULL) + { + hash_search(pgss_hash, &entry->key, HASH_REMOVE, NULL); + num_remove++; + } } + /* All entries are removed? */ + if (num_entries != num_remove) + goto release_lock; + /* * Write new empty query file, perhaps even creating a new one to recover * if the file was missing. @@ -2274,6 +2345,7 @@ done: /* This counts as a query text garbage collection for our purposes */ record_gc_qtexts(); +release_lock: LWLockRelease(pgss->lock); } |