Line data Source code
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 3097858 : _copyConst(const Const *from) 74 : { 75 3097858 : Const *newnode = makeNode(Const); 76 : 77 3097858 : COPY_SCALAR_FIELD(consttype); 78 3097858 : COPY_SCALAR_FIELD(consttypmod); 79 3097858 : COPY_SCALAR_FIELD(constcollid); 80 3097858 : COPY_SCALAR_FIELD(constlen); 81 : 82 3097858 : 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 2196862 : newnode->constvalue = from->constvalue; 89 : } 90 : else 91 : { 92 : /* 93 : * passed by reference. We need a palloc'd copy. 94 : */ 95 900996 : newnode->constvalue = datumCopy(from->constvalue, 96 900996 : from->constbyval, 97 : from->constlen); 98 : } 99 : 100 3097858 : COPY_SCALAR_FIELD(constisnull); 101 3097858 : COPY_SCALAR_FIELD(constbyval); 102 3097858 : COPY_LOCATION_FIELD(location); 103 : 104 3097858 : return newnode; 105 : } 106 : 107 : static A_Const * 108 1462982 : _copyA_Const(const A_Const *from) 109 : { 110 1462982 : A_Const *newnode = makeNode(A_Const); 111 : 112 1462982 : COPY_SCALAR_FIELD(isnull); 113 1462982 : if (!from->isnull) 114 : { 115 : /* This part must duplicate other _copy*() functions. */ 116 1381362 : COPY_SCALAR_FIELD(val.node.type); 117 1381362 : switch (nodeTag(&from->val)) 118 : { 119 544336 : case T_Integer: 120 544336 : COPY_SCALAR_FIELD(val.ival.ival); 121 544336 : break; 122 12396 : case T_Float: 123 12396 : COPY_STRING_FIELD(val.fval.fval); 124 12396 : break; 125 62614 : case T_Boolean: 126 62614 : COPY_SCALAR_FIELD(val.boolval.boolval); 127 62614 : break; 128 757948 : case T_String: 129 757948 : COPY_STRING_FIELD(val.sval.sval); 130 757948 : break; 131 4068 : case T_BitString: 132 4068 : COPY_STRING_FIELD(val.bsval.bsval); 133 4068 : break; 134 0 : default: 135 0 : elog(ERROR, "unrecognized node type: %d", 136 : (int) nodeTag(&from->val)); 137 : break; 138 : } 139 81620 : } 140 : 141 1462982 : COPY_LOCATION_FIELD(location); 142 : 143 1462982 : return newnode; 144 : } 145 : 146 : static ExtensibleNode * 147 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 : 160 0 : return newnode; 161 : } 162 : 163 : static Bitmapset * 164 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 * 177 185673462 : copyObjectImpl(const void *from) 178 : { 179 : void *retval; 180 : 181 185673462 : if (from == NULL) 182 82196630 : return NULL; 183 : 184 : /* Guard against stack overflow due to overly complex expressions */ 185 103476832 : check_stack_depth(); 186 : 187 103476832 : switch (nodeTag(from)) 188 : { 189 : #include "copyfuncs.switch.c" 190 : 191 19531934 : case T_List: 192 19531934 : retval = list_copy_deep(from); 193 19531934 : 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 1387284 : case T_IntList: 200 : case T_OidList: 201 : case T_XidList: 202 1387284 : retval = list_copy(from); 203 1387284 : break; 204 : 205 0 : default: 206 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(from)); 207 : retval = 0; /* keep compiler quiet */ 208 : break; 209 : } 210 : 211 103476832 : return retval; 212 : }