PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
copyfuncs.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * copyfuncs.c
4 * Copy functions for Postgres tree nodes.
5 *
6 *
7 * Portions Copyright (c) 1996-2024, 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) \
62 (newnode->fldname = from->fldname)
63
64
65#include "copyfuncs.funcs.c"
66
67
68/*
69 * Support functions for nodes with custom_copy_equal attribute
70 */
71
72static Const *
73_copyConst(const Const *from)
74{
75 Const *newnode = makeNode(Const);
76
77 COPY_SCALAR_FIELD(consttype);
78 COPY_SCALAR_FIELD(consttypmod);
79 COPY_SCALAR_FIELD(constcollid);
80 COPY_SCALAR_FIELD(constlen);
81
82 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 newnode->constvalue = from->constvalue;
89 }
90 else
91 {
92 /*
93 * passed by reference. We need a palloc'd copy.
94 */
95 newnode->constvalue = datumCopy(from->constvalue,
96 from->constbyval,
97 from->constlen);
98 }
99
100 COPY_SCALAR_FIELD(constisnull);
101 COPY_SCALAR_FIELD(constbyval);
102 COPY_LOCATION_FIELD(location);
103
104 return newnode;
105}
106
107static A_Const *
109{
110 A_Const *newnode = makeNode(A_Const);
111
112 COPY_SCALAR_FIELD(isnull);
113 if (!from->isnull)
114 {
115 /* This part must duplicate other _copy*() functions. */
116 COPY_SCALAR_FIELD(val.node.type);
117 switch (nodeTag(&from->val))
118 {
119 case T_Integer:
120 COPY_SCALAR_FIELD(val.ival.ival);
121 break;
122 case T_Float:
123 COPY_STRING_FIELD(val.fval.fval);
124 break;
125 case T_Boolean:
126 COPY_SCALAR_FIELD(val.boolval.boolval);
127 break;
128 case T_String:
129 COPY_STRING_FIELD(val.sval.sval);
130 break;
131 case T_BitString:
132 COPY_STRING_FIELD(val.bsval.bsval);
133 break;
134 default:
135 elog(ERROR, "unrecognized node type: %d",
136 (int) nodeTag(&from->val));
137 break;
138 }
139 }
140
141 COPY_LOCATION_FIELD(location);
142
143 return newnode;
144}
145
146static ExtensibleNode *
148{
149 ExtensibleNode *newnode;
150 const ExtensibleNodeMethods *methods;
151
152 methods = GetExtensibleNodeMethods(from->extnodename, false);
153 newnode = (ExtensibleNode *) newNode(methods->node_size,
154 T_ExtensibleNode);
155 COPY_STRING_FIELD(extnodename);
156
157 /* copy the private fields */
158 methods->nodeCopy(newnode, from);
159
160 return newnode;
161}
162
163static Bitmapset *
165{
166 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 */
176void *
177copyObjectImpl(const void *from)
178{
179 void *retval;
180
181 if (from == NULL)
182 return NULL;
183
184 /* Guard against stack overflow due to overly complex expressions */
186
187 switch (nodeTag(from))
188 {
189#include "copyfuncs.switch.c"
190
191 case T_List:
192 retval = list_copy_deep(from);
193 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 */
199 case T_IntList:
200 case T_OidList:
201 case T_XidList:
202 retval = list_copy(from);
203 break;
204
205 default:
206 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(from));
207 retval = 0; /* keep compiler quiet */
208 break;
209 }
210
211 return retval;
212}
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:122
static Const * _copyConst(const Const *from)
Definition: copyfuncs.c:73
static ExtensibleNode * _copyExtensibleNode(const ExtensibleNode *from)
Definition: copyfuncs.c:147
#define COPY_LOCATION_FIELD(fldname)
Definition: copyfuncs.c:61
void * copyObjectImpl(const void *from)
Definition: copyfuncs.c:177
static A_Const * _copyA_Const(const A_Const *from)
Definition: copyfuncs.c:108
#define COPY_STRING_FIELD(fldname)
Definition: copyfuncs.c:42
static Bitmapset * _copyBitmapset(const Bitmapset *from)
Definition: copyfuncs.c:164
#define COPY_SCALAR_FIELD(fldname)
Definition: copyfuncs.c:30
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
const ExtensibleNodeMethods * GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
Definition: extensible.c:125
long val
Definition: informix.c:689
List * list_copy_deep(const List *oldlist)
Definition: list.c:1639
List * list_copy(const List *oldlist)
Definition: list.c:1573
#define nodeTag(nodeptr)
Definition: nodes.h:133
static Node * newNode(size_t size, NodeTag tag)
Definition: nodes.h:144
#define makeNode(_type_)
Definition: nodes.h:155
void check_stack_depth(void)
Definition: stack_depth.c:95
bool isnull
Definition: parsenodes.h:365
union ValUnion val
Definition: parsenodes.h:364
void(* nodeCopy)(struct ExtensibleNode *newnode, const struct ExtensibleNode *oldnode)
Definition: extensible.h:66
const char * extnodename
Definition: extensible.h:37