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 42B5070B.9010900@paradise.net.nz
Whole thread Raw
In response to Re: TODO Item - Return compressed length of TOAST datatypes (WIP)  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: TODO Item - Return compressed length of TOAST datatypes
List pgsql-patches
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!

Cheers

Mark

Tom Lane wrote:
>
> My recollection of that discussion is that we just wanted something
> that would return the actual VARSIZE() of the datum.  You're building
> something way too confusing ...
>
> A more interesting point is that the way you've declared the function,
> it will only work on text values, which is pretty limiting.  Ideally
> we'd define this thing as "pg_datum_length(any-varlena-type) returns int"
> but there is no pseudotype corresponding to "any varlena type".
>
> I was thinking about this the other day in connection with my proposal
> to make something that could return the TOAST value OID of an
> out-of-line datum.  I think the only non-restrictive way to do it would
> be to declare the function as taking "any", and then add a runtime check
> using the get_fn_expr_argtype() mechanism to test that what you've been
> given is in fact a varlena datatype.
>
>


diff -Nacr ./src/backend/access/heap/tuptoaster.c.orig ./src/backend/access/heap/tuptoaster.c
*** ./src/backend/access/heap/tuptoaster.c.orig    Mon Mar 21 13:23:58 2005
--- ./src/backend/access/heap/tuptoaster.c    Sun Jun 19 14:24:43 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/Makefile.orig ./src/backend/utils/adt/Makefile
*** ./src/backend/utils/adt/Makefile.orig    Fri Apr  2 09:28:45 2004
--- ./src/backend/utils/adt/Makefile    Fri Jun 17 17:52:09 2005
***************
*** 24,30 ****
      tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
      network.o mac.o inet_net_ntop.o inet_net_pton.o \
      ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
!     ascii.o quote.o pgstatfuncs.o encode.o

  like.o: like.c like_match.c

--- 24,30 ----
      tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
      network.o mac.o inet_net_ntop.o inet_net_pton.o \
      ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
!     ascii.o quote.o pgstatfuncs.o encode.o toastfuncs.o

  like.o: like.c like_match.c

diff -Nacr ./src/backend/utils/adt/toastfuncs.c.orig ./src/backend/utils/adt/toastfuncs.c
*** ./src/backend/utils/adt/toastfuncs.c.orig    Fri Jun 17 17:52:09 2005
--- ./src/backend/utils/adt/toastfuncs.c    Sun Jun 19 17:35:26 2005
***************
*** 0 ****
--- 1,74 ----
+ /*-------------------------------------------------------------------------
+  *
+  * toastfuncs.c
+  *      Functions for accessing information about toasted data.
+  *
+  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  *
+  * IDENTIFICATION
+  *      $PostgreSQL$
+  *
+  *-------------------------------------------------------------------------
+  */
+
+ #include "postgres.h"
+ #include "fmgr.h"
+
+ #include "catalog/pg_type.h"
+ #include "access/xact.h"
+ #include "access/tuptoaster.h"
+ #include "utils/builtins.h"
+ #include "utils/syscache.h"
+
+ Datum
+ pg_datum_length(PG_FUNCTION_ARGS)
+ {
+
+     Datum            value = PG_GETARG_DATUM(0);
+     int                size;
+
+
+     if (fcinfo->flinfo->fn_extra == NULL)
+     {
+         /*
+          * On the first call check 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;
+
+         fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
+                                                      sizeof(int));
+
+         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. */
+             elog(ERROR, "invalid typid %u", argtypeid);
+         }
+
+
+
+         if ( typlen != -1 )
+         {
+             elog(ERROR, "this function is only applicable to varlena types");
+         }
+     }
+
+
+     size = toast_datum_size(value) - VARHDRSZ;
+
+     PG_RETURN_INT32(size);
+ }
+
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    Sun Jun 19 12:48:35 2005
***************
*** 828,831 ****
--- 828,834 ----
  /* catalog/pg_conversion.c */
  extern Datum pg_convert_using(PG_FUNCTION_ARGS);

+ /* toastfuncs.c */
+ extern Datum pg_datum_length(PG_FUNCTION_ARGS);
+
  #endif   /* BUILTINS_H */

pgsql-patches by date:

Previous
From: Martin Pitt
Date:
Subject: Re: Add PG version number to NLS files
Next
From: Andreas Pflug
Date:
Subject: win32/MSVC fix for libpq