Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * copyfuncs.c
4 : * Copy functions for Postgres tree nodes.
5 : *
6 : *
7 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : * IDENTIFICATION
11 : * src/backend/nodes/copyfuncs.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 :
16 : #include "postgres.h"
17 :
18 : #include "miscadmin.h"
19 : #include "utils/datum.h"
20 :
21 :
22 : /*
23 : * Macros to simplify copying of different kinds of fields. Use these
24 : * wherever possible to reduce the chance for silly typos. Note that these
25 : * hard-wire the convention that the local variables in a Copy routine are
26 : * named 'newnode' and 'from'.
27 : */
28 :
29 : /* Copy a simple scalar field (int, float, bool, enum, etc) */
30 : #define COPY_SCALAR_FIELD(fldname) \
31 : (newnode->fldname = from->fldname)
32 :
33 : /* Copy a field that is a pointer to some kind of Node or Node tree */
34 : #define COPY_NODE_FIELD(fldname) \
35 : (newnode->fldname = copyObjectImpl(from->fldname))
36 :
37 : /* Copy a field that is a pointer to a Bitmapset */
38 : #define COPY_BITMAPSET_FIELD(fldname) \
39 : (newnode->fldname = bms_copy(from->fldname))
40 :
41 : /* Copy a field that is a pointer to a C string, or perhaps NULL */
42 : #define COPY_STRING_FIELD(fldname) \
43 : (newnode->fldname = from->fldname ? pstrdup(from->fldname) : (char *) NULL)
44 :
45 : /* Copy a field that is an inline array */
46 : #define COPY_ARRAY_FIELD(fldname) \
47 : memcpy(newnode->fldname, from->fldname, sizeof(newnode->fldname))
48 :
49 : /* Copy a field that is a pointer to a simple palloc'd object of size sz */
50 : #define COPY_POINTER_FIELD(fldname, sz) \
51 : do { \
52 : Size _size = (sz); \
53 : if (_size > 0) \
54 : { \
55 : newnode->fldname = palloc(_size); \
56 : memcpy(newnode->fldname, from->fldname, _size); \
57 : } \
58 : } while (0)
59 :
60 : /* Copy a parse location field (for Copy, this is same as scalar case) */
61 : #define COPY_LOCATION_FIELD(fldname) \
5337 tgl 62 ECB : (newnode->fldname = from->fldname)
63 :
9770 scrappy 64 :
65 : #include "copyfuncs.funcs.c"
66 :
67 :
4560 tgl 68 EUB : /*
69 : * Support functions for nodes with custom_copy_equal attribute
70 : */
71 :
72 : static Const *
274 peter 73 GIC 414564 : _copyConst(const Const *from)
74 : {
75 414564 : Const *newnode = makeNode(Const);
76 :
77 414564 : COPY_SCALAR_FIELD(consttype);
78 414564 : COPY_SCALAR_FIELD(consttypmod);
79 414564 : COPY_SCALAR_FIELD(constcollid);
80 414564 : COPY_SCALAR_FIELD(constlen);
81 :
82 414564 : if (from->constbyval || from->constisnull)
83 : {
84 : /*
85 : * passed by value so just copy the datum. Also, don't try to copy
86 : * struct when value is null!
87 : */
88 310774 : newnode->constvalue = from->constvalue;
89 : }
90 : else
91 : {
92 : /*
93 : * passed by reference. We need a palloc'd copy.
94 : */
95 103790 : newnode->constvalue = datumCopy(from->constvalue,
96 103790 : from->constbyval,
97 103790 : from->constlen);
98 : }
99 :
100 414564 : COPY_SCALAR_FIELD(constisnull);
101 414564 : COPY_SCALAR_FIELD(constbyval);
102 414564 : COPY_LOCATION_FIELD(location);
103 :
6564 tgl 104 414564 : return newnode;
105 : }
106 :
107 : static A_Const *
274 peter 108 48721 : _copyA_Const(const A_Const *from)
109 : {
110 48721 : A_Const *newnode = makeNode(A_Const);
111 :
112 48721 : COPY_SCALAR_FIELD(isnull);
113 48721 : if (!from->isnull)
114 : {
115 : /* This part must duplicate other _copy*() functions. */
116 47527 : COPY_SCALAR_FIELD(val.node.type);
117 47527 : switch (nodeTag(&from->val))
118 : {
119 25884 : case T_Integer:
120 25884 : COPY_SCALAR_FIELD(val.ival.ival);
121 25884 : break;
122 120 : case T_Float:
123 120 : COPY_STRING_FIELD(val.fval.fval);
124 120 : break;
125 972 : case T_Boolean:
126 972 : COPY_SCALAR_FIELD(val.boolval.boolval);
127 972 : break;
128 20551 : case T_String:
129 20551 : COPY_STRING_FIELD(val.sval.sval);
130 20551 : break;
274 peter 131 UIC 0 : case T_BitString:
132 0 : COPY_STRING_FIELD(val.bsval.bsval);
133 0 : break;
134 0 : default:
135 0 : elog(ERROR, "unrecognized node type: %d",
136 : (int) nodeTag(&from->val));
137 : break;
138 : }
139 : }
140 :
274 peter 141 GIC 48721 : COPY_LOCATION_FIELD(location);
142 :
6564 tgl 143 48721 : return newnode;
144 : }
145 :
146 : static ExtensibleNode *
274 peter 147 UIC 0 : _copyExtensibleNode(const ExtensibleNode *from)
148 : {
149 : ExtensibleNode *newnode;
150 : const ExtensibleNodeMethods *methods;
151 :
152 0 : methods = GetExtensibleNodeMethods(from->extnodename, false);
153 0 : newnode = (ExtensibleNode *) newNode(methods->node_size,
154 : T_ExtensibleNode);
155 0 : COPY_STRING_FIELD(extnodename);
156 :
157 : /* copy the private fields */
158 0 : methods->nodeCopy(newnode, from);
159 :
2748 rhaas 160 0 : return newnode;
161 : }
162 :
163 : static Bitmapset *
147 tgl 164 UNC 0 : _copyBitmapset(const Bitmapset *from)
165 : {
166 0 : return bms_copy(from);
167 : }
168 :
169 :
170 : /*
171 : * copyObjectImpl -- implementation of copyObject(); see nodes/nodes.h
172 : *
173 : * Create a copy of a Node tree or list. This is a "deep" copy: all
174 : * substructure is copied too, recursively.
175 : */
176 : void *
274 peter 177 GIC 18199778 : copyObjectImpl(const void *from)
178 : {
179 : void *retval;
180 :
181 18199778 : if (from == NULL)
182 7376442 : return NULL;
183 :
184 : /* Guard against stack overflow due to overly complex expressions */
185 10823336 : check_stack_depth();
186 :
187 10823336 : switch (nodeTag(from))
188 : {
189 : #include "copyfuncs.switch.c"
190 :
191 1807950 : case T_List:
192 1807950 : retval = list_copy_deep(from);
193 1807950 : break;
194 :
195 : /*
196 : * Lists of integers, OIDs and XIDs don't need to be deep-copied,
197 : * so we perform a shallow copy via list_copy()
198 : */
6892 neilc 199 117748 : case T_IntList:
200 : case T_OidList:
201 : case T_XidList:
202 117748 : retval = list_copy(from);
8483 tgl 203 117748 : break;
204 :
9344 bruce 205 UIC 0 : default:
7201 tgl 206 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(from));
207 : retval = 0; /* keep compiler quiet */
208 : break;
209 : }
210 :
9345 bruce 211 GIC 10823336 : return retval;
212 : }
|