@@ -115,7 +115,8 @@ typedef enum pgssVersion
115115{
116116 PGSS_V1_0 = 0 ,
117117 PGSS_V1_1 ,
118- PGSS_V1_2
118+ PGSS_V1_2 ,
119+ PGSS_V1_3
119120} pgssVersion ;
120121
121122/*
@@ -136,6 +137,10 @@ typedef struct Counters
136137{
137138 int64 calls ; /* # of times executed */
138139 double total_time ; /* total execution time, in msec */
140+ double min_time ; /* minimim execution time in msec */
141+ double max_time ; /* maximum execution time in msec */
142+ double mean_time ; /* mean execution time in msec */
143+ double sum_var_time ; /* sum of variances in execution time in msec */
139144 int64 rows ; /* total # of retrieved or affected rows */
140145 int64 shared_blks_hit ; /* # of shared buffer hits */
141146 int64 shared_blks_read ; /* # of shared disk blocks read */
@@ -274,6 +279,7 @@ void _PG_fini(void);
274279
275280PG_FUNCTION_INFO_V1 (pg_stat_statements_reset );
276281PG_FUNCTION_INFO_V1 (pg_stat_statements_1_2 );
282+ PG_FUNCTION_INFO_V1 (pg_stat_statements_1_3 );
277283PG_FUNCTION_INFO_V1 (pg_stat_statements );
278284
279285static void pgss_shmem_startup (void );
@@ -320,6 +326,7 @@ static char *generate_normalized_query(pgssJumbleState *jstate, const char *quer
320326 int * query_len_p , int encoding );
321327static void fill_in_constant_lengths (pgssJumbleState * jstate , const char * query );
322328static int comp_location (const void * a , const void * b );
329+ static inline double sqrtd (const double x );
323330
324331
325332/*
@@ -1215,6 +1222,32 @@ pgss_store(const char *query, uint32 queryId,
12151222
12161223 e -> counters .calls += 1 ;
12171224 e -> counters .total_time += total_time ;
1225+ if (e -> counters .calls == 1 )
1226+ {
1227+ e -> counters .min_time = total_time ;
1228+ e -> counters .max_time = total_time ;
1229+ e -> counters .mean_time = total_time ;
1230+ }
1231+ else
1232+ {
1233+ /*
1234+ * Welford's method for accurately computing variance.
1235+ * See <http://www.johndcook.com/blog/standard_deviation/>
1236+ */
1237+ double old_mean = e -> counters .mean_time ;
1238+
1239+ e -> counters .mean_time +=
1240+ (total_time - old_mean ) / e -> counters .calls ;
1241+ e -> counters .sum_var_time +=
1242+ (total_time - old_mean ) * (total_time - e -> counters .mean_time );
1243+
1244+ /* calculate min and max time */
1245+ if (e -> counters .min_time > total_time )
1246+ e -> counters .min_time = total_time ;
1247+ if (e -> counters .max_time < total_time )
1248+ e -> counters .max_time = total_time ;
1249+
1250+ }
12181251 e -> counters .rows += rows ;
12191252 e -> counters .shared_blks_hit += bufusage -> shared_blks_hit ;
12201253 e -> counters .shared_blks_read += bufusage -> shared_blks_read ;
@@ -1259,7 +1292,8 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS)
12591292#define PG_STAT_STATEMENTS_COLS_V1_0 14
12601293#define PG_STAT_STATEMENTS_COLS_V1_1 18
12611294#define PG_STAT_STATEMENTS_COLS_V1_2 19
1262- #define PG_STAT_STATEMENTS_COLS 19 /* maximum of above */
1295+ #define PG_STAT_STATEMENTS_COLS_V1_3 23
1296+ #define PG_STAT_STATEMENTS_COLS 23 /* maximum of above */
12631297
12641298/*
12651299 * Retrieve statement statistics.
@@ -1271,6 +1305,16 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS)
12711305 * expected API version is identified by embedding it in the C name of the
12721306 * function. Unfortunately we weren't bright enough to do that for 1.1.
12731307 */
1308+ Datum
1309+ pg_stat_statements_1_3 (PG_FUNCTION_ARGS )
1310+ {
1311+ bool showtext = PG_GETARG_BOOL (0 );
1312+
1313+ pg_stat_statements_internal (fcinfo , PGSS_V1_3 , showtext );
1314+
1315+ return (Datum ) 0 ;
1316+ }
1317+
12741318Datum
12751319pg_stat_statements_1_2 (PG_FUNCTION_ARGS )
12761320{
@@ -1360,6 +1404,10 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
13601404 if (api_version != PGSS_V1_2 )
13611405 elog (ERROR , "incorrect number of output arguments" );
13621406 break ;
1407+ case PG_STAT_STATEMENTS_COLS_V1_3 :
1408+ if (api_version != PGSS_V1_3 )
1409+ elog (ERROR , "incorrect number of output arguments" );
1410+ break ;
13631411 default :
13641412 elog (ERROR , "incorrect number of output arguments" );
13651413 }
@@ -1519,6 +1567,23 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
15191567
15201568 values [i ++ ] = Int64GetDatumFast (tmp .calls );
15211569 values [i ++ ] = Float8GetDatumFast (tmp .total_time );
1570+ if (api_version >= PGSS_V1_3 )
1571+ {
1572+ values [i ++ ] = Float8GetDatumFast (tmp .min_time );
1573+ values [i ++ ] = Float8GetDatumFast (tmp .max_time );
1574+ values [i ++ ] = Float8GetDatumFast (tmp .mean_time );
1575+ /*
1576+ * Note we are calculating the population variance here, not the
1577+ * sample variance, as we have data for the whole population,
1578+ * so Bessel's correction is not used, and we don't divide by
1579+ * tmp.calls - 1.
1580+ */
1581+ if (tmp .calls > 1 )
1582+ values [i ++ ] =
1583+ Float8GetDatumFast (sqrtd (tmp .sum_var_time / tmp .calls ));
1584+ else
1585+ values [i ++ ] = Float8GetDatumFast (0.0 );
1586+ }
15221587 values [i ++ ] = Int64GetDatumFast (tmp .rows );
15231588 values [i ++ ] = Int64GetDatumFast (tmp .shared_blks_hit );
15241589 values [i ++ ] = Int64GetDatumFast (tmp .shared_blks_read );
@@ -1541,6 +1606,7 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
15411606 Assert (i == (api_version == PGSS_V1_0 ? PG_STAT_STATEMENTS_COLS_V1_0 :
15421607 api_version == PGSS_V1_1 ? PG_STAT_STATEMENTS_COLS_V1_1 :
15431608 api_version == PGSS_V1_2 ? PG_STAT_STATEMENTS_COLS_V1_2 :
1609+ api_version == PGSS_V1_3 ? PG_STAT_STATEMENTS_COLS_V1_3 :
15441610 -1 /* fail if you forget to update this assert */ ));
15451611
15461612 tuplestore_putvalues (tupstore , tupdesc , values , nulls );
@@ -2899,3 +2965,20 @@ comp_location(const void *a, const void *b)
28992965 else
29002966 return 0 ;
29012967}
2968+
2969+ /*
2970+ * fast sqrt algorithm: reference from Fast inverse square root algorithms.
2971+ */
2972+ static inline double
2973+ sqrtd (const double x )
2974+ {
2975+ double x_half = 0.5 * x ;
2976+ long long int tmp = 0x5FE6EB50C7B537AAl - ( * (long long int * )& x >> 1 );
2977+ double x_result = * (double * )& tmp ;
2978+
2979+ x_result *= (1.5 - (x_half * x_result * x_result ));
2980+ /* If retry this calculation, it becomes higher precision at sqrt */
2981+ x_result *= (1.5 - (x_half * x_result * x_result ));
2982+
2983+ return x_result * x ;
2984+ }
0 commit comments