From a9236028554ca0e11797c887373c1a34800a4fa6 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Wed, 6 Jul 2005 19:02:54 +0000 Subject: [PATCH] Add pg_column_size() to return storage size of a column, including possible compression. Mark Kirkwood --- doc/src/sgml/func.sgml | 10 +++++- src/backend/access/heap/tuptoaster.c | 44 +++++++++++++++++++++++++- src/backend/utils/adt/varlena.c | 47 +++++++++++++++++++++++++++- src/include/access/tuptoaster.h | 10 +++++- src/include/catalog/pg_proc.h | 6 +++- src/include/utils/builtins.h | 3 +- 6 files changed, 114 insertions(+), 6 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index d837219421..4ff434aca8 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,5 +1,5 @@ @@ -2186,6 +2186,14 @@ PostgreSQL documentation 5 + + pg_column_size(string) + integer + Number of bytes required to store the value, which might be compressed + pg_column_size('jo\\000se'::bytea) + 5 + + position(substring in string) integer diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 3a3e2d301b..77caf79dd1 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.49 2005/03/21 01:23:58 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.50 2005/07/06 19:02:52 momjian Exp $ * * * INTERFACE ROUTINES @@ -1436,3 +1436,45 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length) return result; } + +/* ---------- + * toast_datum_size + * + * Show the (possibly compressed) size of a datum + * ---------- + */ +Size +toast_datum_size(Datum value) +{ + + varattrib *attr = (varattrib *) DatumGetPointer(value); + Size result; + + if (VARATT_IS_EXTERNAL(attr)) + { + /* + * Attribute is stored externally - If it is compressed too, + * then we need to get the external datum and calculate its size, + * otherwise we just use the external rawsize. + */ + if (VARATT_IS_COMPRESSED(attr)) + { + varattrib *attrext = toast_fetch_datum(attr); + result = VARSIZE(attrext); + pfree(attrext); + } + else + result = attr->va_content.va_external.va_rawsize; + } + else + { + /* + * Attribute is stored inline either compressed or not, just + * calculate the size of the datum in either case. + */ + result = VARSIZE(attr); + } + + return result; + +} diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index f114f96cf7..0568c2eea7 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.124 2005/07/04 18:56:44 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.125 2005/07/06 19:02:52 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,7 @@ #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/pg_locale.h" +#include "utils/syscache.h" typedef struct varlena unknown; @@ -2348,3 +2349,47 @@ md5_bytea(PG_FUNCTION_ARGS) result_text = PG_STR_GET_TEXT(hexsum); PG_RETURN_TEXT_P(result_text); } + +/* + * Return the length of a datum, possibly compressed + */ +Datum +pg_column_size(PG_FUNCTION_ARGS) +{ + Datum value = PG_GETARG_DATUM(0); + int result; + + /* fn_extra stores the fixed column length, or -1 for varlena. */ + if (fcinfo->flinfo->fn_extra == NULL) /* first call? */ + { + /* On the first call lookup the datatype of the supplied argument */ + Oid argtypeid = get_fn_expr_argtype(fcinfo->flinfo, 0); + HeapTuple tp; + int typlen; + + tp = SearchSysCache(TYPEOID, + ObjectIdGetDatum(argtypeid), + 0, 0, 0); + if (!HeapTupleIsValid(tp)) + { + /* Oid not in pg_type, should never happen. */ + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("invalid typid: %u", argtypeid))); + } + + typlen = ((Form_pg_type)GETSTRUCT(tp))->typlen; + ReleaseSysCache(tp); + fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, + sizeof(int)); + *(int *)fcinfo->flinfo->fn_extra = typlen; + } + + if (*(int *)fcinfo->flinfo->fn_extra != -1) + PG_RETURN_INT32(*(int *)fcinfo->flinfo->fn_extra); + else + { + result = toast_datum_size(value) - VARHDRSZ; + PG_RETURN_INT32(result); + } +} diff --git a/src/include/access/tuptoaster.h b/src/include/access/tuptoaster.h index 1cf3b4debe..b45df277b1 100644 --- a/src/include/access/tuptoaster.h +++ b/src/include/access/tuptoaster.h @@ -6,7 +6,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.22 2005/03/21 01:24:04 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.23 2005/07/06 19:02:53 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -138,4 +138,12 @@ extern Datum toast_compress_datum(Datum value); */ extern Size toast_raw_datum_size(Datum value); +/* ---------- + * toast_datum_size - + * + * Return the storage size of a varlena datum + * ---------- + */ +extern Size toast_datum_size(Datum value); + #endif /* TUPTOASTER_H */ diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 340052792f..0a213f64be 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.373 2005/07/01 19:19:03 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.374 2005/07/06 19:02:53 momjian Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -3658,6 +3658,10 @@ DESCR("current value from last used sequence"); DATA(insert OID = 2560 ( pg_postmaster_start_time PGNSP PGUID 12 f f t f s 0 1184 "" _null_ _null_ _null_ pgsql_postmaster_start_time - _null_ )); DESCR("postmaster start time"); +/* Column storage size */ +DATA(insert OID = 1269 ( pg_column_size PGNSP PGUID 12 f f t f i 1 23 "2276" _null_ _null_ _null_ pg_column_size - _null_ )); +DESCR("bytes required to store the value, perhaps with compression"); + /* new functions for Y-direction rtree opclasses */ DATA(insert OID = 2562 ( box_below PGNSP PGUID 12 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_below - _null_ )); DESCR("is below"); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 37423dc73c..fea496aaae 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.258 2005/06/17 22:32:50 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.259 2005/07/06 19:02:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -601,6 +601,7 @@ extern Datum byteacat(PG_FUNCTION_ARGS); extern Datum byteapos(PG_FUNCTION_ARGS); extern Datum bytea_substr(PG_FUNCTION_ARGS); extern Datum bytea_substr_no_len(PG_FUNCTION_ARGS); +extern Datum pg_column_size(PG_FUNCTION_ARGS); /* version.c */ extern Datum pgsql_version(PG_FUNCTION_ARGS);