Index: pgstattuple.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/contrib/pgstattuple/pgstattuple.c,v retrieving revision 1.19 diff -c -r1.19 pgstattuple.c *** pgstattuple.c 30 May 2005 23:09:06 -0000 1.19 --- pgstattuple.c 28 Jul 2005 14:48:44 -0000 *************** *** 52,58 **** */ #define NCOLUMNS 9 - #define NCHARS 32 Datum pgstattuple(PG_FUNCTION_ARGS) --- 52,57 ---- *************** *** 105,117 **** uint64 dead_tuple_len = 0; uint64 tuple_count = 0; uint64 dead_tuple_count = 0; ! double tuple_percent; ! double dead_tuple_percent; uint64 free_space = 0; /* free/reusable space in bytes */ ! double free_percent; /* free/reusable space in % */ TupleDesc tupdesc; ! AttInMetadata *attinmeta; ! char **values; int i; Datum result; --- 104,116 ---- uint64 dead_tuple_len = 0; uint64 tuple_count = 0; uint64 dead_tuple_count = 0; ! float8 tuple_percent; ! float8 dead_tuple_percent; uint64 free_space = 0; /* free/reusable space in bytes */ ! float8 free_percent; /* free/reusable space in % */ TupleDesc tupdesc; ! Datum *values; ! bool *nulls; int i; Datum result; *************** *** 122,133 **** /* make sure we have a persistent copy of the tupdesc */ tupdesc = CreateTupleDescCopy(tupdesc); - /* - * Generate attribute metadata needed later to produce tuples from raw - * C strings - */ - attinmeta = TupleDescGetAttInMetadata(tupdesc); - scan = heap_beginscan(rel, SnapshotAny, 0, NULL); nblocks = scan->rs_nblocks; /* # blocks to be scanned */ --- 121,126 ---- *************** *** 191,230 **** } else { ! tuple_percent = (double) tuple_len *100.0 / table_len; ! dead_tuple_percent = (double) dead_tuple_len *100.0 / table_len; ! free_percent = (double) free_space *100.0 / table_len; } /* ! * Prepare a values array for constructing the tuple. This should be ! * an array of C strings which will be processed later by the ! * appropriate "in" functions. */ ! values = (char **) palloc(NCOLUMNS * sizeof(char *)); ! for (i = 0; i < NCOLUMNS; i++) ! values[i] = (char *) palloc(NCHARS * sizeof(char)); i = 0; ! snprintf(values[i++], NCHARS, INT64_FORMAT, table_len); ! snprintf(values[i++], NCHARS, INT64_FORMAT, tuple_count); ! snprintf(values[i++], NCHARS, INT64_FORMAT, tuple_len); ! snprintf(values[i++], NCHARS, "%.2f", tuple_percent); ! snprintf(values[i++], NCHARS, INT64_FORMAT, dead_tuple_count); ! snprintf(values[i++], NCHARS, INT64_FORMAT, dead_tuple_len); ! snprintf(values[i++], NCHARS, "%.2f", dead_tuple_percent); ! snprintf(values[i++], NCHARS, INT64_FORMAT, free_space); ! snprintf(values[i++], NCHARS, "%.2f", free_percent); /* build a tuple */ ! tuple = BuildTupleFromCStrings(attinmeta, values); /* make the tuple into a datum */ result = HeapTupleGetDatum(tuple); /* Clean up */ - for (i = 0; i < NCOLUMNS; i++) - pfree(values[i]); pfree(values); ! return (result); } --- 184,220 ---- } else { ! tuple_percent = (float8) tuple_len *100.0 / table_len; ! dead_tuple_percent = (float8) dead_tuple_len *100.0 / table_len; ! free_percent = (float8) free_space *100.0 / table_len; } /* ! * Prepare a values array for constructing the tuple. */ ! values = (Datum *) palloc(NCOLUMNS * sizeof(Datum)); ! nulls = (bool *) palloc0(NCOLUMNS * sizeof(bool)); i = 0; ! ! values[i++] = Int64GetDatum(table_len); ! values[i++] = Int64GetDatum(tuple_count); ! values[i++] = Int64GetDatum(tuple_len); ! values[i++] = Float8GetDatum(tuple_percent); ! values[i++] = Int64GetDatum(dead_tuple_count); ! values[i++] = Int64GetDatum(dead_tuple_len); ! values[i++] = Float8GetDatum(dead_tuple_percent); ! values[i++] = Int64GetDatum(free_space); ! values[i++] = Float8GetDatum(free_percent); /* build a tuple */ ! tuple = heap_form_tuple(tupdesc, values, nulls); /* make the tuple into a datum */ result = HeapTupleGetDatum(tuple); /* Clean up */ pfree(values); + pfree(nulls); ! return result; } Index: pgstattuple.sql.in =================================================================== RCS file: /home/alvherre/cvs/pgsql/contrib/pgstattuple/pgstattuple.sql.in,v retrieving revision 1.9 diff -c -r1.9 pgstattuple.sql.in *** pgstattuple.sql.in 1 Oct 2004 15:43:40 -0000 1.9 --- pgstattuple.sql.in 28 Jul 2005 14:45:50 -0000 *************** *** 1,24 **** -- Adjust this setting to control where the objects get created. SET search_path = public; ! CREATE TYPE pgstattuple_type AS ( ! table_len BIGINT, -- physical table length in bytes ! tuple_count BIGINT, -- number of live tuples ! tuple_len BIGINT, -- total tuples length in bytes ! tuple_percent FLOAT, -- live tuples in % ! dead_tuple_count BIGINT, -- number of dead tuples ! dead_tuple_len BIGINT, -- total dead tuples length in bytes ! dead_tuple_percent FLOAT, -- dead tuples in % ! free_space BIGINT, -- free space in bytes ! free_percent FLOAT -- free space in % ! ); ! ! CREATE OR REPLACE FUNCTION pgstattuple(text) ! RETURNS pgstattuple_type AS 'MODULE_PATHNAME', 'pgstattuple' LANGUAGE 'C' STRICT; ! CREATE OR REPLACE FUNCTION pgstattuple(oid) ! RETURNS pgstattuple_type AS 'MODULE_PATHNAME', 'pgstattuplebyid' LANGUAGE 'C' STRICT; --- 1,32 ---- -- Adjust this setting to control where the objects get created. SET search_path = public; ! CREATE OR REPLACE FUNCTION pgstattuple ( ! IN table_name TEXT, ! OUT table_len BIGINT, ! OUT tuple_count BIGINT, ! OUT tuple_len BIGINT, ! OUT tuple_percent FLOAT8, ! OUT dead_tuple_count BIGINT, ! OUT dead_tuple_len BIGINT, ! OUT dead_tuple_percent FLOAT8, ! OUT free_space BIGINT, ! OUT free_percent FLOAT8 ! ) RETURNS RECORD AS 'MODULE_PATHNAME', 'pgstattuple' LANGUAGE 'C' STRICT; ! CREATE OR REPLACE FUNCTION pgstattuple ( ! IN table_oid OID, ! OUT table_len BIGINT, ! OUT tuple_count BIGINT, ! OUT tuple_len BIGINT, ! OUT tuple_percent FLOAT8, ! OUT dead_tuple_count BIGINT, ! OUT dead_tuple_len BIGINT, ! OUT dead_tuple_percent FLOAT8, ! OUT free_space BIGINT, ! OUT free_percent FLOAT8 ! ) RETURNS RECORD AS 'MODULE_PATHNAME', 'pgstattuplebyid' LANGUAGE 'C' STRICT;