@@ -67,7 +67,9 @@ PG_MODULE_MAGIC;
67
67
#define PGSS_DUMP_FILE "global/pg_stat_statements.stat"
68
68
69
69
/* This constant defines the magic number in the stats file header */
70
- static const uint32 PGSS_FILE_HEADER = 0x20120328 ;
70
+ static const uint32 PGSS_FILE_HEADER = 0x20131115 ;
71
+ /* PostgreSQL major version number, changes in which invalidate all entries */
72
+ static const uint32 PGSS_PG_MAJOR_VERSION = PG_VERSION_NUM / 100 ;
71
73
72
74
/* XXX: Should USAGE_EXEC reflect execution time and/or buffer usage? */
73
75
#define USAGE_EXEC (duration ) (1.0)
@@ -79,6 +81,16 @@ static const uint32 PGSS_FILE_HEADER = 0x20120328;
79
81
80
82
#define JUMBLE_SIZE 1024 /* query serialization buffer size */
81
83
84
+ /*
85
+ * Extension version number, for supporting older extension versions' objects
86
+ */
87
+ typedef enum pgssVersion
88
+ {
89
+ PGSS_V1_0 = 0 ,
90
+ PGSS_V1_1 ,
91
+ PGSS_V1_2
92
+ } pgssVersion ;
93
+
82
94
/*
83
95
* Hashtable key that defines the identity of a hashtable entry. We separate
84
96
* queries by user and by database even if they are otherwise identical.
@@ -390,6 +402,7 @@ pgss_shmem_startup(void)
390
402
FILE * file ;
391
403
uint32 header ;
392
404
int32 num ;
405
+ int32 pgver ;
393
406
int32 i ;
394
407
int query_size ;
395
408
int buffer_size ;
@@ -465,6 +478,8 @@ pgss_shmem_startup(void)
465
478
466
479
if (fread (& header , sizeof (uint32 ), 1 , file ) != 1 ||
467
480
header != PGSS_FILE_HEADER ||
481
+ fread (& pgver , sizeof (uint32 ), 1 , file ) != 1 ||
482
+ pgver != PGSS_PG_MAJOR_VERSION ||
468
483
fread (& num , sizeof (int32 ), 1 , file ) != 1 )
469
484
goto error ;
470
485
@@ -565,6 +580,8 @@ pgss_shmem_shutdown(int code, Datum arg)
565
580
566
581
if (fwrite (& PGSS_FILE_HEADER , sizeof (uint32 ), 1 , file ) != 1 )
567
582
goto error ;
583
+ if (fwrite (& PGSS_PG_MAJOR_VERSION , sizeof (uint32 ), 1 , file ) != 1 )
584
+ goto error ;
568
585
num_entries = hash_get_num_entries (pgss_hash );
569
586
if (fwrite (& num_entries , sizeof (int32 ), 1 , file ) != 1 )
570
587
goto error ;
@@ -1069,7 +1086,8 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS)
1069
1086
}
1070
1087
1071
1088
#define PG_STAT_STATEMENTS_COLS_V1_0 14
1072
- #define PG_STAT_STATEMENTS_COLS 18
1089
+ #define PG_STAT_STATEMENTS_COLS_V1_1 18
1090
+ #define PG_STAT_STATEMENTS_COLS 19
1073
1091
1074
1092
/*
1075
1093
* Retrieve statement statistics.
@@ -1086,7 +1104,7 @@ pg_stat_statements(PG_FUNCTION_ARGS)
1086
1104
bool is_superuser = superuser ();
1087
1105
HASH_SEQ_STATUS hash_seq ;
1088
1106
pgssEntry * entry ;
1089
- bool sql_supports_v1_1_counters = true ;
1107
+ pgssVersion detected_version ;
1090
1108
1091
1109
if (!pgss || !pgss_hash )
1092
1110
ereport (ERROR ,
@@ -1107,8 +1125,21 @@ pg_stat_statements(PG_FUNCTION_ARGS)
1107
1125
/* Build a tuple descriptor for our result type */
1108
1126
if (get_call_result_type (fcinfo , NULL , & tupdesc ) != TYPEFUNC_COMPOSITE )
1109
1127
elog (ERROR , "return type must be a row type" );
1110
- if (tupdesc -> natts == PG_STAT_STATEMENTS_COLS_V1_0 )
1111
- sql_supports_v1_1_counters = false;
1128
+
1129
+ switch (tupdesc -> natts )
1130
+ {
1131
+ case PG_STAT_STATEMENTS_COLS_V1_0 :
1132
+ detected_version = PGSS_V1_0 ;
1133
+ break ;
1134
+ case PG_STAT_STATEMENTS_COLS_V1_1 :
1135
+ detected_version = PGSS_V1_1 ;
1136
+ break ;
1137
+ case PG_STAT_STATEMENTS_COLS :
1138
+ detected_version = PGSS_V1_2 ;
1139
+ break ;
1140
+ default :
1141
+ elog (ERROR , "pgss version unrecognized from tuple descriptor" );
1142
+ }
1112
1143
1113
1144
per_query_ctx = rsinfo -> econtext -> ecxt_per_query_memory ;
1114
1145
oldcontext = MemoryContextSwitchTo (per_query_ctx );
@@ -1140,6 +1171,9 @@ pg_stat_statements(PG_FUNCTION_ARGS)
1140
1171
{
1141
1172
char * qstr ;
1142
1173
1174
+ if (detected_version >= PGSS_V1_2 )
1175
+ values [i ++ ] = Int64GetDatumFast ((int64 ) entry -> key .queryid );
1176
+
1143
1177
qstr = (char * )
1144
1178
pg_do_encoding_conversion ((unsigned char * ) entry -> query ,
1145
1179
entry -> query_len ,
@@ -1150,7 +1184,12 @@ pg_stat_statements(PG_FUNCTION_ARGS)
1150
1184
pfree (qstr );
1151
1185
}
1152
1186
else
1187
+ {
1188
+ if (detected_version >= PGSS_V1_2 )
1189
+ nulls [i ++ ] = true;
1190
+
1153
1191
values [i ++ ] = CStringGetTextDatum ("<insufficient privilege>" );
1192
+ }
1154
1193
1155
1194
/* copy counters to a local variable to keep locking time short */
1156
1195
{
@@ -1170,24 +1209,27 @@ pg_stat_statements(PG_FUNCTION_ARGS)
1170
1209
values [i ++ ] = Int64GetDatumFast (tmp .rows );
1171
1210
values [i ++ ] = Int64GetDatumFast (tmp .shared_blks_hit );
1172
1211
values [i ++ ] = Int64GetDatumFast (tmp .shared_blks_read );
1173
- if (sql_supports_v1_1_counters )
1212
+ if (detected_version >= PGSS_V1_1 )
1174
1213
values [i ++ ] = Int64GetDatumFast (tmp .shared_blks_dirtied );
1175
1214
values [i ++ ] = Int64GetDatumFast (tmp .shared_blks_written );
1176
1215
values [i ++ ] = Int64GetDatumFast (tmp .local_blks_hit );
1177
1216
values [i ++ ] = Int64GetDatumFast (tmp .local_blks_read );
1178
- if (sql_supports_v1_1_counters )
1217
+ if (detected_version >= PGSS_V1_1 )
1179
1218
values [i ++ ] = Int64GetDatumFast (tmp .local_blks_dirtied );
1180
1219
values [i ++ ] = Int64GetDatumFast (tmp .local_blks_written );
1181
1220
values [i ++ ] = Int64GetDatumFast (tmp .temp_blks_read );
1182
1221
values [i ++ ] = Int64GetDatumFast (tmp .temp_blks_written );
1183
- if (sql_supports_v1_1_counters )
1222
+ if (detected_version >= PGSS_V1_1 )
1184
1223
{
1185
1224
values [i ++ ] = Float8GetDatumFast (tmp .blk_read_time );
1186
1225
values [i ++ ] = Float8GetDatumFast (tmp .blk_write_time );
1187
1226
}
1188
1227
1189
- Assert (i == (sql_supports_v1_1_counters ?
1190
- PG_STAT_STATEMENTS_COLS : PG_STAT_STATEMENTS_COLS_V1_0 ));
1228
+ Assert (i == (detected_version == PGSS_V1_0 ?
1229
+ PG_STAT_STATEMENTS_COLS_V1_0 :
1230
+ detected_version == PGSS_V1_1 ?
1231
+ PG_STAT_STATEMENTS_COLS_V1_1 :
1232
+ PG_STAT_STATEMENTS_COLS ));
1191
1233
1192
1234
tuplestore_putvalues (tupstore , tupdesc , values , nulls );
1193
1235
}
0 commit comments