9.4 + gin_statpage. gin_statpage author is Alexander Korotkov <aekorotkov@gmail.com>
authorTeodor Sigaev <teodor@sigaev.ru>
Mon, 19 May 2014 19:41:55 +0000 (23:41 +0400)
committerTeodor Sigaev <teodor@sigaev.ru>
Mon, 19 May 2014 19:41:55 +0000 (23:41 +0400)
Makefile
README.gevel
expected/gevel.out.9.4 [new file with mode: 0644]
gevel.c
gevel.sql.in

index 2c72557..e15bc01 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ pg_version.txt:
        echo PG_MAJORVERSION | $(CPP) -undef -x c -w  -P $(CPPFLAGS) -include pg_config.h -o - - |  grep -v '^$$' | sed -e 's/"//g' > $@
        if [ -f expected/gevel.out.`cat pg_version.txt` ] ; \
        then \
-               cp $(top_srcdir)/$(subdir)/expected/gevel.out.`cat pg_version.txt` expected/gevel.out ; \
+               cp expected/gevel.out.`cat pg_version.txt` expected/gevel.out ; \
        else \
-               cp $(top_srcdir)/$(subdir)/expected/gevel.out.st expected/gevel.out ; \
+               cp expected/gevel.out.st expected/gevel.out ; \
        fi
index 35b81d1..2292c7a 100644 (file)
@@ -195,3 +195,28 @@ regression=# select gist_tree('pix');
                                 790
 (1 row)
 
+   * text gin_statpage(INDEXNAME)
+        Prints various stat about index internals.
+
+# select gin_statpage('gin_idx');
+         gin_statpage         
+------------------------------
+ totalPages:            32   +
+ dataPages:             1    +
+ dataInnerPages:        0    +
+ dataLeafPages:         1    +
+ dataInnerFreeSpace:    0    +
+ dataLeafFreeSpace:     4454 +
+ dataInnerTuplesCount:  0    +
+ dataLeafIptrsCount:    3600 +
+ entryPages:            31   +
+ entryInnerPages:       21   +
+ entryLeafPages:        10   +
+ entryInnerFreeSpace:   15160+
+ entryLeafFreeSpace:    32788+
+ entryInnerTuplesCount: 7810 +
+ entryLeafTuplesCount:  305  +
+ entryPostingSize:      42122+
+ entryPostingCount:     96759+
+ entryAttrSize:         64924+
+
diff --git a/expected/gevel.out.9.4 b/expected/gevel.out.9.4
new file mode 100644 (file)
index 0000000..22fa271
--- /dev/null
@@ -0,0 +1,524 @@
+SET client_min_messages = warning;
+\set ECHO none
+RESET client_min_messages;
+CREATE TABLE gevelt ( t box );
+\copy gevelt from 'data/rect.data'
+SELECT center(t) AS p INTO gevelp FROM gevelt;
+CREATE INDEX gist_idx ON gevelt USING gist ( t );
+CREATE INDEX spgist_idx ON gevelp USING spgist ( p );
+CREATE INDEX kdspgist_idx ON gevelp USING spgist ( p kd_point_ops);
+--GiST
+SELECT gist_stat('gist_idx');
+                gist_stat                
+-----------------------------------------
+ Number of levels:          2           +
+ Number of pages:           29          +
+ Number of leaf pages:      28          +
+ Number of tuples:          3406        +
+ Number of invalid tuples:  0           +
+ Number of leaf tuples:     3378        +
+ Total size of tuples:      143516 bytes+
+ Total size of leaf tuples: 142296 bytes+
+ Total size of index:       237568 bytes+
+(1 row)
+
+SELECT gist_tree('gist_idx');
+                                           gist_tree                                           
+-----------------------------------------------------------------------------------------------
+ 0(l:0) blk: 0 numTuple: 28 free: 6940b(14.95%) rightlink:4294967295 (InvalidBlockNumber)     +
+     1(l:1) blk: 2 numTuple: 278 free: 2588b(68.28%) rightlink:4294967295 (InvalidBlockNumber)+
+     2(l:1) blk: 18 numTuple: 123 free: 2736b(66.47%) rightlink:3 (OK)                        +
+     3(l:1) blk: 8 numTuple: 128 free: 2516b(69.17%) rightlink:21 (OK)                        +
+     4(l:1) blk: 4 numTuple: 92 free: 4100b(49.75%) rightlink:23 (OK)                         +
+     5(l:1) blk: 19 numTuple: 122 free: 2780b(65.93%) rightlink:7 (OK)                        +
+     6(l:1) blk: 15 numTuple: 135 free: 2208b(72.94%) rightlink:11 (OK)                       +
+     7(l:1) blk: 23 numTuple: 126 free: 2604b(68.09%) rightlink:8 (OK)                        +
+     8(l:1) blk: 10 numTuple: 156 free: 1284b(84.26%) rightlink:18 (OK)                       +
+     9(l:1) blk: 13 numTuple: 130 free: 2428b(70.25%) rightlink:19 (OK)                       +
+     10(l:1) blk: 9 numTuple: 124 free: 2692b(67.01%) rightlink:24 (OK)                       +
+     11(l:1) blk: 12 numTuple: 70 free: 5068b(37.89%) rightlink:25 (OK)                       +
+     12(l:1) blk: 21 numTuple: 112 free: 3220b(60.54%) rightlink:10 (OK)                      +
+     13(l:1) blk: 16 numTuple: 89 free: 4232b(48.14%) rightlink:26 (OK)                       +
+     14(l:1) blk: 26 numTuple: 108 free: 3396b(58.38%) rightlink:5 (OK)                       +
+     15(l:1) blk: 7 numTuple: 99 free: 3792b(53.53%) rightlink:16 (OK)                        +
+     16(l:1) blk: 6 numTuple: 85 free: 4408b(45.98%) rightlink:22 (OK)                        +
+     17(l:1) blk: 14 numTuple: 163 free: 976b(88.04%) rightlink:6 (OK)                        +
+     18(l:1) blk: 28 numTuple: 122 free: 2780b(65.93%) rightlink:12 (OK)                      +
+     19(l:1) blk: 3 numTuple: 57 free: 5640b(30.88%) rightlink:27 (OK)                        +
+     20(l:1) blk: 24 numTuple: 80 free: 4628b(43.28%) rightlink:15 (OK)                       +
+     21(l:1) blk: 17 numTuple: 89 free: 4232b(48.14%) rightlink:4 (OK)                        +
+     22(l:1) blk: 20 numTuple: 166 free: 844b(89.66%) rightlink:13 (OK)                       +
+     23(l:1) blk: 27 numTuple: 122 free: 2780b(65.93%) rightlink:14 (OK)                      +
+     24(l:1) blk: 22 numTuple: 147 free: 1680b(79.41%) rightlink:9 (OK)                       +
+     25(l:1) blk: 11 numTuple: 146 free: 1724b(78.87%) rightlink:2 (OK)                       +
+     26(l:1) blk: 5 numTuple: 61 free: 5464b(33.04%) rightlink:28 (OK)                        +
+     27(l:1) blk: 1 numTuple: 92 free: 4100b(49.75%) rightlink:20 (OK)                        +
+     28(l:1) blk: 25 numTuple: 156 free: 1284b(84.26%) rightlink:17 (OK)                      +
+(1 row)
+
+SELECT * FROM gist_print('gist_idx') as t(level int, valid bool, a box) where level=1;
+ level | valid |              a              
+-------+-------+-----------------------------
+     1 | t     | 
+     1 | t     | (32261,50040),(20397,42779)
+     1 | t     | (20400,41715),(9175,31485)
+     1 | t     | (8924,39250),(3,31083)
+     1 | t     | (20594,19151),(10869,10535)
+     1 | t     | (49999,42533),(43290,27088)
+     1 | t     | (8993,50012),(64,39781)
+     1 | t     | (32394,42395),(20513,31557)
+     1 | t     | (20715,10161),(10407,51)
+     1 | t     | (42941,36244),(32606,27088)
+     1 | t     | (32512,16364),(20947,11843)
+     1 | t     | (20327,49975),(9216,42130)
+     1 | t     | (13397,31188),(7334,19288)
+     1 | t     | (20856,31294),(13642,19263)
+     1 | t     | (6986,30859),(107,19466)
+     1 | t     | (39187,26879),(32770,15690)
+     1 | t     | (49985,15380),(42047,43)
+     1 | t     | (32715,11509),(24675,6)
+     1 | t     | (41916,5154),(32914,357)
+     1 | t     | (43056,42360),(32661,36457)
+     1 | t     | (32544,31262),(21146,25161)
+     1 | t     | (10104,18999),(15,7761)
+     1 | t     | (41835,15495),(32828,5360)
+     1 | t     | (49944,26858),(39348,15728)
+     1 | t     | (50027,50073),(32453,42694)
+     1 | t     | (24423,11473),(20828,181)
+     1 | t     | (10146,7495),(138,81)
+     1 | t     | (32705,25105),(20838,16626)
+(28 rows)
+
+--SPGiST
+SELECT spgist_stat('spgist_idx');
+           spgist_stat            
+----------------------------------
+ totalPages:        21           +
+ deletedPages:      0            +
+ innerPages:        2            +
+ leafPages:         19           +
+ emptyPages:        0            +
+ usedSpace:         126.70 kbytes+
+ freeSpace:         40.64 kbytes +
+ fillRatio:         75.71%       +
+ leafTuples:        3947         +
+ innerTuples:       20           +
+ innerAllTheSame:   0            +
+ leafPlaceholders:  569          +
+ innerPlaceholders: 0            +
+ leafRedirects:     0            +
+ innerRedirects:    0
+(1 row)
+
+SELECT * FROM spgist_print('kdspgist_idx') as t(tid tid, node_n int, level int, tid_pointer tid, prefix float8, node_label int, leaf_value point);
+   tid    | node_n | level | tid_pointer | prefix | node_label |    leaf_value     
+----------+--------+-------+-------------+--------+------------+-------------------
+ (1,1)    |      0 |     1 | (5,1)       |        |            | 
+ (1,1)    |      1 |     1 | (5,2)       |        |            | 
+ (5,2)    |      0 |     2 | (5,6)       |        |            | 
+ (5,2)    |      1 |     2 | (5,3)       |        |            | 
+ (5,3)    |      0 |     3 | (5,5)       |        |            | 
+ (5,3)    |      1 |     3 | (5,12)      |        |            | 
+ (5,12)   |      0 |     4 | (5,13)      |        |            | 
+ (5,12)   |      1 |     4 | (14,226)    |        |            | 
+ (14,226) |        |     5 |             |        |            | (43240,47256.5)
+ (5,13)   |      0 |     5 | (3,112)     |        |            | 
+ (5,13)   |      1 |     5 | (5,25)      |        |            | 
+ (5,25)   |      0 |     6 | (22,116)    |        |            | 
+ (5,25)   |      1 |     6 | (22,115)    |        |            | 
+ (22,115) |        |     7 |             |        |            | (30902,44532)
+ (22,116) |        |     7 |             |        |            | (23048,47416)
+ (3,112)  |        |     6 |             |        |            | (35218.5,42124)
+ (5,5)    |      0 |     4 | (5,11)      |        |            | 
+ (5,5)    |      1 |     4 | (5,22)      |        |            | 
+ (5,22)   |      0 |     5 | (20,225)    |        |            | 
+ (5,22)   |      1 |     5 | (5,23)      |        |            | 
+ (5,23)   |      0 |     6 | (9,112)     |        |            | 
+ (5,23)   |      1 |     6 | (9,114)     |        |            | 
+ (9,114)  |        |     7 |             |        |            | (44732,32182)
+ (9,112)  |        |     7 |             |        |            | (35580,33526.5)
+ (20,225) |        |     6 |             |        |            | (47724.5,27185.5)
+ (5,11)   |      0 |     5 | (13,101)    |        |            | 
+ (5,11)   |      1 |     5 | (13,100)    |        |            | 
+ (13,100) |        |     6 |             |        |            | (24069,30850.5)
+ (13,101) |        |     6 |             |        |            | (29539,25566)
+ (5,6)    |      0 |     3 | (5,7)       |        |            | 
+ (5,6)    |      1 |     3 | (5,19)      |        |            | 
+ (5,19)   |      0 |     4 | (5,20)      |        |            | 
+ (5,19)   |      1 |     4 | (18,225)    |        |            | 
+ (18,225) |        |     5 |             |        |            | (20920.5,49105.5)
+ (5,20)   |      0 |     5 | (10,110)    |        |            | 
+ (5,20)   |      1 |     5 | (10,113)    |        |            | 
+ (10,113) |        |     6 |             |        |            | (93,46797)
+ (10,110) |        |     6 |             |        |            | (28.5,38640.5)
+ (5,7)    |      0 |     4 | (7,113)     |        |            | 
+ (5,7)    |      1 |     4 | (5,21)      |        |            | 
+ (5,21)   |      0 |     5 | (19,115)    |        |            | 
+ (5,21)   |      1 |     5 | (19,112)    |        |            | 
+ (19,112) |        |     6 |             |        |            | (11916.5,31668)
+ (19,115) |        |     6 |             |        |            | (20622.5,27462.5)
+ (7,113)  |        |     5 |             |        |            | (9296,35157)
+ (5,1)    |      0 |     2 | (5,8)       |        |            | 
+ (5,1)    |      1 |     2 | (5,4)       |        |            | 
+ (5,4)    |      0 |     3 | (5,10)      |        |            | 
+ (5,4)    |      1 |     3 | (5,14)      |        |            | 
+ (5,14)   |      0 |     4 | (5,15)      |        |            | 
+ (5,14)   |      1 |     4 | (15,222)    |        |            | 
+ (15,222) |        |     5 |             |        |            | (41926.5,17934.5)
+ (5,15)   |      0 |     5 | (8,113)     |        |            | 
+ (5,15)   |      1 |     5 | (8,112)     |        |            | 
+ (8,112)  |        |     6 |             |        |            | (32425,20702.5)
+ (8,113)  |        |     6 |             |        |            | (29134,15559.5)
+ (5,10)   |      0 |     4 | (12,94)     |        |            | 
+ (5,10)   |      1 |     4 | (5,24)      |        |            | 
+ (5,24)   |      0 |     5 | (21,108)    |        |            | 
+ (5,24)   |      1 |     5 | (21,107)    |        |            | 
+ (21,107) |        |     6 |             |        |            | (49822.5,7097.5)
+ (21,108) |        |     6 |             |        |            | (40315.5,1689.5)
+ (12,94)  |        |     5 |             |        |            | (30295.5,5090)
+ (5,8)    |      0 |     3 | (5,17)      |        |            | 
+ (5,8)    |      1 |     3 | (5,9)       |        |            | 
+ (5,9)    |      0 |     4 | (6,114)     |        |            | 
+ (5,9)    |      1 |     4 | (5,16)      |        |            | 
+ (5,16)   |      0 |     5 | (16,123)    |        |            | 
+ (5,16)   |      1 |     5 | (16,127)    |        |            | 
+ (16,127) |        |     6 |             |        |            | (18352.5,19366)
+ (16,123) |        |     6 |             |        |            | (24795,14921)
+ (6,114)  |        |     5 |             |        |            | (6706,16676)
+ (5,17)   |      0 |     4 | (5,18)      |        |            | 
+ (5,17)   |      1 |     4 | (17,226)    |        |            | 
+ (17,226) |        |     5 |             |        |            | (23690,10214.5)
+ (5,18)   |      0 |     5 | (11,113)    |        |            | 
+ (5,18)   |      1 |     5 | (11,109)    |        |            | 
+ (11,109) |        |     6 |             |        |            | (5501.5,9916)
+ (11,113) |        |     6 |             |        |            | (1072.5,4752)
+(79 rows)
+
+SELECT * FROM spgist_print('spgist_idx') as t(tid tid, node_n int, level int, tid_pointer tid, prefix point, node_label int, leaf_value point) WHERE level = 1;
+  tid  | node_n | level | tid_pointer |               prefix                | node_label | leaf_value 
+-------+--------+-------+-------------+-------------------------------------+------------+------------
+ (1,1) |      0 |     1 | (5,4)       | (24530.2070484581,23595.7092511013) |            | 
+ (1,1) |      1 |     1 | (5,3)       | (24530.2070484581,23595.7092511013) |            | 
+ (1,1) |      2 |     1 | (5,2)       | (24530.2070484581,23595.7092511013) |            | 
+ (1,1) |      3 |     1 | (5,1)       | (24530.2070484581,23595.7092511013) |            | 
+(4 rows)
+
+--GIN 
+CREATE TABLE test__int( a int[] );
+\copy test__int from 'data/test__int.data'
+CREATE INDEX gin_idx ON test__int USING gin ( a );
+INSERT INTO test__int ( SELECT ARRAY[t] || '{1000}'::_int4 FROM generate_series (1,300) as t );
+INSERT INTO test__int ( SELECT ARRAY[t] || '{1001}'::_int4 FROM generate_series (1,300) as t, generate_series(1,12) );
+VACUUM ANALYZE test__int; 
+SELECT * FROM gin_stat('gin_idx') as t(value int, nrow int);
+ value | nrow 
+-------+------
+     0 |   38
+     1 |  257
+     2 |  244
+     3 |  222
+     4 |  228
+     5 |  227
+     6 |  243
+     7 |  238
+     8 |  236
+     9 |  224
+    10 |  236
+    11 |  248
+    12 |  224
+    13 |  235
+    14 |  237
+    15 |  253
+    16 |  234
+    17 |  245
+    18 |  246
+    19 |  234
+    20 |  236
+    21 |  213
+    22 |  235
+    23 |  222
+    24 |  197
+    25 |  253
+    26 |  218
+    27 |  239
+    28 |  198
+    29 |  244
+    30 |  247
+    31 |  267
+    32 |  234
+    33 |  209
+    34 |  231
+    35 |  218
+    36 |  242
+    37 |  232
+    38 |  221
+    39 |  232
+    40 |  241
+    41 |  239
+    42 |  221
+    43 |  211
+    44 |  231
+    45 |  213
+    46 |  236
+    47 |  264
+    48 |  221
+    49 |  235
+    50 |  219
+    51 |  250
+    52 |  270
+    53 |  222
+    54 |  242
+    55 |  237
+    56 |  237
+    57 |  251
+    58 |  231
+    59 |  272
+    60 |  219
+    61 |  233
+    62 |  235
+    63 |  260
+    64 |  252
+    65 |  221
+    66 |  228
+    67 |  253
+    68 |  196
+    69 |  232
+    70 |  232
+    71 |  223
+    72 |  247
+    73 |  214
+    74 |  232
+    75 |  229
+    76 |  233
+    77 |  221
+    78 |  227
+    79 |  233
+    80 |  216
+    81 |  244
+    82 |  223
+    83 |  254
+    84 |  227
+    85 |  247
+    86 |  255
+    87 |  239
+    88 |  258
+    89 |  249
+    90 |  244
+    91 |  226
+    92 |  225
+    93 |  230
+    94 |  218
+    95 |  232
+    96 |  239
+    97 |  226
+    98 |  209
+    99 |  211
+   100 |  216
+   101 |   49
+   102 |   47
+   103 |   59
+   104 |   55
+   105 |   48
+   106 |   49
+   107 |   49
+   108 |   51
+   109 |   47
+   110 |   51
+   111 |   45
+   112 |   46
+   113 |   48
+   114 |   38
+   115 |   39
+   116 |   43
+   117 |   44
+   118 |   46
+   119 |   45
+   120 |   52
+   121 |   41
+   122 |   64
+   123 |   50
+   124 |   41
+   125 |   55
+   126 |   41
+   127 |   50
+   128 |   54
+   129 |   43
+   130 |   44
+   131 |   50
+   132 |   57
+   133 |   40
+   134 |   41
+   135 |   44
+   136 |   58
+   137 |   48
+   138 |   44
+   139 |   50
+   140 |   49
+   141 |   48
+   142 |   43
+   143 |   36
+   144 |   43
+   145 |   49
+   146 |   46
+   147 |   40
+   148 |   52
+   149 |   46
+   150 |   49
+   151 |   42
+   152 |   58
+   153 |   49
+   154 |   51
+   155 |   49
+   156 |   45
+   157 |   53
+   158 |   59
+   159 |   38
+   160 |   53
+   161 |   48
+   162 |   41
+   163 |   40
+   164 |   52
+   165 |   50
+   166 |   40
+   167 |   48
+   168 |   45
+   169 |   49
+   170 |   50
+   171 |   45
+   172 |   46
+   173 |   47
+   174 |   41
+   175 |   51
+   176 |   50
+   177 |   41
+   178 |   42
+   179 |   48
+   180 |   47
+   181 |   49
+   182 |   40
+   183 |   46
+   184 |   52
+   185 |   36
+   186 |   45
+   187 |   41
+   188 |   47
+   189 |   49
+   190 |   46
+   191 |   45
+   192 |   39
+   193 |   50
+   194 |   39
+   195 |   54
+   196 |   43
+   197 |   50
+   198 |   46
+   199 |   42
+   200 |   31
+   201 |   28
+   202 |   28
+   203 |   28
+   204 |   30
+   205 |   22
+   206 |   25
+   207 |   27
+   208 |   32
+   209 |   22
+   210 |   21
+   211 |   31
+   212 |   22
+   213 |   37
+   214 |   19
+   215 |   25
+   216 |   27
+   217 |   26
+   218 |   24
+   219 |   25
+   220 |   26
+   221 |   21
+   222 |   23
+   223 |   20
+   224 |   26
+   225 |   25
+   226 |   25
+   227 |   23
+   228 |   30
+   229 |   30
+   230 |   24
+   231 |   22
+   232 |   27
+   233 |   27
+   234 |   21
+   235 |   27
+   236 |   24
+   237 |   24
+   238 |   29
+   239 |   32
+   240 |   31
+   241 |   24
+   242 |   36
+   243 |   21
+   244 |   29
+   245 |   22
+   246 |   23
+   247 |   21
+   248 |   26
+   249 |   29
+   250 |   24
+   251 |   29
+   252 |   25
+   253 |   28
+   254 |   25
+   255 |   19
+   256 |   23
+   257 |   20
+   258 |   24
+   259 |   31
+   260 |   29
+   261 |   20
+   262 |   25
+   263 |   23
+   264 |   25
+   265 |   23
+   266 |   31
+   267 |   22
+   268 |   26
+   269 |   33
+   270 |   25
+   271 |   27
+   272 |   29
+   273 |   29
+   274 |   26
+   275 |   28
+   276 |   30
+   277 |   28
+   278 |   29
+   279 |   22
+   280 |   29
+   281 |   23
+   282 |   30
+   283 |   29
+   284 |   23
+   285 |   37
+   286 |   27
+   287 |   31
+   288 |   28
+   289 |   26
+   290 |   25
+   291 |   29
+   292 |   22
+   293 |   26
+   294 |   29
+   295 |   24
+   296 |   27
+   297 |   30
+   298 |   29
+   299 |   26
+   300 |   13
+  1000 |  300
+  1001 |    0
+       |    9
+       |  244
+(305 rows)
+
diff --git a/gevel.c b/gevel.c
index d95fbdf..b4e66f4 100644 (file)
--- a/gevel.c
+++ b/gevel.c
@@ -695,8 +695,11 @@ processTuple( FuncCallContext  *funcctx,  GinStatState *st, IndexTuple itup ) {
        if ( GinIsPostingTree(itup) ) {
                BlockNumber     rootblkno = GinGetPostingTree(itup);
 #if PG_VERSION_NUM >= 90400
-               GinBtreeData    btree, *gdi = &btree;
+               GinBtreeData    btree;
                GinBtreeStack   *stack;
+               ItemPointerData minItem;
+               int                             nlist;
+               ItemPointer             list;
 #else
                GinPostingTreeScan *gdi;
                Buffer          entrybuffer;              
@@ -706,9 +709,11 @@ processTuple( FuncCallContext  *funcctx,  GinStatState *st, IndexTuple itup ) {
 
                LockBuffer(st->buffer, GIN_UNLOCK);
 #if PG_VERSION_NUM >= 90400
-               ginPrepareDataScan(gdi, st->index, rootblkno);
-               stack = ginScanBeginPostingTree(gdi, st->index, rootblkno);
+               stack = ginScanBeginPostingTree(&btree, st->index, rootblkno);
                page = BufferGetPage(stack->buffer);
+               ItemPointerSetMin(&minItem);
+               list = GinDataLeafPageGetItems(page, &nlist, minItem);
+               pfree(list);
                predictNumber = stack->predictNumber;
 #elif PG_VERSION_NUM >= 90100
                gdi = ginPrepareScanPostingTree(st->index, rootblkno, TRUE);
@@ -729,6 +734,7 @@ processTuple( FuncCallContext  *funcctx,  GinStatState *st, IndexTuple itup ) {
                freeGinBtreeStack(gdi->stack);
                pfree(gdi);
 #else
+               LockBuffer(stack->buffer, GIN_UNLOCK);
                freeGinBtreeStack(stack);
 #endif
        } else {
@@ -830,7 +836,7 @@ gin_count_estimate(PG_FUNCTION_ARGS) {
 
 #if PG_VERSION_NUM >= 90100
 #if PG_VERSION_NUM >= 90400
-       scan = index_beginscan_bitmap(index, GetTransactionSnapshot(), 1);
+       scan = index_beginscan_bitmap(index, SnapshotSelf, 1);
 #else
        scan = index_beginscan_bitmap(index, SnapshotNow, 1);
 #endif
@@ -1227,3 +1233,172 @@ next:
 #endif
 }
 
+
+PG_FUNCTION_INFO_V1(gin_statpage);
+Datum gin_statpage(PG_FUNCTION_ARGS);
+Datum
+gin_statpage(PG_FUNCTION_ARGS)
+{
+#if PG_VERSION_NUM < 90400
+       elog(NOTICE, "Function is not working under PgSQL < 9.4");
+
+       PG_RETURN_TEXT_P(CStringGetTextDatum("???"));
+#else
+       text       *name = PG_GETARG_TEXT_P(0);
+       RangeVar   *relvar;
+       Relation        index;
+       BlockNumber blkno;
+       char            res[1024];
+       uint32          totalPages,
+                               entryPages = 0,
+                               dataPages = 0,
+                               dataInnerPages = 0,
+                               dataLeafPages = 0,
+                               entryInnerPages = 0,
+                               entryLeafPages = 0
+                               ;
+       uint64          dataInnerFreeSpace = 0,
+                               dataLeafFreeSpace = 0,
+                               dataInnerTuplesCount = 0,
+                               dataLeafIptrsCount = 0,
+                               entryInnerFreeSpace = 0,
+                               entryLeafFreeSpace = 0,
+                               entryInnerTuplesCount = 0,
+                               entryLeafTuplesCount = 0,
+                               entryPostingSize = 0,
+                               entryPostingCount = 0,
+                               entryAttrSize = 0
+                               ;
+
+       relvar = makeRangeVarFromNameList(textToQualifiedNameList(name));
+       index = relation_openrv(relvar, AccessExclusiveLock);
+
+       if (index->rd_rel->relkind != RELKIND_INDEX ||
+                       index->rd_rel->relam != GIN_AM_OID)
+               elog(ERROR, "relation \"%s\" is not an SPGiST index",
+                        RelationGetRelationName(index));
+
+       totalPages = RelationGetNumberOfBlocks(index);
+
+       for (blkno = GIN_ROOT_BLKNO; blkno < totalPages; blkno++)
+       {
+               Buffer          buffer;
+               Page            page;
+               PageHeader      header;
+
+               buffer = ReadBuffer(index, blkno);
+               LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+               page = BufferGetPage(buffer);
+               header = (PageHeader)page;
+
+               if (GinPageIsData(page))
+               {
+                       dataPages++;
+                       if (GinPageIsLeaf(page))
+                       {
+                               ItemPointerData minItem;
+                               int nlist;
+
+                               dataLeafPages++;
+                               dataLeafFreeSpace += header->pd_upper - header->pd_lower;
+                               ItemPointerSetMin(&minItem);
+                               pfree(GinDataLeafPageGetItems(page, &nlist, minItem));
+                               dataLeafIptrsCount += nlist;
+                       }
+                       else
+                       {
+                               dataInnerPages++;
+                               dataInnerFreeSpace += header->pd_upper - header->pd_lower;
+                               dataInnerTuplesCount += GinPageGetOpaque(page)->maxoff;
+                       }
+               }
+               else
+               {
+                       IndexTuple itup;
+                       OffsetNumber i, maxoff;
+
+                       maxoff = PageGetMaxOffsetNumber(page);
+
+                       entryPages++;
+                       if (GinPageIsLeaf(page))
+                       {
+                               entryLeafPages++;
+                               entryLeafFreeSpace += header->pd_upper - header->pd_lower;
+                               entryLeafTuplesCount += maxoff;
+                       }
+                       else
+                       {
+                               entryInnerPages++;
+                               entryInnerFreeSpace += header->pd_upper - header->pd_lower;
+                               entryInnerTuplesCount += maxoff;
+                       }
+
+                       for (i = 1; i <= maxoff; i++)
+                       {
+                               itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, i));
+
+                               if (GinPageIsLeaf(page))
+                               {
+                                       GinPostingList *list = (GinPostingList *)GinGetPosting(itup);
+                                       entryPostingCount += GinGetNPosting(itup);
+                                       entryPostingSize += SizeOfGinPostingList(list);
+                                       entryAttrSize += GinGetPostingOffset(itup) - IndexInfoFindDataOffset((itup)->t_info);
+                               }
+                               else
+                               {
+                                       entryAttrSize += IndexTupleSize(itup) - IndexInfoFindDataOffset((itup)->t_info);
+                               }
+                       }
+               }
+
+               UnlockReleaseBuffer(buffer);
+       }
+
+       index_close(index, AccessExclusiveLock);
+       totalPages--;
+
+       snprintf(res, sizeof(res),
+                        "totalPages:            %u\n"
+                        "dataPages:             %u\n"
+                        "dataInnerPages:        %u\n"
+                        "dataLeafPages:         %u\n"
+                        "dataInnerFreeSpace:    " INT64_FORMAT "\n"
+                        "dataLeafFreeSpace:     " INT64_FORMAT "\n"
+                        "dataInnerTuplesCount:  " INT64_FORMAT "\n"
+                        "dataLeafIptrsCount:    " INT64_FORMAT "\n"
+                        "entryPages:            %u\n"
+                        "entryInnerPages:       %u\n"
+                        "entryLeafPages:        %u\n"
+                        "entryInnerFreeSpace:   " INT64_FORMAT "\n"
+                        "entryLeafFreeSpace:    " INT64_FORMAT "\n"
+                        "entryInnerTuplesCount: " INT64_FORMAT "\n"
+                        "entryLeafTuplesCount:  " INT64_FORMAT "\n"
+                        "entryPostingSize:      " INT64_FORMAT "\n"
+                        "entryPostingCount:     " INT64_FORMAT "\n"
+                        "entryAttrSize:         " INT64_FORMAT "\n"
+                        ,
+                        totalPages,
+                        dataPages,
+                        dataInnerPages,
+                        dataLeafPages,
+                        dataInnerFreeSpace,
+                        dataLeafFreeSpace,
+                        dataInnerTuplesCount,
+                        dataLeafIptrsCount,
+                        entryPages,
+                        entryInnerPages,
+                        entryLeafPages,
+                        entryInnerFreeSpace,
+                        entryLeafFreeSpace,
+                        entryInnerTuplesCount,
+                        entryLeafTuplesCount,
+                        entryPostingSize,
+                        entryPostingCount,
+                        entryAttrSize
+                        );
+
+       PG_RETURN_TEXT_P(CStringGetTextDatum(res));
+#endif
+}
+
index 1f031ed..a2310bf 100644 (file)
@@ -37,6 +37,12 @@ create or replace function gin_stat(text, int)
         language C
         with (isstrict); 
 
+create or replace function gin_statpage(text)
+        returns text
+        as 'MODULE_PATHNAME'
+        language C
+        with (isstrict); 
+
 create or replace function gin_count_estimate(text, tsquery)
         returns bigint 
         as 'MODULE_PATHNAME'