@ -21,7 +21,7 @@
* as the collations of Vars and , most notably , the values of constants .
* 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
* 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
* 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
* tree ( s ) generated from the query . The executor can then use this value
* to blame query costs on the proper queryId .
* 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"
# define PGSS_TEXT_FILE PG_STAT_TMP_DIR " / pgss_query_texts.stat"
/* Magic number identifying the stats file format */
/* 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 */
/* PostgreSQL major version number, changes in which invalidate all entries */
static const uint32 PGSS_PG_MAJOR_VERSION = PG_VERSION_NUM / 100 ;
static const uint32 PGSS_PG_MAJOR_VERSION = PG_VERSION_NUM / 100 ;
@ -130,7 +130,7 @@ typedef struct pgssHashKey
{
{
Oid userid ; /* user OID */
Oid userid ; /* user OID */
Oid dbid ; /* database OID */
Oid dbid ; /* database OID */
uint32 queryid ; /* query identifier */
uint64 queryid ; /* query identifier */
} pgssHashKey ;
} pgssHashKey ;
/*
/*
@ -301,10 +301,8 @@ static void pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
ProcessUtilityContext context , ParamListInfo params ,
ProcessUtilityContext context , ParamListInfo params ,
QueryEnvironment * queryEnv ,
QueryEnvironment * queryEnv ,
DestReceiver * dest , char * completionTag ) ;
DestReceiver * dest , char * completionTag ) ;
static uint32 pgss_hash_fn ( const void * key , Size keysize ) ;
static uint64 pgss_hash_string ( const char * str , int len ) ;
static int pgss_match_fn ( const void * key1 , const void * key2 , Size keysize ) ;
static void pgss_store ( const char * query , uint64 queryId ,
static uint32 pgss_hash_string ( const char * str , int len ) ;
static void pgss_store ( const char * query , uint32 queryId ,
int query_location , int query_len ,
int query_location , int query_len ,
double total_time , uint64 rows ,
double total_time , uint64 rows ,
const BufferUsage * bufusage ,
const BufferUsage * bufusage ,
@ -500,12 +498,10 @@ pgss_shmem_startup(void)
memset ( & info , 0 , sizeof ( info ) ) ;
memset ( & info , 0 , sizeof ( info ) ) ;
info . keysize = sizeof ( pgssHashKey ) ;
info . keysize = sizeof ( pgssHashKey ) ;
info . entrysize = sizeof ( pgssEntry ) ;
info . entrysize = sizeof ( pgssEntry ) ;
info . hash = pgss_hash_fn ;
info . match = pgss_match_fn ;
pgss_hash = ShmemInitHash ( " pg_stat_statements hash " ,
pgss_hash = ShmemInitHash ( " pg_stat_statements hash " ,
pgss_max , pgss_max ,
pgss_max , pgss_max ,
& info ,
& info ,
HASH_ELEM | HASH_FUNCTION | HASH_COMPARE ) ;
HASH_ELEM | HASH_BLOBS ) ;
LWLockRelease ( AddinShmemInitLock ) ;
LWLockRelease ( AddinShmemInitLock ) ;
@ -781,7 +777,7 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query)
prev_post_parse_analyze_hook ( pstate , query ) ;
prev_post_parse_analyze_hook ( pstate , query ) ;
/* Assert we didn't do this already */
/* Assert we didn't do this already */
Assert ( query - > queryId = = 0 ) ;
Assert ( query - > queryId = = UINT64CONST ( 0 ) ) ;
/* Safety check... */
/* Safety check... */
if ( ! pgss | | ! pgss_hash )
if ( ! pgss | | ! pgss_hash )
@ -797,7 +793,7 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query)
*/
*/
if ( query - > utilityStmt )
if ( query - > utilityStmt )
{
{
query - > queryId = 0 ;
query - > queryId = UINT64CONST ( 0 ) ;
return ;
return ;
}
}
@ -812,14 +808,15 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query)
/* Compute query ID and mark the Query node with it */
/* Compute query ID and mark the Query node with it */
JumbleQuery ( & jstate , query ) ;
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
* If we are unlucky enough to get a hash of zero , use 1 instead , to
* prevent confusion with the utility - statement case .
* prevent confusion with the utility - statement case .
*/
*/
if ( query - > queryId = = 0 )
if ( query - > queryId = = UINT64CONST ( 0 ) )
query - > queryId = 1 ;
query - > queryId = UINT64CONST ( 1 ) ;
/*
/*
* If we were able to identify any ignorable constants , we immediately
* 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
* counting of optimizable statements that are directly contained in
* utility statements .
* 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
* Set up to track total elapsed time in ExecutorRun . Make sure the
@ -926,9 +923,9 @@ pgss_ExecutorFinish(QueryDesc *queryDesc)
static void
static void
pgss_ExecutorEnd ( QueryDesc * queryDesc )
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
* 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
* Given an arbitrarily long query string , produce a hash for the purposes of
* identifying the query , without normalizing constants . Used when hashing
* identifying the query , without normalizing constants . Used when hashing
* utility statements .
* utility statements .
*/
*/
static uint32
static uint64
pgss_hash_string ( const char * str , int len )
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 .
* query string . total_time , rows , bufusage are ignored in this case .
*/
*/
static void
static void
pgss_store ( const char * query , uint32 queryId ,
pgss_store ( const char * query , uint64 queryId ,
int query_location , int query_len ,
int query_location , int query_len ,
double total_time , uint64 rows ,
double total_time , uint64 rows ,
const BufferUsage * bufusage ,
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 .
* 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 ) ;
queryId = pgss_hash_string ( query , query_len ) ;
/* Set up key for hashtable search */
/* Set up key for hashtable search */
@ -2324,8 +2292,10 @@ AppendJumble(pgssJumbleState *jstate, const unsigned char *item, Size size)
if ( jumble_len > = JUMBLE_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 ) ) ;
memcpy ( jumble , & start_hash , sizeof ( start_hash ) ) ;
jumble_len = sizeof ( start_hash ) ;
jumble_len = sizeof ( start_hash ) ;
}
}