LCOV - code coverage report
Current view: top level - src/include/utils - expandeddatum.h (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 4 4 100.0 %
Date: 2024-11-21 08:14:44 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * expandeddatum.h
       4             :  *    Declarations for access to "expanded" value representations.
       5             :  *
       6             :  * Complex data types, particularly container types such as arrays and
       7             :  * records, usually have on-disk representations that are compact but not
       8             :  * especially convenient to modify.  What's more, when we do modify them,
       9             :  * having to recopy all the rest of the value can be extremely inefficient.
      10             :  * Therefore, we provide a notion of an "expanded" representation that is used
      11             :  * only in memory and is optimized more for computation than storage.
      12             :  * The format appearing on disk is called the data type's "flattened"
      13             :  * representation, since it is required to be a contiguous blob of bytes --
      14             :  * but the type can have an expanded representation that is not.  Data types
      15             :  * must provide means to translate an expanded representation back to
      16             :  * flattened form.
      17             :  *
      18             :  * An expanded object is meant to survive across multiple operations, but
      19             :  * not to be enormously long-lived; for example it might be a local variable
      20             :  * in a PL/pgSQL procedure.  So its extra bulk compared to the on-disk format
      21             :  * is a worthwhile trade-off.
      22             :  *
      23             :  * References to expanded objects are a type of TOAST pointer.
      24             :  * Because of longstanding conventions in Postgres, this means that the
      25             :  * flattened form of such an object must always be a varlena object.
      26             :  * Fortunately that's no restriction in practice.
      27             :  *
      28             :  * There are actually two kinds of TOAST pointers for expanded objects:
      29             :  * read-only and read-write pointers.  Possession of one of the latter
      30             :  * authorizes a function to modify the value in-place rather than copying it
      31             :  * as would normally be required.  Functions should always return a read-write
      32             :  * pointer to any new expanded object they create.  Functions that modify an
      33             :  * argument value in-place must take care that they do not corrupt the old
      34             :  * value if they fail partway through.
      35             :  *
      36             :  *
      37             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
      38             :  * Portions Copyright (c) 1994, Regents of the University of California
      39             :  *
      40             :  * src/include/utils/expandeddatum.h
      41             :  *
      42             :  *-------------------------------------------------------------------------
      43             :  */
      44             : #ifndef EXPANDEDDATUM_H
      45             : #define EXPANDEDDATUM_H
      46             : 
      47             : #include "varatt.h"
      48             : 
      49             : /* Size of an EXTERNAL datum that contains a pointer to an expanded object */
      50             : #define EXPANDED_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(varatt_expanded))
      51             : 
      52             : /*
      53             :  * "Methods" that must be provided for any expanded object.
      54             :  *
      55             :  * get_flat_size: compute space needed for flattened representation (total,
      56             :  * including header).
      57             :  *
      58             :  * flatten_into: construct flattened representation in the caller-allocated
      59             :  * space at *result, of size allocated_size (which will always be the result
      60             :  * of a preceding get_flat_size call; it's passed for cross-checking).
      61             :  *
      62             :  * The flattened representation must be a valid in-line, non-compressed,
      63             :  * 4-byte-header varlena object.
      64             :  *
      65             :  * Note: construction of a heap tuple from an expanded datum calls
      66             :  * get_flat_size twice, so it's worthwhile to make sure that that doesn't
      67             :  * incur too much overhead.
      68             :  */
      69             : typedef Size (*EOM_get_flat_size_method) (ExpandedObjectHeader *eohptr);
      70             : typedef void (*EOM_flatten_into_method) (ExpandedObjectHeader *eohptr,
      71             :                                          void *result, Size allocated_size);
      72             : 
      73             : /* Struct of function pointers for an expanded object's methods */
      74             : typedef struct ExpandedObjectMethods
      75             : {
      76             :     EOM_get_flat_size_method get_flat_size;
      77             :     EOM_flatten_into_method flatten_into;
      78             : } ExpandedObjectMethods;
      79             : 
      80             : /*
      81             :  * Every expanded object must contain this header; typically the header
      82             :  * is embedded in some larger struct that adds type-specific fields.
      83             :  *
      84             :  * It is presumed that the header object and all subsidiary data are stored
      85             :  * in eoh_context, so that the object can be freed by deleting that context,
      86             :  * or its storage lifespan can be altered by reparenting the context.
      87             :  * (In principle the object could own additional resources, such as malloc'd
      88             :  * storage, and use a memory context reset callback to free them upon reset or
      89             :  * deletion of eoh_context.)
      90             :  *
      91             :  * We set up two TOAST pointers within the standard header, one read-write
      92             :  * and one read-only.  This allows functions to return either kind of pointer
      93             :  * without making an additional allocation, and in particular without worrying
      94             :  * whether a separately palloc'd object would have sufficient lifespan.
      95             :  * But note that these pointers are just a convenience; a pointer object
      96             :  * appearing somewhere else would still be legal.
      97             :  *
      98             :  * The typedef declaration for this appears in postgres.h.
      99             :  */
     100             : struct ExpandedObjectHeader
     101             : {
     102             :     /* Phony varlena header */
     103             :     int32       vl_len_;        /* always EOH_HEADER_MAGIC, see below */
     104             : 
     105             :     /* Pointer to methods required for object type */
     106             :     const ExpandedObjectMethods *eoh_methods;
     107             : 
     108             :     /* Memory context containing this header and subsidiary data */
     109             :     MemoryContext eoh_context;
     110             : 
     111             :     /* Standard R/W TOAST pointer for this object is kept here */
     112             :     char        eoh_rw_ptr[EXPANDED_POINTER_SIZE];
     113             : 
     114             :     /* Standard R/O TOAST pointer for this object is kept here */
     115             :     char        eoh_ro_ptr[EXPANDED_POINTER_SIZE];
     116             : };
     117             : 
     118             : /*
     119             :  * Particularly for read-only functions, it is handy to be able to work with
     120             :  * either regular "flat" varlena inputs or expanded inputs of the same data
     121             :  * type.  To allow determining which case an argument-fetching function has
     122             :  * returned, the first int32 of an ExpandedObjectHeader always contains -1
     123             :  * (EOH_HEADER_MAGIC to the code).  This works since no 4-byte-header varlena
     124             :  * could have that as its first 4 bytes.  Caution: we could not reliably tell
     125             :  * the difference between an ExpandedObjectHeader and a short-header object
     126             :  * with this trick.  However, it works fine if the argument fetching code
     127             :  * always returns either a 4-byte-header flat object or an expanded object.
     128             :  */
     129             : #define EOH_HEADER_MAGIC (-1)
     130             : #define VARATT_IS_EXPANDED_HEADER(PTR) \
     131             :     (((varattrib_4b *) (PTR))->va_4byte.va_header == (uint32) EOH_HEADER_MAGIC)
     132             : 
     133             : /*
     134             :  * Generic support functions for expanded objects.
     135             :  * (More of these might be worth inlining later.)
     136             :  */
     137             : 
     138             : static inline Datum
     139       42114 : EOHPGetRWDatum(const struct ExpandedObjectHeader *eohptr)
     140             : {
     141       42114 :     return PointerGetDatum(eohptr->eoh_rw_ptr);
     142             : }
     143             : 
     144             : static inline Datum
     145       31212 : EOHPGetRODatum(const struct ExpandedObjectHeader *eohptr)
     146             : {
     147       31212 :     return PointerGetDatum(eohptr->eoh_ro_ptr);
     148             : }
     149             : 
     150             : /* Does the Datum represent a writable expanded object? */
     151             : #define DatumIsReadWriteExpandedObject(d, isnull, typlen) \
     152             :     (((isnull) || (typlen) != -1) ? false : \
     153             :      VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)))
     154             : 
     155             : #define MakeExpandedObjectReadOnly(d, isnull, typlen) \
     156             :     (((isnull) || (typlen) != -1) ? (d) : \
     157             :      MakeExpandedObjectReadOnlyInternal(d))
     158             : 
     159             : extern ExpandedObjectHeader *DatumGetEOHP(Datum d);
     160             : extern void EOH_init_header(ExpandedObjectHeader *eohptr,
     161             :                             const ExpandedObjectMethods *methods,
     162             :                             MemoryContext obj_context);
     163             : extern Size EOH_get_flat_size(ExpandedObjectHeader *eohptr);
     164             : extern void EOH_flatten_into(ExpandedObjectHeader *eohptr,
     165             :                              void *result, Size allocated_size);
     166             : extern Datum MakeExpandedObjectReadOnlyInternal(Datum d);
     167             : extern Datum TransferExpandedObject(Datum d, MemoryContext new_parent);
     168             : extern void DeleteExpandedObject(Datum d);
     169             : 
     170             : #endif                          /* EXPANDEDDATUM_H */

Generated by: LCOV version 1.14