Patch for pgstatindex to fix a bug reporting a value of strange leaf_fragmentation

From: Tatsuhito Kasahara <kasahara(dot)tatsuhito(at)oss(dot)ntt(dot)co(dot)jp>
To: pgsql-patches(at)postgresql(dot)org
Cc: "kasahara(OSSC)" <kasahara(dot)tatsuhito(at)oss(dot)ntt(dot)co(dot)jp>
Subject: Patch for pgstatindex to fix a bug reporting a value of strange leaf_fragmentation
Date: 2007-03-08 03:26:43
Message-ID: 45EF8273.40404@oss.ntt.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-patches

Hello.

I found a bug in contrib/pgstatindex.c to reports a strange value of
leaf_fragmentation with some cases.
#Look the following test example.

In GetBTPageStatistics(), stat->fragments is not initialized properly
so that invalid leaf_fragments values are inserted in results.
For example, GetBTPageStatistics() read a dead_leaf_block
(stat->type = 'd';) first, stat->fragments hold a strange value because
stat->fragments is not initialized before "return true"(pgstatindex.c
164th line)
And then, the strange value is just inserted in result. Under normal
circumstances, stat.fragments must be incremented only when stat->type
is 'l'.
So pgstatindex reports strange leaf_fragmentation.

I made the patch.
Please confirm this.

Best regards.

======== Test (postgresql8.2.1)========
test=# CREATE TABLE test (id int);
CREATE TABLE

test=# INSERT INTO test select generate_series(1,1000);
INSERT 0 1000

test=# CREATE INDEX idx_test ON test(id);
CREATE INDEX

test=# SELECT leaf_fragmentation from pgstatindex('idx_test');
-[ RECORD 1 ]------+--
leaf_fragmentation | 0

test=# DELETE FROM test;
DELETE 1000

test=# SELECT leaf_fragmentation from pgstatindex('idx_test');
-[ RECORD 1 ]------+--
leaf_fragmentation | 0

test=# VACUUM test;
VACUUM

test=# SELECT leaf_fragmentation from pgstatindex('idx_test');
-[ RECORD 1 ]------+------------
leaf_fragmentation | 28943878400 <- Invalid value
======== Test (postgresql8.2.1)========

=========gdb============
(gdb) b GetBTPageStatistics
Breakpoint 4 at 0xfd8126: file pgstatindex.c, line 145.
(gdb) c
Continuing.

Breakpoint 4, GetBTPageStatistics (blkno=1, buffer=101, stat=0xbfc3fbe4)
at pgstatindex.c:145
145 Page page = BufferGetPage(buffer);
(gdb) print stat.fragments
$4 = 144719392 <- Already have a invalid value.

(snip)

Breakpoint 3, GetBTPageStatistics (blkno=1, buffer=<value optimized out>,
stat=0xbfc3fbe4) at pgstatindex.c:161
161 if (P_ISDELETED(opaque))
(gdb) n
163 stat->type = 'd';

(snip)

pgstatindex (fcinfo=0xbfc3fc70) at pgstatindex.c:297
297 switch (stat.type)
(gdb) n
300 indexStat.deleted_pages++;
(gdb) n
319 indexStat.fragments += stat.fragments;
(gdb) print stat.fragments
$3 = 144719392 <- Just inserts inavlid value in result even if stat.type is 'dead'.
=========gdb============

=========patch test============
test=# CREATE TABLE test2 (id int);
CREATE TABLE
test=# INSERT INTO test2 select generate_series(1,1000);
INSERT 0 1000
test=# CREATE INDEX idx_test2 ON test2(id);
CREATE INDEX
test=# DELETE FROM test2;
DELETE 1000
test=# VACUUM test2;
VACUUM
test=# SELECT leaf_fragmentation from pgstatindex('idx_test2');
-[ RECORD 1 ]------+--
leaf_fragmentation | 0 <- OK

test=# INSERT INTO test2 select generate_series(1,1000);
INSERT 0 1000
test=# SELECT leaf_fragmentation from pgstatindex('idx_test2');
-[ RECORD 1 ]------+--
leaf_fragmentation | 0 <- OK

test=# INSERT INTO test2 select generate_series(1,1000);
INSERT 0 1000
test=# SELECT leaf_fragmentation from pgstatindex('idx_test2');
-[ RECORD 1 ]------+------
leaf_fragmentation | 28.57 <- OK.
=========patch test============

--
NTT OSS Center
Tatsuhito Kasahara

kasahara.tatsuhito _at_ oss.ntt.co.jp

Attachment Content-Type Size
pgstatindex.c.patch text/plain 626 bytes

Responses

Browse pgsql-patches by date

  From Date Subject
Next Message Luke Lonergan 2007-03-08 03:32:14 Re: Auto creation of Partitions
Previous Message Joris Dobbelsteen 2007-03-07 20:13:40 Re: Auto creation of Partitions