/*------------------------------------------------------------------------- * datumTransfer * * Transfer a non-NULL datum into the current memory context. * * This is equivalent to datumCopy() except when the datum is a read-write * pointer to an expanded object. In that case we merely reparent the object * into the current context, and return its standard R/W pointer (in case the * given one is a transient pointer of shorter lifespan). *------------------------------------------------------------------------- */ Datum datumTransfer(Datum value, bool typByVal, int typLen) { if (!typByVal && typLen == -1 && VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(value))) value = TransferExpandedObject(value, CurrentMemoryContext); else value = datumCopy(value, typByVal, typLen); return value; }
/* * Delete an expanded object (must be referenced by a R/W pointer). */ void DeleteExpandedObject(Datum d) { ExpandedObjectHeader *eohptr = DatumGetEOHP(d); /* Assert caller gave a R/W pointer */ Assert(VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d))); /* Kill it */ MemoryContextDelete(eohptr->eoh_context); }
/* * Does the Datum represent a writable expanded object? */ bool DatumIsReadWriteExpandedObject(Datum d, bool isnull, int16 typlen) { /* Reject if it's NULL or not a varlena type */ if (isnull || typlen != -1) return false; /* Reject if not a read-write expanded-object pointer */ if (!VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d))) return false; return true; }
/* * Transfer ownership of an expanded object to a new___ parent memory context. * The object must be referenced by a R/W pointer, and what we return is * always its "standard" R/W pointer, which is certain to have the same * lifespan as the object itself. (The passed-in pointer might not, and * in any case wouldn't provide a unique identifier if it's not that one.) */ Datum TransferExpandedObject(Datum d, MemoryContext new_parent) { ExpandedObjectHeader *eohptr = DatumGetEOHP(d); /* Assert caller gave a R/W pointer */ Assert(VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d))); /* Transfer ownership */ MemoryContextSetParent(eohptr->eoh_context, new_parent); /* Return the object's standard read-write pointer */ return EOHPGetRWDatum(eohptr); }
/* * DatumGetExpandedArray: get a writable expanded array from an input argument * * Caution: if the input is a read/write pointer, this returns the input * argument; so callers must be sure that their changes are "safe", that is * they cannot leave the array in a corrupt state. */ ExpandedArrayHeader * DatumGetExpandedArray(Datum d) { /* If it's a writable expanded array already, just return it */ if (VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d))) { ExpandedArrayHeader *eah = (ExpandedArrayHeader *) DatumGetEOHP(d); Assert(eah->ea_magic == EA_MAGIC); return eah; } /* Else expand the hard way */ d = expand_array(d, CurrentMemoryContext, NULL); return (ExpandedArrayHeader *) DatumGetEOHP(d); }
/* * If the Datum represents a R/W expanded object, change it to R/O. * Otherwise return the original Datum. */ Datum MakeExpandedObjectReadOnly(Datum d, bool isnull, int16 typlen) { ExpandedObjectHeader *eohptr; /* Nothing to do if it's NULL or not a varlena type */ if (isnull || typlen != -1) return d; /* Nothing to do if not a read-write expanded-object pointer */ if (!VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d))) return d; /* Now safe to extract the object pointer */ eohptr = DatumGetEOHP(d); /* Return the built-in read-only pointer instead of given pointer */ return EOHPGetRODatum(eohptr); }
/* * As above, when caller has the ability to cache element type info */ ExpandedArrayHeader * DatumGetExpandedArrayX(Datum d, ArrayMetaState *metacache) { /* If it's a writable expanded array already, just return it */ if (VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d))) { ExpandedArrayHeader *eah = (ExpandedArrayHeader *) DatumGetEOHP(d); Assert(eah->ea_magic == EA_MAGIC); /* Update cache if provided */ if (metacache) { metacache->element_type = eah->element_type; metacache->typlen = eah->typlen; metacache->typbyval = eah->typbyval; metacache->typalign = eah->typalign; } return eah; } /* Else expand using caller's cache if any */ d = expand_array(d, CurrentMemoryContext, metacache); return (ExpandedArrayHeader *) DatumGetEOHP(d); }