PostgreSQL Source Code  git master
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 
72 static 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 
107 static A_Const *
108 _copyA_Const(const A_Const *from)
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 
146 static 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 
163 static 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  */
176 void *
177 copyObjectImpl(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
#define COPY_LOCATION_FIELD(fldname)
Definition: copyfuncs.c:61
#define COPY_STRING_FIELD(fldname)
Definition: copyfuncs.c:42
void * copyObjectImpl(const void *from)
Definition: copyfuncs.c:177
static A_Const * _copyA_Const(const A_Const *from)
Definition: copyfuncs.c:108
static ExtensibleNode * _copyExtensibleNode(const ExtensibleNode *from)
Definition: copyfuncs.c:147
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:224
const ExtensibleNodeMethods * GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
Definition: extensible.c:125
long val
Definition: informix.c:670
List * list_copy_deep(const List *oldlist)
Definition: list.c:1639
List * list_copy(const List *oldlist)
Definition: list.c:1573
static Node * newNode(size_t size, NodeTag tag)
Definition: nodes.h:144
#define nodeTag(nodeptr)
Definition: nodes.h:133
#define makeNode(_type_)
Definition: nodes.h:155
void check_stack_depth(void)
Definition: postgres.c:3531
bool isnull
Definition: parsenodes.h:363
union ValUnion val
Definition: parsenodes.h:362
void(* nodeCopy)(struct ExtensibleNode *newnode, const struct ExtensibleNode *oldnode)
Definition: extensible.h:66
const char * extnodename
Definition: extensible.h:37