diff -Nacr ./doc/src/sgml/func.sgml.orig ./doc/src/sgml/func.sgml *** ./doc/src/sgml/func.sgml.orig Mon Jun 20 15:38:23 2005 --- ./doc/src/sgml/func.sgml Mon Jun 20 15:45:51 2005 *************** *** 2187,2192 **** --- 2187,2200 ---- + pg_datum_length(string) + integer + Number of bytes (before toast decompression) in string + pg_datum_length( 'jo\\000se'::bytea) + 5 + + + position(substring in string) integer Location of specified substring diff -Nacr ./src/backend/access/heap/tuptoaster.c.orig ./src/backend/access/heap/tuptoaster.c *** ./src/backend/access/heap/tuptoaster.c.orig Mon Jun 20 17:11:37 2005 --- ./src/backend/access/heap/tuptoaster.c Mon Jun 20 17:11:44 2005 *************** *** 1436,1438 **** --- 1436,1482 ---- 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 -Nacr ./src/backend/utils/adt/varlena.c.orig ./src/backend/utils/adt/varlena.c *** ./src/backend/utils/adt/varlena.c.orig Mon Jun 20 14:28:03 2005 --- ./src/backend/utils/adt/varlena.c Mon Jun 20 17:17:58 2005 *************** *** 28,33 **** --- 28,34 ---- #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/pg_locale.h" + #include "utils/syscache.h" typedef struct varlena unknown; *************** *** 2330,2333 **** --- 2331,2396 ---- result_text = PG_STR_GET_TEXT(hexsum); PG_RETURN_TEXT_P(result_text); + } + + /* + * Show the (possibly compressed) length of a datum. + */ + Datum + pg_datum_length(PG_FUNCTION_ARGS) + { + + Datum value = PG_GETARG_DATUM(0); + int result; + + + if (fcinfo->flinfo->fn_extra == NULL) + { + /* + * On the first call lookup the datatype of the supplied argument + * and check if is a varlena. + */ + Oid argtypeid = get_fn_expr_argtype(fcinfo->flinfo, 0); + HeapTuple tp; + int typlen = 0; + + + tp = SearchSysCache(TYPEOID, + ObjectIdGetDatum(argtypeid), + 0, 0, 0); + if (HeapTupleIsValid(tp)) + { + Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); + typlen = typtup->typlen; + ReleaseSysCache(tp); + } + else + { + /* Oid not in pg_type, should never happen. */ + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("invalid typid: %u", argtypeid))); + } + + + if ( typlen != -1 ) + { + /* Not a varlena. */ + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("function is only applicable to varlena types"))); + } + + + /* + * Allocate fn_extra so we don't go here again! + */ + fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, + sizeof(int)); + } + + + result = toast_datum_size(value) - VARHDRSZ; + + PG_RETURN_INT32(result); } diff -Nacr ./src/include/access/tuptoaster.h.orig ./src/include/access/tuptoaster.h *** ./src/include/access/tuptoaster.h.orig Mon Mar 21 13:24:04 2005 --- ./src/include/access/tuptoaster.h Sun Jun 19 14:45:18 2005 *************** *** 138,141 **** --- 138,149 ---- */ extern Size toast_raw_datum_size(Datum value); + /* ---------- + * toast_datum_size - + * + * Return the (possibly compressed) size of a varlena datum + * ---------- + */ + extern Size toast_datum_size(Datum value); + #endif /* TUPTOASTER_H */ diff -Nacr ./src/include/catalog/pg_proc.h.orig ./src/include/catalog/pg_proc.h *** ./src/include/catalog/pg_proc.h.orig Wed Jun 15 09:04:41 2005 --- ./src/include/catalog/pg_proc.h Sun Jun 19 17:08:35 2005 *************** *** 3655,3660 **** --- 3655,3664 ---- 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"); + /* Toast compressed length */ + DATA(insert OID = 2561 ( pg_datum_length PGNSP PGUID 12 f f t f i 1 23 "2276" _null_ _null_ _null_ pg_datum_length - _null_ )); + DESCR("length (possibly compressed) of varlena types"); + /* * Symbolic values for provolatile column: these indicate whether the result diff -Nacr ./src/include/utils/builtins.h.orig ./src/include/utils/builtins.h *** ./src/include/utils/builtins.h.orig Fri May 27 12:57:49 2005 --- ./src/include/utils/builtins.h Mon Jun 20 15:59:09 2005 *************** *** 601,606 **** --- 601,607 ---- 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_datum_length(PG_FUNCTION_ARGS); /* version.c */ extern Datum pgsql_version(PG_FUNCTION_ARGS);