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);

---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
       choose an index scan if your joining column's datatypes do not
       match

Reply via email to