33 * pg_freespacemap.c
44 * display some contents of the free space map.
55 *
6- * $PostgreSQL: pgsql/contrib/pg_freespacemap/pg_freespacemap.c,v 1.2 2006/02/14 15:03:59 tgl Exp $
6+ * $PostgreSQL: pgsql/contrib/pg_freespacemap/pg_freespacemap.c,v 1.3 2006/04/26 22:41:18 momjian Exp $
77 *-------------------------------------------------------------------------
88 */
99#include "postgres.h"
1212#include "storage/freespace.h"
1313#include "utils/relcache.h"
1414
15- #define NUM_FREESPACE_PAGES_ELEM 6
15+ #define NUM_FREESPACE_PAGES_ELEM 5
1616
1717#if defined(WIN32 )|| defined(__CYGWIN__ )
1818/* Need DLLIMPORT for some things that are not so marked in main headers */
@@ -29,12 +29,12 @@ Datumpg_freespacemap(PG_FUNCTION_ARGS);
2929typedef struct
3030{
3131
32- uint32 blockid ;
33- uint32 relfilenode ;
3432uint32 reltablespace ;
3533uint32 reldatabase ;
34+ uint32 relfilenode ;
3635uint32 relblocknumber ;
37- uint32 blockfreebytes ;
36+ uint32 bytes ;
37+ bool isindex ;
3838
3939}FreeSpacePagesRec ;
4040
@@ -91,17 +91,15 @@ pg_freespacemap(PG_FUNCTION_ARGS)
9191
9292/* Construct a tuple to return. */
9393tupledesc = CreateTemplateTupleDesc (NUM_FREESPACE_PAGES_ELEM , false);
94- TupleDescInitEntry (tupledesc , (AttrNumber )1 ,"blockid" ,
95- INT4OID ,-1 ,0 );
96- TupleDescInitEntry (tupledesc , (AttrNumber )2 ,"relfilenode" ,
94+ TupleDescInitEntry (tupledesc , (AttrNumber )1 ,"reltablespace" ,
9795OIDOID ,-1 ,0 );
98- TupleDescInitEntry (tupledesc , (AttrNumber )3 ,"reltablespace " ,
96+ TupleDescInitEntry (tupledesc , (AttrNumber )2 ,"reldatabase " ,
9997OIDOID ,-1 ,0 );
100- TupleDescInitEntry (tupledesc , (AttrNumber )4 ,"reldatabase " ,
98+ TupleDescInitEntry (tupledesc , (AttrNumber )3 ,"relfilenode " ,
10199OIDOID ,-1 ,0 );
102- TupleDescInitEntry (tupledesc , (AttrNumber )5 ,"relblocknumber" ,
100+ TupleDescInitEntry (tupledesc , (AttrNumber )4 ,"relblocknumber" ,
103101INT8OID ,-1 ,0 );
104- TupleDescInitEntry (tupledesc , (AttrNumber )6 ,"blockfreebytes " ,
102+ TupleDescInitEntry (tupledesc , (AttrNumber )5 ,"bytes " ,
105103INT4OID ,-1 ,0 );
106104
107105/* Generate attribute metadata needed later to produce tuples */
@@ -129,7 +127,6 @@ pg_freespacemap(PG_FUNCTION_ARGS)
129127fctx -> values [2 ]= (char * )palloc (3 * sizeof (uint32 )+ 1 );
130128fctx -> values [3 ]= (char * )palloc (3 * sizeof (uint32 )+ 1 );
131129fctx -> values [4 ]= (char * )palloc (3 * sizeof (uint32 )+ 1 );
132- fctx -> values [5 ]= (char * )palloc (3 * sizeof (uint32 )+ 1 );
133130
134131
135132/* Return to original context when allocating transient memory */
@@ -158,12 +155,12 @@ pg_freespacemap(PG_FUNCTION_ARGS)
158155for (nPages = 0 ;nPages < fsmrel -> storedPages ;nPages ++ )
159156{
160157
161- fctx -> record [i ].blockid = i ;
162- fctx -> record [i ].relfilenode = fsmrel -> key .relNode ;
163158fctx -> record [i ].reltablespace = fsmrel -> key .spcNode ;
164159fctx -> record [i ].reldatabase = fsmrel -> key .dbNode ;
160+ fctx -> record [i ].relfilenode = fsmrel -> key .relNode ;
165161fctx -> record [i ].relblocknumber = IndexFSMPageGetPageNum (page );
166- fctx -> record [i ].blockfreebytes = 0 ;/* index.*/
162+ fctx -> record [i ].bytes = 0 ;
163+ fctx -> record [i ].isindex = true;
167164
168165page ++ ;
169166i ++ ;
@@ -178,12 +175,12 @@ pg_freespacemap(PG_FUNCTION_ARGS)
178175
179176for (nPages = 0 ;nPages < fsmrel -> storedPages ;nPages ++ )
180177{
181- fctx -> record [i ].blockid = i ;
182- fctx -> record [i ].relfilenode = fsmrel -> key .relNode ;
183178fctx -> record [i ].reltablespace = fsmrel -> key .spcNode ;
184179fctx -> record [i ].reldatabase = fsmrel -> key .dbNode ;
180+ fctx -> record [i ].relfilenode = fsmrel -> key .relNode ;
185181fctx -> record [i ].relblocknumber = FSMPageGetPageNum (page );
186- fctx -> record [i ].blockfreebytes = FSMPageGetSpace (page );
182+ fctx -> record [i ].bytes = FSMPageGetSpace (page );
183+ fctx -> record [i ].isindex = false;
187184
188185page ++ ;
189186i ++ ;
@@ -209,19 +206,41 @@ pg_freespacemap(PG_FUNCTION_ARGS)
209206if (funcctx -> call_cntr < funcctx -> max_calls )
210207{
211208uint32 i = funcctx -> call_cntr ;
209+ char * values [NUM_FREESPACE_PAGES_ELEM ];
210+ int j ;
212211
212+ /*
213+ * Use a temporary values array, initially pointing to fctx->values,
214+ * so it can be reassigned w/o losing the storage for subsequent
215+ * calls.
216+ */
217+ for (j = 0 ;j < NUM_FREESPACE_PAGES_ELEM ;j ++ )
218+ {
219+ values [j ]= fctx -> values [j ];
220+ }
221+
222+
223+ sprintf (values [0 ],"%u" ,fctx -> record [i ].reltablespace );
224+ sprintf (values [1 ],"%u" ,fctx -> record [i ].reldatabase );
225+ sprintf (values [2 ],"%u" ,fctx -> record [i ].relfilenode );
226+ sprintf (values [3 ],"%u" ,fctx -> record [i ].relblocknumber );
213227
214- sprintf (fctx -> values [0 ],"%u" ,fctx -> record [i ].blockid );
215- sprintf (fctx -> values [1 ],"%u" ,fctx -> record [i ].relfilenode );
216- sprintf (fctx -> values [2 ],"%u" ,fctx -> record [i ].reltablespace );
217- sprintf (fctx -> values [3 ],"%u" ,fctx -> record [i ].reldatabase );
218- sprintf (fctx -> values [4 ],"%u" ,fctx -> record [i ].relblocknumber );
219- sprintf (fctx -> values [5 ],"%u" ,fctx -> record [i ].blockfreebytes );
220228
229+ /*
230+ * Set (free) bytes to NULL for an index relation.
231+ */
232+ if (fctx -> record [i ].isindex == true)
233+ {
234+ values [4 ]= NULL ;
235+ }
236+ else
237+ {
238+ sprintf (values [4 ],"%u" ,fctx -> record [i ].bytes );
239+ }
221240
222241
223242/* Build and return the tuple. */
224- tuple = BuildTupleFromCStrings (funcctx -> attinmeta ,fctx -> values );
243+ tuple = BuildTupleFromCStrings (funcctx -> attinmeta ,values );
225244result = HeapTupleGetDatum (tuple );
226245
227246