@@ -115,7 +115,8 @@ typedef enum pgssVersion
115115{
116116PGSS_V1_0 = 0 ,
117117PGSS_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{
137138int64 calls ;/* # of times executed */
138139double 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 */
139144int64 rows ;/* total # of retrieved or affected rows */
140145int64 shared_blks_hit ;/* # of shared buffer hits */
141146int64 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
320326int * 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
12161223e -> counters .calls += 1 ;
12171224e -> 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+ }
12181251e -> counters .rows += rows ;
12191252e -> counters .shared_blks_hit += bufusage -> shared_blks_hit ;
12201253e -> 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,
13601404if (api_version != PGSS_V1_2 )
13611405elog (ERROR ,"incorrect number of output arguments" );
13621406break ;
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 ;
13631411default :
13641412elog (ERROR ,"incorrect number of output arguments" );
13651413}
@@ -1519,6 +1567,23 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
15191567
15201568values [i ++ ]= Int64GetDatumFast (tmp .calls );
15211569values [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+ }
15221587values [i ++ ]= Int64GetDatumFast (tmp .rows );
15231588values [i ++ ]= Int64GetDatumFast (tmp .shared_blks_hit );
15241589values [i ++ ]= Int64GetDatumFast (tmp .shared_blks_read );
@@ -1541,6 +1606,7 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
15411606Assert (i == (api_version == PGSS_V1_0 ?PG_STAT_STATEMENTS_COLS_V1_0 :
15421607api_version == PGSS_V1_1 ?PG_STAT_STATEMENTS_COLS_V1_1 :
15431608api_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
15461612tuplestore_putvalues (tupstore ,tupdesc ,values ,nulls );
@@ -2899,3 +2965,20 @@ comp_location(const void *a, const void *b)
28992965else
29002966return 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 longint tmp = 0x5FE6EB50C7B537AAl - (* (long longint * )& 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+ }