diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 84f5e2e6ad..962baa40ce 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 ((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; } @@ -176,8 +171,6 @@ _copyBitmapset(const Bitmapset *from) void * copyObjectImpl(const void *from) { - void *retval; - if (from == NULL) return NULL; @@ -189,7 +182,7 @@ copyObjectImpl(const void *from) #include "copyfuncs.switch.c" case T_List: - retval = list_copy_deep(from); + return list_copy_deep(from); break; /* @@ -199,14 +192,13 @@ copyObjectImpl(const void *from) case T_IntList: case T_OidList: case T_XidList: - retval = list_copy(from); + return list_copy(from); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(from)); - retval = 0; /* keep compiler quiet */ break; } - return retval; + return NULL; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index b2f07da62e..f3658e79a2 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -60,12 +60,12 @@ /* Macro for comparing string fields that might be NULL */ #define equalstr(a, b) \ - (((a) != NULL && (b) != NULL) ? (strcmp(a, b) == 0) : (a) == (b)) + (((a) != NULL && (b) != NULL) ? (a[0] == b[0] && strcmp(a, b) == 0) : (a) == (b)) /* Compare a field that is an inline array */ #define COMPARE_ARRAY_FIELD(fldname) \ do { \ - if (memcmp(a->fldname, b->fldname, sizeof(a->fldname)) != 0) \ + if (a->fldname[0] != b->fldname[0] || memcmp(a->fldname, b->fldname, sizeof(a->fldname)) != 0) \ return false; \ } while (0) @@ -224,9 +224,7 @@ _equalList(const List *a, const List *b) bool equal(const void *a, const void *b) { - bool retval; - - if (a == b) + if (unlikely(a == b)) return true; /* @@ -252,15 +250,14 @@ equal(const void *a, const void *b) case T_IntList: case T_OidList: case T_XidList: - retval = _equalList(a, b); + return _equalList(a, b); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(a)); - retval = false; /* keep compiler quiet */ break; } - return retval; + return false; } diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl index b6f086e262..b02ce7bbb2 100644 --- a/src/backend/nodes/gen_node_support.pl +++ b/src/backend/nodes/gen_node_support.pl @@ -656,12 +656,12 @@ foreach my $n (@node_types) next if $struct_no_copy && $struct_no_equal; print $cfs "\t\tcase T_${n}:\n" - . "\t\t\tretval = _copy${n}(from);\n" + . "\t\t\treturn _copy${n}(from);\n" . "\t\t\tbreak;\n" unless $struct_no_copy; print $efs "\t\tcase T_${n}:\n" - . "\t\t\tretval = _equal${n}(a, b);\n" + . "\t\t\treturn _equal${n}(a, b);\n" . "\t\t\tbreak;\n" unless $struct_no_equal; @@ -680,6 +680,7 @@ static bool _equal${n}(const $n *a, const $n *b) { " unless $struct_no_equal; + my $memcpy_ignore = 0; # print instructions for each field foreach my $f (@{ $node_type_info{$n}->{fields} }) @@ -708,8 +709,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 copy_as is specified - if (defined $copy_as_field) + if (defined $copy_as_field && !$memcpy_ignore) { print $cff "\tnewnode->$f = $copy_as_field;\n" unless $copy_ignore; @@ -730,12 +737,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 @@ -779,7 +786,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 @@ -792,7 +799,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*' @@ -801,7 +808,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 diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 23776367c5..2ba2dc8358 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -58,74 +58,74 @@ /* Read an integer field (anything written as ":fldname %d") */ #define READ_INT_FIELD(fldname) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = atoi(token) /* Read an unsigned integer field (anything written as ":fldname %u") */ #define READ_UINT_FIELD(fldname) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = atoui(token) /* Read an unsigned integer field (anything written using UINT64_FORMAT) */ #define READ_UINT64_FIELD(fldname) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = strtou64(token, NULL, 10) /* Read a long integer field (anything written as ":fldname %ld") */ #define READ_LONG_FIELD(fldname) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = atol(token) /* Read an OID field (don't hard-wire assumption that OID is same as uint) */ #define READ_OID_FIELD(fldname) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = atooid(token) /* Read a char field (ie, one ascii character) */ #define READ_CHAR_FIELD(fldname) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ /* avoid overhead of calling debackslash() for one char */ \ local_node->fldname = (length == 0) ? '\0' : (token[0] == '\\' ? token[1] : token[0]) /* Read an enumerated-type field that was written as an integer code */ #define READ_ENUM_FIELD(fldname, enumtype) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = (enumtype) atoi(token) /* Read a float field */ #define READ_FLOAT_FIELD(fldname) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = atof(token) /* Read a boolean field */ #define READ_BOOL_FIELD(fldname) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = strtobool(token) /* Read a character-string field */ #define READ_STRING_FIELD(fldname) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = nullable_string(token, length) /* Read a parse location field (and possibly throw away the value) */ #ifdef WRITE_READ_PARSE_PLAN_TREES #define READ_LOCATION_FIELD(fldname) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = restore_location_fields ? atoi(token) : -1 #else #define READ_LOCATION_FIELD(fldname) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ (void) token; /* in case not used elsewhere */ \ local_node->fldname = -1 /* set field to "unknown" */ @@ -145,22 +145,22 @@ /* Read an attribute number array */ #define READ_ATTRNUMBER_ARRAY(fldname, len) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ local_node->fldname = readAttrNumberCols(len) /* Read an oid array */ #define READ_OID_ARRAY(fldname, len) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ local_node->fldname = readOidCols(len) /* Read an int array */ #define READ_INT_ARRAY(fldname, len) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ local_node->fldname = readIntCols(len) /* Read a bool array */ #define READ_BOOL_ARRAY(fldname, len) \ - token = pg_strtok(&length); /* skip :fldname */ \ + (void) pg_strtok(&length); /* skip :fldname */ \ local_node->fldname = readBoolCols(len) /* Routine exit */ @@ -283,7 +283,7 @@ _readBoolExpr(void) READ_LOCALS(BoolExpr); /* do-it-yourself enum representation */ - token = pg_strtok(&length); /* skip :boolop */ + (void) pg_strtok(&length); /* skip :boolop */ token = pg_strtok(&length); /* get field value */ if (length == 3 && strncmp(token, "and", 3) == 0) local_node->boolop = AND_EXPR; @@ -333,7 +333,7 @@ _readConstraint(void) READ_BOOL_FIELD(initdeferred); READ_LOCATION_FIELD(location); - token = pg_strtok(&length); /* skip :contype */ + (void) pg_strtok(&length); /* skip :contype */ token = pg_strtok(&length); /* get field value */ if (length == 4 && strncmp(token, "NULL", 4) == 0) local_node->contype = CONSTR_NULL; @@ -643,7 +643,7 @@ _readExtensibleNode(void) READ_TEMP_LOCALS(); - token = pg_strtok(&length); /* skip :extnodename */ + (void) pg_strtok(&length); /* skip :extnodename */ token = pg_strtok(&length); /* get extnodename */ extnodename = nullable_string(token, length);