Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * expandeddatum.c 4 : * Support functions for "expanded" value representations. 5 : * 6 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group 7 : * Portions Copyright (c) 1994, Regents of the University of California 8 : * 9 : * 10 : * IDENTIFICATION 11 : * src/backend/utils/adt/expandeddatum.c 12 : * 13 : *------------------------------------------------------------------------- 14 : */ 15 : #include "postgres.h" 16 : 17 : #include "utils/expandeddatum.h" 18 : #include "utils/memutils.h" 19 : 20 : /* 21 : * DatumGetEOHP 22 : * 23 : * Given a Datum that is an expanded-object reference, extract the pointer. 24 : * 25 : * This is a bit tedious since the pointer may not be properly aligned; 26 : * compare VARATT_EXTERNAL_GET_POINTER(). 27 : */ 28 : ExpandedObjectHeader * 29 101404 : DatumGetEOHP(Datum d) 30 : { 31 101404 : varattrib_1b_e *datum = (varattrib_1b_e *) DatumGetPointer(d); 32 : varatt_expanded ptr; 33 : 34 : Assert(VARATT_IS_EXTERNAL_EXPANDED(datum)); 35 101404 : memcpy(&ptr, VARDATA_EXTERNAL(datum), sizeof(ptr)); 36 : Assert(VARATT_IS_EXPANDED_HEADER(ptr.eohptr)); 37 101404 : return ptr.eohptr; 38 : } 39 : 40 : /* 41 : * EOH_init_header 42 : * 43 : * Initialize the common header of an expanded object. 44 : * 45 : * The main thing this encapsulates is initializing the TOAST pointers. 46 : */ 47 : void 48 53156 : EOH_init_header(ExpandedObjectHeader *eohptr, 49 : const ExpandedObjectMethods *methods, 50 : MemoryContext obj_context) 51 : { 52 : varatt_expanded ptr; 53 : 54 53156 : eohptr->vl_len_ = EOH_HEADER_MAGIC; 55 53156 : eohptr->eoh_methods = methods; 56 53156 : eohptr->eoh_context = obj_context; 57 : 58 53156 : ptr.eohptr = eohptr; 59 : 60 53156 : SET_VARTAG_EXTERNAL(eohptr->eoh_rw_ptr, VARTAG_EXPANDED_RW); 61 53156 : memcpy(VARDATA_EXTERNAL(eohptr->eoh_rw_ptr), &ptr, sizeof(ptr)); 62 : 63 53156 : SET_VARTAG_EXTERNAL(eohptr->eoh_ro_ptr, VARTAG_EXPANDED_RO); 64 53156 : memcpy(VARDATA_EXTERNAL(eohptr->eoh_ro_ptr), &ptr, sizeof(ptr)); 65 53156 : } 66 : 67 : /* 68 : * EOH_get_flat_size 69 : * EOH_flatten_into 70 : * 71 : * Convenience functions for invoking the "methods" of an expanded object. 72 : */ 73 : 74 : Size 75 15004 : EOH_get_flat_size(ExpandedObjectHeader *eohptr) 76 : { 77 15004 : return eohptr->eoh_methods->get_flat_size(eohptr); 78 : } 79 : 80 : void 81 12032 : EOH_flatten_into(ExpandedObjectHeader *eohptr, 82 : void *result, Size allocated_size) 83 : { 84 12032 : eohptr->eoh_methods->flatten_into(eohptr, result, allocated_size); 85 12032 : } 86 : 87 : /* 88 : * If the Datum represents a R/W expanded object, change it to R/O. 89 : * Otherwise return the original Datum. 90 : * 91 : * Caller must ensure that the datum is a non-null varlena value. Typically 92 : * this is invoked via MakeExpandedObjectReadOnly(), which checks that. 93 : */ 94 : Datum 95 8361702 : MakeExpandedObjectReadOnlyInternal(Datum d) 96 : { 97 : ExpandedObjectHeader *eohptr; 98 : 99 : /* Nothing to do if not a read-write expanded-object pointer */ 100 8361702 : if (!VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d))) 101 8330564 : return d; 102 : 103 : /* Now safe to extract the object pointer */ 104 31138 : eohptr = DatumGetEOHP(d); 105 : 106 : /* Return the built-in read-only pointer instead of given pointer */ 107 31138 : return EOHPGetRODatum(eohptr); 108 : } 109 : 110 : /* 111 : * Transfer ownership of an expanded object to a new parent memory context. 112 : * The object must be referenced by a R/W pointer, and what we return is 113 : * always its "standard" R/W pointer, which is certain to have the same 114 : * lifespan as the object itself. (The passed-in pointer might not, and 115 : * in any case wouldn't provide a unique identifier if it's not that one.) 116 : */ 117 : Datum 118 3744 : TransferExpandedObject(Datum d, MemoryContext new_parent) 119 : { 120 3744 : ExpandedObjectHeader *eohptr = DatumGetEOHP(d); 121 : 122 : /* Assert caller gave a R/W pointer */ 123 : Assert(VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d))); 124 : 125 : /* Transfer ownership */ 126 3744 : MemoryContextSetParent(eohptr->eoh_context, new_parent); 127 : 128 : /* Return the object's standard read-write pointer */ 129 3744 : return EOHPGetRWDatum(eohptr); 130 : } 131 : 132 : /* 133 : * Delete an expanded object (must be referenced by a R/W pointer). 134 : */ 135 : void 136 9134 : DeleteExpandedObject(Datum d) 137 : { 138 9134 : ExpandedObjectHeader *eohptr = DatumGetEOHP(d); 139 : 140 : /* Assert caller gave a R/W pointer */ 141 : Assert(VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d))); 142 : 143 : /* Kill it */ 144 9134 : MemoryContextDelete(eohptr->eoh_context); 145 9134 : }