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 */
---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

Reply via email to