Re: TODO Item - Return compressed length of TOAST datatypes - Mailing list pgsql-patches

From Mark Kirkwood
Subject Re: TODO Item - Return compressed length of TOAST datatypes
Date
Msg-id 42B79B34.5000609@paradise.net.nz
Whole thread Raw
In response to Re: TODO Item - Return compressed length of TOAST datatypes  (Mark Kirkwood <markir@paradise.net.nz>)
Responses Re: TODO Item - Return compressed length of TOAST datatypes
List pgsql-patches
I did a few cleanups on the last patch. Please examine this one instead.
The changes are:

1. Add documentation for pg_datum_length builtin.
2. Correct some typos in the code comments.
3. Move the code in toastfuncs.c to varlena.c as it is probably the
correct place.
4. Use ereport instead of elog.
5  Quiet compiler warning in pg_datum_length.

Best wishes

Mark

Mark Kirkwood wrote:
> The next iteration -
>
> Hopefully I have got the idea basically right.
>
> I wonder if I have done the "am I a varlena" the long way.., pls advise
> if so!
>


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 ----
        </row>

        <row>
+        <entry><literal><function>pg_datum_length</function>(<parameter>string</parameter>)</literal></entry>
+        <entry><type>integer</type></entry>
+        <entry>Number of bytes (before toast decompression) in string</entry>
+        <entry><literal>pg_datum_length( 'jo\\000se'::bytea)</literal></entry>
+        <entry><literal>5</literal></entry>
+       </row>
+
+       <row>
         <entry><literal><function>position</function>(<parameter>substring</parameter> in
<parameter>string</parameter>)</literal></entry>
         <entry><type>integer</type></entry>
         <entry>Location of specified substring</entry>
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);


pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: code cleanup for tz
Next
From: Eugen Nedelcu
Date:
Subject: thousands comma numeric formatting in psql