Age Owner Branch data TLA 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 *
3258 tgl@sss.pgh.pa.us 29 :CBC 50442 : DatumGetEOHP(Datum d)
30 : : {
31 : 50442 : varattrib_1b_e *datum = (varattrib_1b_e *) DatumGetPointer(d);
32 : : varatt_expanded ptr;
33 : :
34 [ + - - + ]: 50442 : Assert(VARATT_IS_EXTERNAL_EXPANDED(datum));
35 : 50442 : memcpy(&ptr, VARDATA_EXTERNAL(datum), sizeof(ptr));
36 [ - + ]: 50442 : Assert(VARATT_IS_EXPANDED_HEADER(ptr.eohptr));
37 : 50442 : 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 : 26576 : EOH_init_header(ExpandedObjectHeader *eohptr,
49 : : const ExpandedObjectMethods *methods,
50 : : MemoryContext obj_context)
51 : : {
52 : : varatt_expanded ptr;
53 : :
54 : 26576 : eohptr->vl_len_ = EOH_HEADER_MAGIC;
55 : 26576 : eohptr->eoh_methods = methods;
56 : 26576 : eohptr->eoh_context = obj_context;
57 : :
58 : 26576 : ptr.eohptr = eohptr;
59 : :
60 : 26576 : SET_VARTAG_EXTERNAL(eohptr->eoh_rw_ptr, VARTAG_EXPANDED_RW);
61 : 26576 : memcpy(VARDATA_EXTERNAL(eohptr->eoh_rw_ptr), &ptr, sizeof(ptr));
62 : :
63 : 26576 : SET_VARTAG_EXTERNAL(eohptr->eoh_ro_ptr, VARTAG_EXPANDED_RO);
64 : 26576 : memcpy(VARDATA_EXTERNAL(eohptr->eoh_ro_ptr), &ptr, sizeof(ptr));
65 : 26576 : }
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 : 7439 : EOH_get_flat_size(ExpandedObjectHeader *eohptr)
76 : : {
2411 peter_e@gmx.net 77 : 7439 : return eohptr->eoh_methods->get_flat_size(eohptr);
78 : : }
79 : :
80 : : void
3258 tgl@sss.pgh.pa.us 81 : 5954 : EOH_flatten_into(ExpandedObjectHeader *eohptr,
82 : : void *result, Size allocated_size)
83 : : {
2411 peter_e@gmx.net 84 : 5954 : eohptr->eoh_methods->flatten_into(eohptr, result, allocated_size);
3258 tgl@sss.pgh.pa.us 85 : 5954 : }
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
2872 95 : 4134602 : MakeExpandedObjectReadOnlyInternal(Datum d)
96 : : {
97 : : ExpandedObjectHeader *eohptr;
98 : :
99 : : /* Nothing to do if not a read-write expanded-object pointer */
3258 100 [ + + + + ]: 4134602 : if (!VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)))
101 : 4119129 : return d;
102 : :
103 : : /* Now safe to extract the object pointer */
104 : 15473 : eohptr = DatumGetEOHP(d);
105 : :
106 : : /* Return the built-in read-only pointer instead of given pointer */
107 : 15473 : 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 : 1871 : TransferExpandedObject(Datum d, MemoryContext new_parent)
119 : : {
120 : 1871 : ExpandedObjectHeader *eohptr = DatumGetEOHP(d);
121 : :
122 : : /* Assert caller gave a R/W pointer */
123 [ + - - + ]: 1871 : Assert(VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)));
124 : :
125 : : /* Transfer ownership */
126 : 1871 : MemoryContextSetParent(eohptr->eoh_context, new_parent);
127 : :
128 : : /* Return the object's standard read-write pointer */
129 : 1871 : return EOHPGetRWDatum(eohptr);
130 : : }
131 : :
132 : : /*
133 : : * Delete an expanded object (must be referenced by a R/W pointer).
134 : : */
135 : : void
136 : 4505 : DeleteExpandedObject(Datum d)
137 : : {
138 : 4505 : ExpandedObjectHeader *eohptr = DatumGetEOHP(d);
139 : :
140 : : /* Assert caller gave a R/W pointer */
141 [ + - - + ]: 4505 : Assert(VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)));
142 : :
143 : : /* Kill it */
144 : 4505 : MemoryContextDelete(eohptr->eoh_context);
145 : 4505 : }
|