diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index a0e7a46871..b04b4d6ce1 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -21,7 +21,7 @@ * 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. @@ -95,7 +95,7 @@ PG_MODULE_MAGIC; #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; @@ -130,7 +130,7 @@ typedef struct pgssHashKey { Oid userid; /* user OID */ Oid dbid; /* database OID */ - uint32 queryid; /* query identifier */ + uint64 queryid; /* query identifier */ } pgssHashKey; /* @@ -301,10 +301,8 @@ static void pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, 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, @@ -500,12 +498,10 @@ pgss_shmem_startup(void) 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); @@ -781,7 +777,7 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query) 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) @@ -797,7 +793,7 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query) */ if (query->utilityStmt) { - query->queryId = 0; + query->queryId = UINT64CONST(0); return; } @@ -812,14 +808,15 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query) /* 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 @@ -855,7 +852,7 @@ pgss_ExecutorStart(QueryDesc *queryDesc, int eflags) * 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 @@ -926,9 +923,9 @@ pgss_ExecutorFinish(QueryDesc *queryDesc) 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 @@ -1069,45 +1066,16 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, } } -/* - * 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)); } /* @@ -1121,7 +1089,7 @@ pgss_hash_string(const char *str, int len) * 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, @@ -1173,7 +1141,7 @@ pgss_store(const char *query, uint32 queryId, /* * 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 */ @@ -2324,8 +2292,10 @@ AppendJumble(pgssJumbleState *jstate, const unsigned char *item, Size size) 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); } diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index 5dc26ed17a..1b477baecb 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -162,7 +162,7 @@ ExecSerializePlan(Plan *plan, EState *estate) */ pstmt = makeNode(PlannedStmt); pstmt->commandType = CMD_SELECT; - pstmt->queryId = 0; + pstmt->queryId = UINT64CONST(0); pstmt->hasReturning = false; pstmt->hasModifyingCTE = false; pstmt->canSetTag = true; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 2532edc94a..43d62062bc 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -54,6 +54,11 @@ static void outChar(StringInfo str, char c); #define WRITE_UINT_FIELD(fldname) \ appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname) +/* Write an unsigned integer field (anything written with UINT64_FORMAT) */ +#define WRITE_UINT64_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " " UINT64_FORMAT, \ + node->fldname) + /* Write an OID field (don't hard-wire assumption that OID is same as uint) */ #define WRITE_OID_FIELD(fldname) \ appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname) @@ -260,7 +265,7 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node) WRITE_NODE_TYPE("PLANNEDSTMT"); WRITE_ENUM_FIELD(commandType, CmdType); - WRITE_UINT_FIELD(queryId); + WRITE_UINT64_FIELD(queryId); WRITE_BOOL_FIELD(hasReturning); WRITE_BOOL_FIELD(hasModifyingCTE); WRITE_BOOL_FIELD(canSetTag); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 07ba69178c..ccb6a1f4ac 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -33,6 +33,7 @@ #include "nodes/parsenodes.h" #include "nodes/plannodes.h" #include "nodes/readfuncs.h" +#include "utils/builtins.h" /* @@ -70,6 +71,12 @@ 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 */ \ @@ -231,7 +238,7 @@ _readQuery(void) 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); @@ -1456,7 +1463,7 @@ _readPlannedStmt(void) 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); diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 7054d4f77d..7a61af7905 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -3575,7 +3575,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events) List * QueryRewrite(Query *parsetree) { - uint32 input_query_id = parsetree->queryId; + uint64 input_query_id = parsetree->queryId; List *querylist; List *results; ListCell *l; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 50eec730b3..732e5d6788 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -111,7 +111,7 @@ typedef struct Query QuerySource querySource; /* where did I come from? */ - uint32 queryId; /* query identifier (can be set by plugins) */ + uint64 queryId; /* query identifier (can be set by plugins) */ bool canSetTag; /* do I set the command result tag? */ diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index a382331f41..dd74efa9a4 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -44,7 +44,7 @@ typedef struct PlannedStmt CmdType commandType; /* select|insert|update|delete|utility */ - uint32 queryId; /* query identifier (copied from Query) */ + uint64 queryId; /* query identifier (copied from Query) */ bool hasReturning; /* is it insert|update|delete RETURNING? */