* as the collations of Vars and, most notably, the values of constants.
*
* This jumble is acquired at the end of parse analysis of each query, and
- * a 32-bit hash of it is stored into the query's Query.queryId field.
+ * a 64-bit hash of it is stored into the query's Query.queryId field.
* The server then copies this value around, making it available in plan
* tree(s) generated from the query. The executor can then use this value
* to blame query costs on the proper queryId.
#define PGSS_TEXT_FILE PG_STAT_TMP_DIR "/pgss_query_texts.stat"
/* Magic number identifying the stats file format */
-static const uint32 PGSS_FILE_HEADER = 0x20140125;
+static const uint32 PGSS_FILE_HEADER = 0x20171004;
/* PostgreSQL major version number, changes in which invalidate all entries */
static const uint32 PGSS_PG_MAJOR_VERSION = PG_VERSION_NUM / 100;
{
Oid userid; /* user OID */
Oid dbid; /* database OID */
- uint32 queryid; /* query identifier */
+ uint64 queryid; /* query identifier */
} pgssHashKey;
/*
ProcessUtilityContext context, ParamListInfo params,
QueryEnvironment *queryEnv,
DestReceiver *dest, char *completionTag);
-static uint32 pgss_hash_fn(const void *key, Size keysize);
-static int pgss_match_fn(const void *key1, const void *key2, Size keysize);
-static uint32 pgss_hash_string(const char *str, int len);
-static void pgss_store(const char *query, uint32 queryId,
+static uint64 pgss_hash_string(const char *str, int len);
+static void pgss_store(const char *query, uint64 queryId,
int query_location, int query_len,
double total_time, uint64 rows,
const BufferUsage *bufusage,
memset(&info, 0, sizeof(info));
info.keysize = sizeof(pgssHashKey);
info.entrysize = sizeof(pgssEntry);
- info.hash = pgss_hash_fn;
- info.match = pgss_match_fn;
pgss_hash = ShmemInitHash("pg_stat_statements hash",
pgss_max, pgss_max,
&info,
- HASH_ELEM | HASH_FUNCTION | HASH_COMPARE);
+ HASH_ELEM | HASH_BLOBS);
LWLockRelease(AddinShmemInitLock);
prev_post_parse_analyze_hook(pstate, query);
/* Assert we didn't do this already */
- Assert(query->queryId == 0);
+ Assert(query->queryId == UINT64CONST(0));
/* Safety check... */
if (!pgss || !pgss_hash)
*/
if (query->utilityStmt)
{
- query->queryId = 0;
+ query->queryId = UINT64CONST(0);
return;
}
/* Compute query ID and mark the Query node with it */
JumbleQuery(&jstate, query);
- query->queryId = hash_any(jstate.jumble, jstate.jumble_len);
+ query->queryId =
+ DatumGetUInt64(hash_any_extended(jstate.jumble, jstate.jumble_len, 0));
/*
* If we are unlucky enough to get a hash of zero, use 1 instead, to
* prevent confusion with the utility-statement case.
*/
- if (query->queryId == 0)
- query->queryId = 1;
+ if (query->queryId == UINT64CONST(0))
+ query->queryId = UINT64CONST(1);
/*
* If we were able to identify any ignorable constants, we immediately
* counting of optimizable statements that are directly contained in
* utility statements.
*/
- if (pgss_enabled() && queryDesc->plannedstmt->queryId != 0)
+ if (pgss_enabled() && queryDesc->plannedstmt->queryId != UINT64CONST(0))
{
/*
* Set up to track total elapsed time in ExecutorRun. Make sure the
static void
pgss_ExecutorEnd(QueryDesc *queryDesc)
{
- uint32 queryId = queryDesc->plannedstmt->queryId;
+ uint64 queryId = queryDesc->plannedstmt->queryId;
- if (queryId != 0 && queryDesc->totaltime && pgss_enabled())
+ if (queryId != UINT64CONST(0) && queryDesc->totaltime && pgss_enabled())
{
/*
* Make sure stats accumulation is done. (Note: it's okay if several
}
}
-/*
- * Calculate hash value for a key
- */
-static uint32
-pgss_hash_fn(const void *key, Size keysize)
-{
- const pgssHashKey *k = (const pgssHashKey *) key;
-
- return hash_uint32((uint32) k->userid) ^
- hash_uint32((uint32) k->dbid) ^
- hash_uint32((uint32) k->queryid);
-}
-
-/*
- * Compare two keys - zero means match
- */
-static int
-pgss_match_fn(const void *key1, const void *key2, Size keysize)
-{
- const pgssHashKey *k1 = (const pgssHashKey *) key1;
- const pgssHashKey *k2 = (const pgssHashKey *) key2;
-
- if (k1->userid == k2->userid &&
- k1->dbid == k2->dbid &&
- k1->queryid == k2->queryid)
- return 0;
- else
- return 1;
-}
-
/*
* Given an arbitrarily long query string, produce a hash for the purposes of
* identifying the query, without normalizing constants. Used when hashing
* utility statements.
*/
-static uint32
+static uint64
pgss_hash_string(const char *str, int len)
{
- return hash_any((const unsigned char *) str, len);
+ return DatumGetUInt64(hash_any_extended((const unsigned char *) str,
+ len, 0));
}
/*
* query string. total_time, rows, bufusage are ignored in this case.
*/
static void
-pgss_store(const char *query, uint32 queryId,
+pgss_store(const char *query, uint64 queryId,
int query_location, int query_len,
double total_time, uint64 rows,
const BufferUsage *bufusage,
/*
* For utility statements, we just hash the query string to get an ID.
*/
- if (queryId == 0)
+ if (queryId == UINT64CONST(0))
queryId = pgss_hash_string(query, query_len);
/* Set up key for hashtable search */
if (jumble_len >= JUMBLE_SIZE)
{
- uint32 start_hash = hash_any(jumble, JUMBLE_SIZE);
+ uint64 start_hash;
+ start_hash = DatumGetUInt64(hash_any_extended(jumble,
+ JUMBLE_SIZE, 0));
memcpy(jumble, &start_hash, sizeof(start_hash));
jumble_len = sizeof(start_hash);
}
#include "nodes/parsenodes.h"
#include "nodes/plannodes.h"
#include "nodes/readfuncs.h"
+#include "utils/builtins.h"
/*
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = atoui(token)
+/* Read an unsigned integer field (anything written using UINT64_FORMAT) */
+#define READ_UINT64_FIELD(fldname) \
+ token = pg_strtok(&length); /* skip :fldname */ \
+ token = pg_strtok(&length); /* get field value */ \
+ local_node->fldname = pg_strtouint64(token, NULL, 10)
+
/* Read an long integer field (anything written as ":fldname %ld") */
#define READ_LONG_FIELD(fldname) \
token = pg_strtok(&length); /* skip :fldname */ \
READ_ENUM_FIELD(commandType, CmdType);
READ_ENUM_FIELD(querySource, QuerySource);
- local_node->queryId = 0; /* not saved in output format */
+ local_node->queryId = UINT64CONST(0); /* not saved in output format */
READ_BOOL_FIELD(canSetTag);
READ_NODE_FIELD(utilityStmt);
READ_INT_FIELD(resultRelation);
READ_LOCALS(PlannedStmt);
READ_ENUM_FIELD(commandType, CmdType);
- READ_UINT_FIELD(queryId);
+ READ_UINT64_FIELD(queryId);
READ_BOOL_FIELD(hasReturning);
READ_BOOL_FIELD(hasModifyingCTE);
READ_BOOL_FIELD(canSetTag);