LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - datum.c (source / functions) Coverage Total Hit UNC UBC GIC GNC CBC EUB ECB DUB DCB
Current: bed3ffbf9d952be6c7d739d068cdce44c046dfb7 vs 574581b50ac9c63dd9e4abebb731a3b67e5b50f6 Lines: 89.9 % 178 160 18 7 153 1 7
Current Date: 2026-05-05 10:23:31 +0900 Functions: 100.0 % 10 10 5 5
Baseline: lcov-20260505-025707-baseline Branches: 73.1 % 104 76 2 26 6 8 62 8 32 2 8
Baseline Date: 2026-05-05 10:27:06 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 80.0 % 30 24 6 7 17
(360..) days: 91.9 % 148 136 12 136 1
Function coverage date bins:
(360..) days: 100.0 % 10 10 5 5
Branch coverage date bins:
(30,360] days: 77.8 % 18 14 2 2 8 6
(360..) days: 49.2 % 126 62 24 6 56 8 32

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * datum.c
                                  4                 :                :  *    POSTGRES Datum (abstract data type) manipulation routines.
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/utils/adt/datum.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : 
                                 16                 :                : /*
                                 17                 :                :  * In the implementation of these routines we assume the following:
                                 18                 :                :  *
                                 19                 :                :  * A) if a type is "byVal" then all the information is stored in the
                                 20                 :                :  * Datum itself (i.e. no pointers involved!). In this case the
                                 21                 :                :  * length of the type is always greater than zero and not more than
                                 22                 :                :  * "sizeof(Datum)"
                                 23                 :                :  *
                                 24                 :                :  * B) if a type is not "byVal" and it has a fixed length (typlen > 0),
                                 25                 :                :  * then the "Datum" always contains a pointer to a stream of bytes.
                                 26                 :                :  * The number of significant bytes are always equal to the typlen.
                                 27                 :                :  *
                                 28                 :                :  * C) if a type is not "byVal" and has typlen == -1,
                                 29                 :                :  * then the "Datum" always points to a "varlena".
                                 30                 :                :  * This varlena structure has information about the actual length of this
                                 31                 :                :  * particular instance of the type and about its value.
                                 32                 :                :  *
                                 33                 :                :  * D) if a type is not "byVal" and has typlen == -2,
                                 34                 :                :  * then the "Datum" always points to a null-terminated C string.
                                 35                 :                :  *
                                 36                 :                :  * Note that we do not treat "toasted" datums specially; therefore what
                                 37                 :                :  * will be copied or compared is the compressed data or toast reference.
                                 38                 :                :  * An exception is made for datumCopy() of an expanded object, however,
                                 39                 :                :  * because most callers expect to get a simple contiguous (and pfree'able)
                                 40                 :                :  * result from datumCopy().  See also datumTransfer().
                                 41                 :                :  */
                                 42                 :                : 
                                 43                 :                : #include "postgres.h"
                                 44                 :                : 
                                 45                 :                : #include "access/detoast.h"
                                 46                 :                : #include "common/hashfn.h"
                                 47                 :                : #include "fmgr.h"
                                 48                 :                : #include "utils/datum.h"
                                 49                 :                : #include "utils/expandeddatum.h"
                                 50                 :                : #include "utils/fmgrprotos.h"
                                 51                 :                : 
                                 52                 :                : 
                                 53                 :                : /*-------------------------------------------------------------------------
                                 54                 :                :  * datumGetSize
                                 55                 :                :  *
                                 56                 :                :  * Find the "real" size of a datum, given the datum value,
                                 57                 :                :  * whether it is a "by value", and the declared type length.
                                 58                 :                :  * (For TOAST pointer datums, this is the size of the pointer datum.)
                                 59                 :                :  *
                                 60                 :                :  * This is essentially an out-of-line version of the att_addlength_datum()
                                 61                 :                :  * macro in access/tupmacs.h.  We do a tad more error checking though.
                                 62                 :                :  *-------------------------------------------------------------------------
                                 63                 :                :  */
                                 64                 :                : Size
 9428 tgl@sss.pgh.pa.us          65                 :CBC     4712022 : datumGetSize(Datum value, bool typByVal, int typLen)
                                 66                 :                : {
                                 67                 :                :     Size        size;
                                 68                 :                : 
                                 69         [ +  + ]:        4712022 :     if (typByVal)
                                 70                 :                :     {
                                 71                 :                :         /* Pass-by-value types are always fixed-length */
                                 72   [ +  -  -  + ]:          69048 :         Assert(typLen > 0 && typLen <= sizeof(Datum));
                                 73                 :          69048 :         size = (Size) typLen;
                                 74                 :                :     }
                                 75                 :                :     else
                                 76                 :                :     {
 8655                            77         [ +  + ]:        4642974 :         if (typLen > 0)
                                 78                 :                :         {
                                 79                 :                :             /* Fixed-length pass-by-ref type */
                                 80                 :        4254195 :             size = (Size) typLen;
                                 81                 :                :         }
                                 82         [ +  + ]:         388779 :         else if (typLen == -1)
                                 83                 :                :         {
                                 84                 :                :             /* It is a varlena datatype */
   83 michael@paquier.xyz        85                 :GNC      337421 :             varlena    *s = (varlena *) DatumGetPointer(value);
                                 86                 :                : 
  223 peter@eisentraut.org       87         [ -  + ]:         337421 :             if (!s)
 8318 tgl@sss.pgh.pa.us          88         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                 89                 :                :                         (errcode(ERRCODE_DATA_EXCEPTION),
                                 90                 :                :                          errmsg("invalid Datum pointer")));
                                 91                 :                : 
 6969 tgl@sss.pgh.pa.us          92   [ +  +  +  -  :CBC      337421 :             size = (Size) VARSIZE_ANY(s);
                                     +  -  -  +  +  
                                                 + ]
                                 93                 :                :         }
 8655                            94         [ +  - ]:          51358 :         else if (typLen == -2)
                                 95                 :                :         {
                                 96                 :                :             /* It is a cstring datatype */
 8644 bruce@momjian.us           97                 :          51358 :             char       *s = (char *) DatumGetPointer(value);
                                 98                 :                : 
  223 peter@eisentraut.org       99         [ -  + ]:GNC       51358 :             if (!s)
 8318 tgl@sss.pgh.pa.us         100         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                101                 :                :                         (errcode(ERRCODE_DATA_EXCEPTION),
                                102                 :                :                          errmsg("invalid Datum pointer")));
                                103                 :                : 
 8655 tgl@sss.pgh.pa.us         104                 :CBC       51358 :             size = (Size) (strlen(s) + 1);
                                105                 :                :         }
                                106                 :                :         else
                                107                 :                :         {
 8318 tgl@sss.pgh.pa.us         108         [ #  # ]:UBC           0 :             elog(ERROR, "invalid typLen: %d", typLen);
                                109                 :                :             size = 0;           /* keep compiler quiet */
                                110                 :                :         }
                                111                 :                :     }
                                112                 :                : 
10108 bruce@momjian.us          113                 :CBC     4712022 :     return size;
                                114                 :                : }
                                115                 :                : 
                                116                 :                : /*-------------------------------------------------------------------------
                                117                 :                :  * datumCopy
                                118                 :                :  *
                                119                 :                :  * Make a copy of a non-NULL datum.
                                120                 :                :  *
                                121                 :                :  * If the datatype is pass-by-reference, memory is obtained with palloc().
                                122                 :                :  *
                                123                 :                :  * If the value is a reference to an expanded object, we flatten into memory
                                124                 :                :  * obtained with palloc().  We need to copy because one of the main uses of
                                125                 :                :  * this function is to copy a datum out of a transient memory context that's
                                126                 :                :  * about to be destroyed, and the expanded object is probably in a child
                                127                 :                :  * context that will also go away.  Moreover, many callers assume that the
                                128                 :                :  * result is a single pfree-able chunk.
                                129                 :                :  *-------------------------------------------------------------------------
                                130                 :                :  */
                                131                 :                : Datum
 9428 tgl@sss.pgh.pa.us         132                 :       16492523 : datumCopy(Datum value, bool typByVal, int typLen)
                                133                 :                : {
                                134                 :                :     Datum       res;
                                135                 :                : 
                                136         [ +  + ]:       16492523 :     if (typByVal)
10467 bruce@momjian.us          137                 :        8523946 :         res = value;
 4009 tgl@sss.pgh.pa.us         138         [ +  + ]:        7968577 :     else if (typLen == -1)
                                139                 :                :     {
                                140                 :                :         /* It is a varlena datatype */
   83 michael@paquier.xyz       141                 :GNC     4295607 :         varlena    *vl = (varlena *) DatumGetPointer(value);
                                142                 :                : 
 4009 tgl@sss.pgh.pa.us         143   [ +  +  +  + ]:CBC     4295607 :         if (VARATT_IS_EXTERNAL_EXPANDED(vl))
 4009 tgl@sss.pgh.pa.us         144                 :ECB       (472) :         {
                                145                 :                :             /* Flatten into the caller's memory context */
 4009 tgl@sss.pgh.pa.us         146                 :CBC         582 :             ExpandedObjectHeader *eoh = DatumGetEOHP(value);
                                147                 :                :             Size        resultsize;
                                148                 :                :             char       *resultptr;
                                149                 :                : 
                                150                 :            582 :             resultsize = EOH_get_flat_size(eoh);
                                151                 :            582 :             resultptr = (char *) palloc(resultsize);
  523 peter@eisentraut.org      152                 :            582 :             EOH_flatten_into(eoh, resultptr, resultsize);
 4009 tgl@sss.pgh.pa.us         153                 :            582 :             res = PointerGetDatum(resultptr);
                                154                 :                :         }
                                155                 :                :         else
                                156                 :                :         {
                                157                 :                :             /* Otherwise, just copy the varlena datum verbatim */
                                158                 :                :             Size        realSize;
                                159                 :                :             char       *resultptr;
                                160                 :                : 
                                161   [ +  +  +  -  :        4295025 :             realSize = (Size) VARSIZE_ANY(vl);
                                     +  -  -  +  +  
                                                 + ]
                                162                 :        4295025 :             resultptr = (char *) palloc(realSize);
                                163                 :        4295025 :             memcpy(resultptr, vl, realSize);
                                164                 :        4295025 :             res = PointerGetDatum(resultptr);
                                165                 :                :         }
                                166                 :                :     }
                                167                 :                :     else
                                168                 :                :     {
                                169                 :                :         /* Pass by reference, but not varlena, so not toasted */
                                170                 :                :         Size        realSize;
                                171                 :                :         char       *resultptr;
                                172                 :                : 
 9428                           173                 :        3672970 :         realSize = datumGetSize(value, typByVal, typLen);
                                174                 :                : 
 4009                           175                 :        3672970 :         resultptr = (char *) palloc(realSize);
                                176                 :        3672970 :         memcpy(resultptr, DatumGetPointer(value), realSize);
                                177                 :        3672970 :         res = PointerGetDatum(resultptr);
                                178                 :                :     }
10108 bruce@momjian.us          179                 :       16492523 :     return res;
                                180                 :                : }
                                181                 :                : 
                                182                 :                : /*-------------------------------------------------------------------------
                                183                 :                :  * datumTransfer
                                184                 :                :  *
                                185                 :                :  * Transfer a non-NULL datum into the current memory context.
                                186                 :                :  *
                                187                 :                :  * This is equivalent to datumCopy() except when the datum is a read-write
                                188                 :                :  * pointer to an expanded object.  In that case we merely reparent the object
                                189                 :                :  * into the current context, and return its standard R/W pointer (in case the
                                190                 :                :  * given one is a transient pointer of shorter lifespan).
                                191                 :                :  *-------------------------------------------------------------------------
                                192                 :                :  */
                                193                 :                : Datum
 4009 tgl@sss.pgh.pa.us         194                 :          75907 : datumTransfer(Datum value, bool typByVal, int typLen)
                                195                 :                : {
                                196   [ +  +  +  +  :         149814 :     if (!typByVal && typLen == -1 &&
                                              +  + ]
                                197   [ +  +  +  + ]:          73907 :         VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(value)))
                                198                 :           2065 :         value = TransferExpandedObject(value, CurrentMemoryContext);
                                199                 :                :     else
                                200                 :          73842 :         value = datumCopy(value, typByVal, typLen);
                                201                 :          75907 :     return value;
                                202                 :                : }
                                203                 :                : 
                                204                 :                : /*-------------------------------------------------------------------------
                                205                 :                :  * datumIsEqual
                                206                 :                :  *
                                207                 :                :  * Return true if two datums are equal, false otherwise
                                208                 :                :  *
                                209                 :                :  * NOTE: XXX!
                                210                 :                :  * We just compare the bytes of the two values, one by one.
                                211                 :                :  * This routine will return false if there are 2 different
                                212                 :                :  * representations of the same value (something along the lines
                                213                 :                :  * of say the representation of zero in one's complement arithmetic).
                                214                 :                :  * Also, it will probably not give the answer you want if either
                                215                 :                :  * datum has been "toasted".
                                216                 :                :  *
                                217                 :                :  * Do not try to make this any smarter than it currently is with respect
                                218                 :                :  * to "toasted" datums, because some of the callers could be working in the
                                219                 :                :  * context of an aborted transaction.
                                220                 :                :  *-------------------------------------------------------------------------
                                221                 :                :  */
                                222                 :                : bool
 9428                           223                 :        1102657 : datumIsEqual(Datum value1, Datum value2, bool typByVal, int typLen)
                                224                 :                : {
                                225                 :                :     bool        res;
                                226                 :                : 
                                227         [ +  + ]:        1102657 :     if (typByVal)
                                228                 :                :     {
                                229                 :                :         /*
                                230                 :                :          * just compare the two datums. NOTE: just comparing "len" bytes will
                                231                 :                :          * not do the work, because we do not know how these bytes are aligned
                                232                 :                :          * inside the "Datum".  We assume instead that any given datatype is
                                233                 :                :          * consistent about how it fills extraneous bits in the Datum.
                                234                 :                :          */
                                235                 :         896059 :         res = (value1 == value2);
                                236                 :                :     }
                                237                 :                :     else
                                238                 :                :     {
                                239                 :                :         Size        size1,
                                240                 :                :                     size2;
                                241                 :                :         char       *s1,
                                242                 :                :                    *s2;
                                243                 :                : 
                                244                 :                :         /*
                                245                 :                :          * Compare the bytes pointed by the pointers stored in the datums.
                                246                 :                :          */
                                247                 :         206598 :         size1 = datumGetSize(value1, typByVal, typLen);
                                248                 :         206598 :         size2 = datumGetSize(value2, typByVal, typLen);
10467 bruce@momjian.us          249         [ +  + ]:         206598 :         if (size1 != size2)
10108                           250                 :           8502 :             return false;
10467                           251                 :         198096 :         s1 = (char *) DatumGetPointer(value1);
                                252                 :         198096 :         s2 = (char *) DatumGetPointer(value2);
 9428 tgl@sss.pgh.pa.us         253                 :         198096 :         res = (memcmp(s1, s2, size1) == 0);
                                254                 :                :     }
                                255                 :        1094155 :     return res;
                                256                 :                : }
                                257                 :                : 
                                258                 :                : /*-------------------------------------------------------------------------
                                259                 :                :  * datum_image_eq
                                260                 :                :  *
                                261                 :                :  * Compares two datums for identical contents when coerced to a signed integer
                                262                 :                :  * of typLen bytes.  Return true if the two datums are equal, false otherwise.
                                263                 :                :  *
                                264                 :                :  * The coercion is required as we're not always careful to use the correct
                                265                 :                :  * PG_RETURN_* macro.  If we didn't do this, a Datum that's been formed and
                                266                 :                :  * deformed into a tuple may not have the same signed representation as the
                                267                 :                :  * other datum value.
                                268                 :                :  *-------------------------------------------------------------------------
                                269                 :                :  */
                                270                 :                : bool
 2605 peter@eisentraut.org      271                 :       14555376 : datum_image_eq(Datum value1, Datum value2, bool typByVal, int typLen)
                                272                 :                : {
                                273                 :                :     Size        len1,
                                274                 :                :                 len2;
                                275                 :       14555376 :     bool        result = true;
                                276                 :                : 
 2374                           277         [ +  + ]:       14555376 :     if (typByVal)
                                278                 :                :     {
   36 drowley@postgresql.o      279   [ +  +  +  + ]:       12403633 :         switch (typLen)
                                280                 :                :         {
                                281                 :          13869 :             case sizeof(char):
                                282                 :          13869 :                 result = (DatumGetChar(value1) == DatumGetChar(value2));
                                283                 :          13869 :                 break;
                                284                 :         194017 :             case sizeof(int16):
                                285                 :         194017 :                 result = (DatumGetInt16(value1) == DatumGetInt16(value2));
                                286                 :         194017 :                 break;
                                287                 :       11836275 :             case sizeof(int32):
                                288                 :       11836275 :                 result = (DatumGetInt32(value1) == DatumGetInt32(value2));
                                289                 :       11836275 :                 break;
                                290                 :         359472 :             default:
                                291                 :         359472 :                 result = (value1 == value2);
                                292                 :         359472 :                 break;
                                293                 :                :         }
                                294                 :                :     }
 2374 peter@eisentraut.org      295         [ +  + ]:        2151743 :     else if (typLen > 0)
                                296                 :                :     {
                                297                 :        1606802 :         result = (memcmp(DatumGetPointer(value1),
                                298                 :        1606802 :                          DatumGetPointer(value2),
                                299                 :                :                          typLen) == 0);
                                300                 :                :     }
                                301         [ +  + ]:         544941 :     else if (typLen == -1)
                                302                 :                :     {
 2605                           303                 :         217023 :         len1 = toast_raw_datum_size(value1);
                                304                 :         217023 :         len2 = toast_raw_datum_size(value2);
                                305                 :                :         /* No need to de-toast if lengths don't match. */
                                306         [ +  + ]:         217023 :         if (len1 != len2)
                                307                 :          14551 :             result = false;
                                308                 :                :         else
                                309                 :                :         {
                                310                 :                :             varlena    *arg1val;
                                311                 :                :             varlena    *arg2val;
                                312                 :                : 
                                313                 :         202472 :             arg1val = PG_DETOAST_DATUM_PACKED(value1);
                                314                 :         202472 :             arg2val = PG_DETOAST_DATUM_PACKED(value2);
                                315                 :                : 
                                316         [ +  + ]:         202472 :             result = (memcmp(VARDATA_ANY(arg1val),
                                317         [ +  + ]:         202472 :                              VARDATA_ANY(arg2val),
                                318                 :                :                              len1 - VARHDRSZ) == 0);
                                319                 :                : 
                                320                 :                :             /* Only free memory if it's a copy made here. */
  152 peter@eisentraut.org      321         [ +  + ]:GNC      202472 :             if (arg1val != DatumGetPointer(value1))
 2605 peter@eisentraut.org      322                 :CBC           4 :                 pfree(arg1val);
  152 peter@eisentraut.org      323         [ +  + ]:GNC      202472 :             if (arg2val != DatumGetPointer(value2))
 2605 peter@eisentraut.org      324                 :CBC           4 :                 pfree(arg2val);
                                325                 :                :         }
                                326                 :                :     }
 2366 pg@bowt.ie                327         [ +  - ]:         327918 :     else if (typLen == -2)
                                328                 :                :     {
                                329                 :                :         char       *s1,
                                330                 :                :                    *s2;
                                331                 :                : 
                                332                 :                :         /* Compare cstring datums */
                                333                 :         327918 :         s1 = DatumGetCString(value1);
                                334                 :         327918 :         s2 = DatumGetCString(value2);
                                335                 :         327918 :         len1 = strlen(s1) + 1;
                                336                 :         327918 :         len2 = strlen(s2) + 1;
                                337         [ +  + ]:         327918 :         if (len1 != len2)
                                338                 :         175079 :             return false;
                                339                 :         152839 :         result = (memcmp(s1, s2, len1) == 0);
                                340                 :                :     }
                                341                 :                :     else
 2374 peter@eisentraut.org      342         [ #  # ]:UBC           0 :         elog(ERROR, "unexpected typLen: %d", typLen);
                                343                 :                : 
 2605 peter@eisentraut.org      344                 :CBC    14380297 :     return result;
                                345                 :                : }
                                346                 :                : 
                                347                 :                : /*-------------------------------------------------------------------------
                                348                 :                :  * datum_image_hash
                                349                 :                :  *
                                350                 :                :  * Generate a hash value based on the binary representation of 'value' when
                                351                 :                :  * represented as a signed integer of typLen bytes.  Most use cases will want
                                352                 :                :  * to use the hash function specific to the Datum's type, however, some corner
                                353                 :                :  * cases require generating a hash value based on the actual bits rather than
                                354                 :                :  * the logical value.
                                355                 :                :  *-------------------------------------------------------------------------
                                356                 :                :  */
                                357                 :                : uint32
 1623 drowley@postgresql.o      358                 :          80890 : datum_image_hash(Datum value, bool typByVal, int typLen)
                                359                 :                : {
                                360                 :                :     Size        len;
                                361                 :                :     uint32      result;
                                362                 :                : 
                                363         [ +  + ]:          80890 :     if (typByVal)
                                364                 :                :     {
   36                           365   [ -  -  +  + ]:          80754 :         switch (typLen)
                                366                 :                :         {
   36 drowley@postgresql.o      367                 :UBC           0 :             case sizeof(char):
                                368                 :              0 :                 value = CharGetDatum(DatumGetChar(value));
                                369                 :              0 :                 break;
                                370                 :              0 :             case sizeof(int16):
                                371                 :              0 :                 value = Int16GetDatum(DatumGetInt16(value));
                                372                 :              0 :                 break;
   36 drowley@postgresql.o      373                 :CBC       80722 :             case sizeof(int32):
                                374                 :          80722 :                 value = Int32GetDatum(DatumGetInt32(value));
                                375                 :          80722 :                 break;
                                376                 :                :                 /* Nothing needs done for 64-bit types */
                                377                 :                :         }
                                378                 :                : 
 1623                           379                 :          80754 :         result = hash_bytes((unsigned char *) &value, sizeof(Datum));
                                380                 :                :     }
                                381         [ +  + ]:            136 :     else if (typLen > 0)
                                382                 :             24 :         result = hash_bytes((unsigned char *) DatumGetPointer(value), typLen);
                                383         [ +  - ]:            112 :     else if (typLen == -1)
                                384                 :                :     {
                                385                 :                :         varlena    *val;
                                386                 :                : 
                                387                 :            112 :         len = toast_raw_datum_size(value);
                                388                 :                : 
                                389                 :            112 :         val = PG_DETOAST_DATUM_PACKED(value);
                                390                 :                : 
                                391         [ +  + ]:            112 :         result = hash_bytes((unsigned char *) VARDATA_ANY(val), len - VARHDRSZ);
                                392                 :                : 
                                393                 :                :         /* Only free memory if it's a copy made here. */
  152 peter@eisentraut.org      394         [ +  + ]:GNC         112 :         if (val != DatumGetPointer(value))
 1623 drowley@postgresql.o      395                 :CBC           8 :             pfree(val);
                                396                 :                :     }
 1623 drowley@postgresql.o      397         [ #  # ]:UBC           0 :     else if (typLen == -2)
                                398                 :                :     {
                                399                 :                :         char       *s;
                                400                 :                : 
                                401                 :              0 :         s = DatumGetCString(value);
                                402                 :              0 :         len = strlen(s) + 1;
                                403                 :                : 
                                404                 :              0 :         result = hash_bytes((unsigned char *) s, len);
                                405                 :                :     }
                                406                 :                :     else
                                407                 :                :     {
                                408         [ #  # ]:              0 :         elog(ERROR, "unexpected typLen: %d", typLen);
                                409                 :                :         result = 0;             /* keep compiler quiet */
                                410                 :                :     }
                                411                 :                : 
 1623 drowley@postgresql.o      412                 :CBC       80890 :     return result;
                                413                 :                : }
                                414                 :                : 
                                415                 :                : /*-------------------------------------------------------------------------
                                416                 :                :  * btequalimage
                                417                 :                :  *
                                418                 :                :  * Generic "equalimage" support function.
                                419                 :                :  *
                                420                 :                :  * B-Tree operator classes whose equality function could safely be replaced by
                                421                 :                :  * datum_image_eq() in all cases can use this as their "equalimage" support
                                422                 :                :  * function.
                                423                 :                :  *
                                424                 :                :  * Currently, we unconditionally assume that any B-Tree operator class that
                                425                 :                :  * registers btequalimage as its support function 4 must be able to safely use
                                426                 :                :  * optimizations like deduplication (i.e. we return true unconditionally).  If
                                427                 :                :  * it ever proved necessary to rescind support for an operator class, we could
                                428                 :                :  * do that in a targeted fashion by doing something with the opcintype
                                429                 :                :  * argument.
                                430                 :                :  *-------------------------------------------------------------------------
                                431                 :                :  */
                                432                 :                : Datum
 2260 pg@bowt.ie                433                 :          54684 : btequalimage(PG_FUNCTION_ARGS)
                                434                 :                : {
                                435                 :                : #ifdef NOT_USED
                                436                 :                :     Oid         opcintype = PG_GETARG_OID(0);
                                437                 :                : #endif
                                438                 :                : 
                                439                 :          54684 :     PG_RETURN_BOOL(true);
                                440                 :                : }
                                441                 :                : 
                                442                 :                : /*-------------------------------------------------------------------------
                                443                 :                :  * datumEstimateSpace
                                444                 :                :  *
                                445                 :                :  * Compute the amount of space that datumSerialize will require for a
                                446                 :                :  * particular Datum.
                                447                 :                :  *-------------------------------------------------------------------------
                                448                 :                :  */
                                449                 :                : Size
 3872 rhaas@postgresql.org      450                 :            100 : datumEstimateSpace(Datum value, bool isnull, bool typByVal, int typLen)
                                451                 :                : {
 3617                           452                 :            100 :     Size        sz = sizeof(int);
                                453                 :                : 
 3872                           454         [ +  - ]:            100 :     if (!isnull)
                                455                 :                :     {
                                456                 :                :         /* no need to use add_size, can't overflow */
                                457         [ +  + ]:            100 :         if (typByVal)
                                458                 :             88 :             sz += sizeof(Datum);
 3192 tgl@sss.pgh.pa.us         459   [ +  -  +  + ]:             24 :         else if (typLen == -1 &&
                                460   [ +  +  +  - ]:             12 :                  VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(value)))
                                461                 :                :         {
                                462                 :                :             /* Expanded objects need to be flattened, see comment below */
                                463                 :              4 :             sz += EOH_get_flat_size(DatumGetEOHP(value));
                                464                 :                :         }
                                465                 :                :         else
 3872 rhaas@postgresql.org      466                 :              8 :             sz += datumGetSize(value, typByVal, typLen);
                                467                 :                :     }
                                468                 :                : 
                                469                 :            100 :     return sz;
                                470                 :                : }
                                471                 :                : 
                                472                 :                : /*-------------------------------------------------------------------------
                                473                 :                :  * datumSerialize
                                474                 :                :  *
                                475                 :                :  * Serialize a possibly-NULL datum into caller-provided storage.
                                476                 :                :  *
                                477                 :                :  * Note: "expanded" objects are flattened so as to produce a self-contained
                                478                 :                :  * representation, but other sorts of toast pointers are transferred as-is.
                                479                 :                :  * This is because the intended use of this function is to pass the value
                                480                 :                :  * to another process within the same database server.  The other process
                                481                 :                :  * could not access an "expanded" object within this process's memory, but
                                482                 :                :  * we assume it can dereference the same TOAST pointers this one can.
                                483                 :                :  *
                                484                 :                :  * The format is as follows: first, we write a 4-byte header word, which
                                485                 :                :  * is either the length of a pass-by-reference datum, -1 for a
                                486                 :                :  * pass-by-value datum, or -2 for a NULL.  If the value is NULL, nothing
                                487                 :                :  * further is written.  If it is pass-by-value, sizeof(Datum) bytes
                                488                 :                :  * follow.  Otherwise, the number of bytes indicated by the header word
                                489                 :                :  * follow.  The caller is responsible for ensuring that there is enough
                                490                 :                :  * storage to store the number of bytes that will be written; use
                                491                 :                :  * datumEstimateSpace() to find out how many will be needed.
                                492                 :                :  * *start_address is updated to point to the byte immediately following
                                493                 :                :  * those written.
                                494                 :                :  *-------------------------------------------------------------------------
                                495                 :                :  */
                                496                 :                : void
                                497                 :             76 : datumSerialize(Datum value, bool isnull, bool typByVal, int typLen,
                                498                 :                :                char **start_address)
                                499                 :                : {
 3837                           500                 :             76 :     ExpandedObjectHeader *eoh = NULL;
                                501                 :                :     int         header;
                                502                 :                : 
                                503                 :                :     /* Write header word. */
 3872                           504         [ -  + ]:             76 :     if (isnull)
 3872 rhaas@postgresql.org      505                 :UBC           0 :         header = -2;
 3872 rhaas@postgresql.org      506         [ +  + ]:CBC          76 :     else if (typByVal)
                                507                 :             64 :         header = -1;
 3192 tgl@sss.pgh.pa.us         508   [ +  -  +  + ]:             24 :     else if (typLen == -1 &&
                                509   [ +  +  +  - ]:             12 :              VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(value)))
                                510                 :                :     {
 3837 rhaas@postgresql.org      511                 :              4 :         eoh = DatumGetEOHP(value);
                                512                 :              4 :         header = EOH_get_flat_size(eoh);
                                513                 :                :     }
                                514                 :                :     else
 3872                           515                 :              8 :         header = datumGetSize(value, typByVal, typLen);
                                516                 :             76 :     memcpy(*start_address, &header, sizeof(int));
                                517                 :             76 :     *start_address += sizeof(int);
                                518                 :                : 
                                519                 :                :     /* If not null, write payload bytes. */
                                520         [ +  - ]:             76 :     if (!isnull)
                                521                 :                :     {
                                522         [ +  + ]:             76 :         if (typByVal)
                                523                 :                :         {
                                524                 :             64 :             memcpy(*start_address, &value, sizeof(Datum));
                                525                 :             64 :             *start_address += sizeof(Datum);
                                526                 :                :         }
 3837                           527         [ +  + ]:             12 :         else if (eoh)
                                528                 :                :         {
                                529                 :                :             char       *tmp;
                                530                 :                : 
                                531                 :                :             /*
                                532                 :                :              * EOH_flatten_into expects the target address to be maxaligned,
                                533                 :                :              * so we can't store directly to *start_address.
                                534                 :                :              */
 2771 akapila@postgresql.o      535                 :              4 :             tmp = (char *) palloc(header);
  523 peter@eisentraut.org      536                 :              4 :             EOH_flatten_into(eoh, tmp, header);
 2771 akapila@postgresql.o      537                 :              4 :             memcpy(*start_address, tmp, header);
 3837 rhaas@postgresql.org      538                 :              4 :             *start_address += header;
                                539                 :                : 
                                540                 :                :             /* be tidy. */
 2771 akapila@postgresql.o      541                 :              4 :             pfree(tmp);
                                542                 :                :         }
                                543                 :                :         else
                                544                 :                :         {
 3872 rhaas@postgresql.org      545                 :              8 :             memcpy(*start_address, DatumGetPointer(value), header);
                                546                 :              8 :             *start_address += header;
                                547                 :                :         }
                                548                 :                :     }
                                549                 :             76 : }
                                550                 :                : 
                                551                 :                : /*-------------------------------------------------------------------------
                                552                 :                :  * datumRestore
                                553                 :                :  *
                                554                 :                :  * Restore a possibly-NULL datum previously serialized by datumSerialize.
                                555                 :                :  * *start_address is updated according to the number of bytes consumed.
                                556                 :                :  *-------------------------------------------------------------------------
                                557                 :                :  */
                                558                 :                : Datum
                                559                 :            184 : datumRestore(char **start_address, bool *isnull)
                                560                 :                : {
                                561                 :                :     int         header;
                                562                 :                :     void       *d;
                                563                 :                : 
                                564                 :                :     /* Read header word. */
                                565                 :            184 :     memcpy(&header, *start_address, sizeof(int));
                                566                 :            184 :     *start_address += sizeof(int);
                                567                 :                : 
                                568                 :                :     /* If this datum is NULL, we can stop here. */
                                569         [ -  + ]:            184 :     if (header == -2)
                                570                 :                :     {
 3872 rhaas@postgresql.org      571                 :UBC           0 :         *isnull = true;
                                572                 :              0 :         return (Datum) 0;
                                573                 :                :     }
                                574                 :                : 
                                575                 :                :     /* OK, datum is not null. */
 3872 rhaas@postgresql.org      576                 :CBC         184 :     *isnull = false;
                                577                 :                : 
                                578                 :                :     /* If this datum is pass-by-value, sizeof(Datum) bytes follow. */
                                579         [ +  + ]:            184 :     if (header == -1)
                                580                 :                :     {
                                581                 :                :         Datum       val;
                                582                 :                : 
                                583                 :            144 :         memcpy(&val, *start_address, sizeof(Datum));
                                584                 :            144 :         *start_address += sizeof(Datum);
                                585                 :            144 :         return val;
                                586                 :                :     }
                                587                 :                : 
                                588                 :                :     /* Pass-by-reference case; copy indicated number of bytes. */
                                589         [ -  + ]:             40 :     Assert(header > 0);
                                590                 :             40 :     d = palloc(header);
                                591                 :             40 :     memcpy(d, *start_address, header);
                                592                 :             40 :     *start_address += header;
                                593                 :             40 :     return PointerGetDatum(d);
                                594                 :                : }
        

Generated by: LCOV version 2.5.0-beta