index f2568ff5e6..8233c9b7d3 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -40,7 +40,10 @@ /* Copy a field that is a pointer to a C string, or perhaps NULL */ #define COPY_STRING_FIELD(fldname) \ - (newnode->fldname = from->fldname ? pstrdup(from->fldname) : (char *) NULL) + do { \ + if (from->fldname) \ + newnode->fldname = pstrdup(from->fldname); \ + } while (0) /* Copy a field that is an inline array */ #define COPY_ARRAY_FIELD(fldname) \ @@ -49,11 +52,10 @@ /* Copy a field that is a pointer to a simple palloc'd object of size sz */ #define COPY_POINTER_FIELD(fldname, sz) \ do { \ - Size _size = (sz); \ - if (_size > 0) \ + if (from->fldname && (sz) > 0) \ { \ - newnode->fldname = palloc(_size); \ - memcpy(newnode->fldname, from->fldname, _size); \ + newnode->fldname = palloc((sz)); \ + memcpy(newnode->fldname, from->fldname, (sz)); \ } \ } while (0) @@ -74,10 +76,7 @@ _copyConst(const Const *from) { Const *newnode = makeNode(Const); - COPY_SCALAR_FIELD(consttype); - COPY_SCALAR_FIELD(consttypmod); - COPY_SCALAR_FIELD(constcollid); - COPY_SCALAR_FIELD(constlen); + memcpy(newnode, from, sizeof(*from)); if (from->constbyval || from->constisnull) { @@ -97,10 +96,6 @@ _copyConst(const Const *from) from->constlen); } - COPY_SCALAR_FIELD(constisnull); - COPY_SCALAR_FIELD(constbyval); - COPY_LOCATION_FIELD(location); - return newnode; } @@ -109,7 +104,8 @@ _copyA_Const(const A_Const *from) { A_Const *newnode = makeNode(A_Const); - COPY_SCALAR_FIELD(isnull); + memcpy(newnode, from, sizeof(*from)); + if (!from->isnull) { /* This part must duplicate other _copy*() functions. */ @@ -138,8 +134,6 @@ _copyA_Const(const A_Const *from) } } - COPY_LOCATION_FIELD(location); - return newnode; } diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl index b3c1ead496..39560fbd0e 100644 --- a/src/backend/nodes/gen_node_support.pl +++ b/src/backend/nodes/gen_node_support.pl @@ -680,6 +680,7 @@ static bool _equal${n}(const $n *a, const $n *b) { " unless $struct_no_equal; + my $memcpy_ignore = 0; # track already-processed fields to support field order checks my %previous_fields; @@ -725,8 +726,14 @@ _equal${n}(const $n *a, const $n *b) } } + if (!$memcpy_ignore && $node_type_info{$n}->{fields} > 2) + { + print $cff "\tmemcpy(newnode, from, sizeof(*from));\n" unless $copy_ignore; + $memcpy_ignore = 1; + } + # override type-specific copy method if requested - if (defined $copy_as_field) + if (defined $copy_as_field && !$memcpy_ignore) { print $cff "\tnewnode->$f = $copy_as_field;\n" unless $copy_ignore; @@ -735,7 +742,7 @@ _equal${n}(const $n *a, const $n *b) elsif ($copy_as_scalar) { print $cff "\tCOPY_SCALAR_FIELD($f);\n" - unless $copy_ignore; + unless $copy_ignore || $memcpy_ignore; $copy_ignore = 1; } @@ -761,12 +768,12 @@ _equal${n}(const $n *a, const $n *b) } elsif ($t eq 'int' && $f =~ 'location$') { - print $cff "\tCOPY_LOCATION_FIELD($f);\n" unless $copy_ignore; + print $cff "\tCOPY_LOCATION_FIELD($f);\n" unless $copy_ignore || $memcpy_ignore; print $eff "\tCOMPARE_LOCATION_FIELD($f);\n" unless $equal_ignore; } elsif (elem $t, @scalar_types or elem $t, @enum_types) { - print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore; + print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore || $memcpy_ignore; if (elem 'equal_ignore_if_zero', @a) { print $eff @@ -810,7 +817,7 @@ _equal${n}(const $n *a, const $n *b) elsif ($t eq 'function pointer') { # we can copy and compare as a scalar - print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore; + print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore || $memcpy_ignore; print $eff "\tCOMPARE_SCALAR_FIELD($f);\n" unless $equal_ignore; } # node type @@ -834,7 +841,7 @@ _equal${n}(const $n *a, const $n *b) # array (inline) elsif ($t =~ /^\w+\[\w+\]$/) { - print $cff "\tCOPY_ARRAY_FIELD($f);\n" unless $copy_ignore; + print $cff "\tCOPY_ARRAY_FIELD($f);\n" unless $copy_ignore || $memcpy_ignore; print $eff "\tCOMPARE_ARRAY_FIELD($f);\n" unless $equal_ignore; } elsif ($t eq 'struct CustomPathMethods*' @@ -843,7 +850,7 @@ _equal${n}(const $n *a, const $n *b) # Fields of these types are required to be a pointer to a # static table of callback functions. So we don't copy # the table itself, just reference the original one. - print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore; + print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore || $memcpy_ignore; print $eff "\tCOMPARE_SCALAR_FIELD($f);\n" unless $equal_ignore; } else