Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * expandeddatum.c
4 : * Support functions for "expanded" value representations.
5 : *
6 : * Portions Copyright (c) 1996-2017, 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 5645 : DatumGetEOHP(Datum d)
30 : {
31 5645 : varattrib_1b_e *datum = (varattrib_1b_e *) DatumGetPointer(d);
32 : varatt_expanded ptr;
33 :
34 5645 : Assert(VARATT_IS_EXTERNAL_EXPANDED(datum));
35 5645 : memcpy(&ptr, VARDATA_EXTERNAL(datum), sizeof(ptr));
36 5645 : Assert(VARATT_IS_EXPANDED_HEADER(ptr.eohptr));
37 5645 : 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 1081 : EOH_init_header(ExpandedObjectHeader *eohptr,
49 : const ExpandedObjectMethods *methods,
50 : MemoryContext obj_context)
51 : {
52 : varatt_expanded ptr;
53 :
54 1081 : eohptr->vl_len_ = EOH_HEADER_MAGIC;
55 1081 : eohptr->eoh_methods = methods;
56 1081 : eohptr->eoh_context = obj_context;
57 :
58 1081 : ptr.eohptr = eohptr;
59 :
60 1081 : SET_VARTAG_EXTERNAL(eohptr->eoh_rw_ptr, VARTAG_EXPANDED_RW);
61 1081 : memcpy(VARDATA_EXTERNAL(eohptr->eoh_rw_ptr), &ptr, sizeof(ptr));
62 :
63 1081 : SET_VARTAG_EXTERNAL(eohptr->eoh_ro_ptr, VARTAG_EXPANDED_RO);
64 1081 : memcpy(VARDATA_EXTERNAL(eohptr->eoh_ro_ptr), &ptr, sizeof(ptr));
65 1081 : }
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 1187 : EOH_get_flat_size(ExpandedObjectHeader *eohptr)
76 : {
77 1187 : return (*eohptr->eoh_methods->get_flat_size) (eohptr);
78 : }
79 :
80 : void
81 802 : EOH_flatten_into(ExpandedObjectHeader *eohptr,
82 : void *result, Size allocated_size)
83 : {
84 802 : (*eohptr->eoh_methods->flatten_into) (eohptr, result, allocated_size);
85 802 : }
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 636072 : MakeExpandedObjectReadOnlyInternal(Datum d)
96 : {
97 : ExpandedObjectHeader *eohptr;
98 :
99 : /* Nothing to do if not a read-write expanded-object pointer */
100 636072 : if (!VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)))
101 634969 : return d;
102 :
103 : /* Now safe to extract the object pointer */
104 1103 : eohptr = DatumGetEOHP(d);
105 :
106 : /* Return the built-in read-only pointer instead of given pointer */
107 1103 : 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 18 : TransferExpandedObject(Datum d, MemoryContext new_parent)
119 : {
120 18 : ExpandedObjectHeader *eohptr = DatumGetEOHP(d);
121 :
122 : /* Assert caller gave a R/W pointer */
123 18 : Assert(VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)));
124 :
125 : /* Transfer ownership */
126 18 : MemoryContextSetParent(eohptr->eoh_context, new_parent);
127 :
128 : /* Return the object's standard read-write pointer */
129 18 : return EOHPGetRWDatum(eohptr);
130 : }
131 :
132 : /*
133 : * Delete an expanded object (must be referenced by a R/W pointer).
134 : */
135 : void
136 785 : DeleteExpandedObject(Datum d)
137 : {
138 785 : ExpandedObjectHeader *eohptr = DatumGetEOHP(d);
139 :
140 : /* Assert caller gave a R/W pointer */
141 785 : Assert(VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)));
142 :
143 : /* Kill it */
144 785 : MemoryContextDelete(eohptr->eoh_context);
145 785 : }
|