Copilot commented on code in PR #1827:
URL: https://github.com/apache/cloudberry/pull/1827#discussion_r3504658535
##########
gpcontrib/pg_hint_plan/pg_hint_plan.c:
##########
@@ -2963,7 +2963,7 @@ get_current_hint_string(ParseState *pstate, Query *query)
if (jumblequery)
{
- jstate = JumbleQueryDirect(query, query_str);
+ jstate = JumbleQuery(query);
Review Comment:
`JumbleQuery()` now contains `Assert(IsQueryIdEnabled())`. Calling it here
without ensuring query-id computation is enabled can crash builds with
`USE_ASSERT_CHECKING` (e.g., when `compute_query_id=off/auto` and no module
enabled it). Since this path needs a `JumbleState` for normalization, it should
either enable query-id computation (when allowed) or raise a clear error
instead of tripping an assertion.
##########
src/backend/nodes/gen_node_support.pl:
##########
@@ -889,6 +930,720 @@ sub elem
close $cfs;
close $efs;
+
+# outfuncs.c, readfuncs.c
+
+push @output_files, 'outfuncs.funcs.c';
+open my $off, '>', "$output_path/outfuncs.funcs.c$tmpext" or die $!;
+push @output_files, 'readfuncs.funcs.c';
+open my $rff, '>', "$output_path/readfuncs.funcs.c$tmpext" or die $!;
+push @output_files, 'outfuncs.switch.c';
+open my $ofs, '>', "$output_path/outfuncs.switch.c$tmpext" or die $!;
+push @output_files, 'readfuncs.switch.c';
+open my $rfs, '>', "$output_path/readfuncs.switch.c$tmpext" or die $!;
+
+printf $off $header_comment, 'outfuncs.funcs.c';
+printf $rff $header_comment, 'readfuncs.funcs.c';
+printf $ofs $header_comment, 'outfuncs.switch.c';
+printf $rfs $header_comment, 'readfuncs.switch.c';
+
+print $off $node_includes;
+print $rff $node_includes;
+
+
+push @output_files, 'outfast.funcs.c';
+open my $ofaf, '>', "$output_path/outfast.funcs.c$tmpext" or die $!;
+push @output_files, 'readfast.funcs.c';
+open my $rfaf, '>', "$output_path/readfast.funcs.c$tmpext" or die $!;
+push @output_files, 'outfast.switch.c';
+open my $ofas, '>', "$output_path/outfast.switch.c$tmpext" or die $!;
+push @output_files, 'readfast.switch.c';
+open my $rfas, '>', "$output_path/readfast.switch.c$tmpext" or die $!;
+
+printf $ofaf $header_comment, 'outfast.funcs.c';
+printf $rfaf $header_comment, 'readfast.funcs.c';
+printf $ofas $header_comment, 'outfast.switch.c';
+printf $rfas $header_comment, 'readfast.switch.c';
+
+print $ofaf $node_includes;
+print $rfaf $node_includes;
+
+foreach my $n (@node_types)
+{
+ next if elem $n, @abstract_types;
+ next if elem $n, @nodetag_only;
+ next if elem $n, @no_read_write;
+ next if elem $n, @special_read_write;
+
+ my $no_read = (elem $n, @no_read);
+
+ # output format starts with upper case node type name
+ my $N = uc $n;
+
+ print $ofs "\t\t\tcase T_${n}:\n"
+ . "\t\t\t\t_out${n}(str, obj);\n"
+ . "\t\t\t\tbreak;\n";
+
+ print $rfs "\tif (MATCH(\"$N\", "
+ . length($N) . "))\n"
+ . "\t\treturn (Node *) _read${n}();\n"
+ unless $no_read;
+
+ # for out and read fast
+ print $ofas "\t\t\tcase T_${n}:\n"
+ . "\t\t\t\t_out${n}(str, obj);\n"
+ . "\t\t\t\tbreak;\n";
+
+ print $rfas "\t\t\tcase T_${n}:\n"
+ . "\t\t\t\treturn_value = _read${n}();\n"
+ . "\t\t\t\tbreak;\n"
+ unless $no_read;
+
+ next if elem $n, @custom_read_write;
+
+ print $off "
+static void
+_out${n}(StringInfo str, const $n *node)
+{
+\tWRITE_NODE_TYPE(\"$N\");
+
+";
+ # for out fast
+ print $ofaf "
+static void
+_out${n}(StringInfo str, const $n *node)
+{
+\tWRITE_NODE_TYPE(\"$N\");
+
+";
+
+ if (!$no_read)
+ {
+ my $macro =
+ (@{ $node_type_info{$n}->{fields} } > 0)
+ ? 'READ_LOCALS'
+ : 'READ_LOCALS_NO_FIELDS';
+ print $rff "
+static $n *
+_read${n}(void)
+{
+\t$macro($n);
+
+";
+
+ # for read fast
+ my $macro =
+ (@{ $node_type_info{$n}->{fields} } > 0)
+ ? 'READ_LOCALS'
+ : 'READ_LOCALS_NO_FIELDS';
+ print $rfaf "
+static $n *
+_read${n}(void)
+{
+\t$macro($n);
+
+";
+ }
+
+ # track already-processed fields to support field order checks
+ # (this isn't quite redundant with the previous loop, since
+ # we may be considering structs that lack copy/equal support)
+ my %previous_fields;
+
+ # print instructions for each field
+ foreach my $f (@{ $node_type_info{$n}->{fields} })
+ {
+ my $t = $node_type_info{$n}->{field_types}{$f};
+ my @a = @{ $node_type_info{$n}->{field_attrs}{$f} };
+
+ # extract per-field attributes
+ my $array_size_field;
+ my $read_as_field;
+ my $read_write_ignore = 0;
+ foreach my $a (@a)
+ {
+ if ($a =~ /^array_size\(([\w.]+)\)$/)
+ {
+ $array_size_field = $1;
+ # insist that we read the array size first!
+ die
+ "array size field $array_size_field for field
$n.$f must precede $f\n"
+ if (!$previous_fields{$array_size_field} &&
!$no_read);
+ }
+ elsif ($a =~ /^read_as\(([\w.]+)\)$/)
+ {
+ $read_as_field = $1;
+ }
+ elsif ($a eq 'read_write_ignore')
+ {
+ $read_write_ignore = 1;
+ }
+ }
+
+ if ($read_write_ignore)
+ {
+ # nothing to do if no_read
+ next if $no_read;
+ # for read_write_ignore with read_as(), emit the
appropriate
+ # assignment on the read side and move on.
+ if (defined $read_as_field)
+ {
+ print $rff "\tlocal_node->$f =
$read_as_field;\n";
+
+ #for read fast
+ print $rfaf "\tlocal_node->$f =
$read_as_field;\n";
+ next;
+ }
+ # else, bad specification
+ die "$n.$f must not be marked read_write_ignore\n";
+ }
+
+ # select instructions by field type
+ if ($t eq 'bool')
+ {
+ print $off "\tWRITE_BOOL_FIELD($f);\n";
+ print $rff "\tREAD_BOOL_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_BOOL_FIELD($f);\n";
+ print $rfaf "\tREAD_BOOL_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'int' && $f =~ 'location$')
+ {
+ print $off "\tWRITE_LOCATION_FIELD($f);\n";
+ print $rff "\tREAD_LOCATION_FIELD($f);\n" unless
$no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_LOCATION_FIELD($f);\n";
+ print $rfaf "\tREAD_LOCATION_FIELD($f);\n" unless
$no_read;
+ }
+ elsif ($t eq 'int'
+ || $t eq 'int8'
+ || $t eq 'int16'
+ || $t eq 'int32'
+ || $t eq 'AttrNumber'
+ || $t eq 'StrategyNumber')
+ {
+ print $off "\tWRITE_INT_FIELD($f);\n";
+ print $rff "\tREAD_INT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_INT_FIELD($f);\n";
+ print $rfaf "\tREAD_INT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'int64')
+ {
+ print $off "\tWRITE_LONG_FIELD($f);\n";
+ print $rff "\tREAD_LONG_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_LONG_FIELD($f);\n";
+ print $rfaf "\tREAD_LONG_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'uint32'
+ || $t eq 'uint8'
+ || $t eq 'bits32'
+ || $t eq 'BlockNumber'
+ || $t eq 'Index'
+ || $t eq 'SubTransactionId')
+ {
+ print $off "\tWRITE_UINT_FIELD($f);\n";
+ print $rff "\tREAD_UINT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_UINT_FIELD($f);\n";
+ print $rfaf "\tREAD_UINT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'uint64'
+ || $t eq 'AclMode')
+ {
+ print $off "\tWRITE_UINT64_FIELD($f);\n";
+ print $rff "\tREAD_UINT64_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_UINT64_FIELD($f);\n";
+ print $rfaf "\tREAD_UINT64_FIELD($f);\n" unless
$no_read;
+ }
+ elsif ($t eq 'Oid' || $t eq 'RelFileNumber')
+ {
+ print $off "\tWRITE_OID_FIELD($f);\n";
+ print $rff "\tREAD_OID_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_OID_FIELD($f);\n";
+ print $rfaf "\tREAD_OID_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'long')
+ {
+ print $off "\tWRITE_LONG_FIELD($f);\n";
+ print $rff "\tREAD_LONG_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_LONG_FIELD($f);\n";
+ print $rfaf "\tREAD_LONG_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'char')
+ {
+ print $off "\tWRITE_CHAR_FIELD($f);\n";
+ print $rff "\tREAD_CHAR_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_CHAR_FIELD($f);\n";
+ print $rfaf "\tREAD_CHAR_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'double')
+ {
+ print $off "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rfaf "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'Cardinality')
+ {
+ print $off "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rfaf "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'Cost')
+ {
+ print $off "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rfaf "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'QualCost')
+ {
+ print $off "\tWRITE_FLOAT_FIELD($f.startup);\n";
+ print $off "\tWRITE_FLOAT_FIELD($f.per_tuple);\n";
+ print $rff "\tREAD_FLOAT_FIELD($f.startup);\n" unless
$no_read;
+ print $rff "\tREAD_FLOAT_FIELD($f.per_tuple);\n" unless
$no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_FLOAT_FIELD($f.startup);\n";
+ print $ofaf "\tWRITE_FLOAT_FIELD($f.per_tuple);\n";
+ print $rfaf "\tREAD_FLOAT_FIELD($f.startup);\n" unless
$no_read;
+ print $rfaf "\tREAD_FLOAT_FIELD($f.per_tuple);\n"
unless $no_read;
+ }
+ elsif ($t eq 'Selectivity')
+ {
+ print $off "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rfaf "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'char*')
+ {
+ print $off "\tWRITE_STRING_FIELD($f);\n";
+ print $rff "\tREAD_STRING_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_STRING_FIELD($f);\n";
+ print $rfaf "\tREAD_STRING_FIELD($f);\n" unless
$no_read;
+ }
+ elsif ($t eq 'Bitmapset*' || $t eq 'Relids')
+ {
+ print $off "\tWRITE_BITMAPSET_FIELD($f);\n";
+ print $rff "\tREAD_BITMAPSET_FIELD($f);\n" unless
$no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_BITMAPSET_FIELD($f);\n";
+ print $rfaf "\tREAD_BITMAPSET_FIELD($f);\n" unless
$no_read;
+ }
+ elsif (elem $t, @enum_types)
+ {
+ print $off "\tWRITE_ENUM_FIELD($f, $t);\n";
+ print $rff "\tREAD_ENUM_FIELD($f, $t);\n" unless
$no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_ENUM_FIELD($f, $t);\n";
+ print $rfaf "\tREAD_ENUM_FIELD($f, $t);\n" unless
$no_read;
+ }
+ # arrays of scalar types
+ elsif ($t =~ /^(\w+)(\*|\[\w+\])$/ and elem $1, @scalar_types)
+ {
+ my $tt = uc $1;
+ if (!defined $array_size_field)
+ {
+ die "no array size defined for $n.$f of type
$t\n";
+ }
+ if
($node_type_info{$n}->{field_types}{$array_size_field} eq
+ 'List*')
+ {
+ print $off
+ "\tWRITE_${tt}_ARRAY($f,
list_length(node->$array_size_field));\n";
+ print $rff
+ "\tREAD_${tt}_ARRAY($f,
list_length(local_node->$array_size_field));\n"
+ unless $no_read;
+
+ # for out and read fast
+ print $ofaf
+ "\tWRITE_${tt}_ARRAY($f,
list_length(node->$array_size_field));\n";
+ print $rfaf
+ "\tREAD_${tt}_ARRAY($f,
list_length(local_node->$array_size_field));\n"
+ unless $no_read;
+ }
+ else
+ {
+ print $off
+ "\tWRITE_${tt}_ARRAY($f,
node->$array_size_field);\n";
+ print $rff
+ "\tREAD_${tt}_ARRAY($f,
local_node->$array_size_field);\n"
+ unless $no_read;
+
+ # for out and read fast
+ print $ofaf
+ "\tWRITE_${tt}_ARRAY($f,
node->$array_size_field);\n";
+ print $rfaf
+ "\tREAD_${tt}_ARRAY($f,
local_node->$array_size_field);\n"
+ unless $no_read;
+ }
+ }
+ elsif ($t eq 'function pointer')
+ {
+ # We don't print these, and we can't read them either
+ die "cannot read function pointer in struct \"$n\"
field \"$f\"\n"
+ unless $no_read;
+ }
+ # Special treatments of several Path node fields
+ elsif ($t eq 'RelOptInfo*' && elem 'write_only_relids', @a)
+ {
+ print $off
+ "\tappendStringInfoString(str, \" :parent_relids
\");\n"
+ . "\toutBitmapset(str, node->$f->relids);\n";
+
+ # for out and read fast
+ print $ofaf
+ "\tappendStringInfoString(str, \"
:parent_relids \");\n"
+ . "\toutBitmapset(str,
node->$f->relids);\n";
+ }
+ elsif ($t eq 'PathTarget*' && elem
'write_only_nondefault_pathtarget',
+ @a)
+ {
+ (my $f2 = $f) =~ s/pathtarget/parent/;
+ print $off "\tif (node->$f != node->$f2->reltarget)\n"
+ . "\t\tWRITE_NODE_FIELD($f);\n";
+
+ # for out and read fast
+ print $ofaf "\tif (node->$f != node->$f2->reltarget)\n"
+ . "\t\tWRITE_NODE_FIELD($f);\n";
+ }
+ elsif ($t eq 'ParamPathInfo*' && elem 'write_only_req_outer',
@a)
+ {
+ print $off
+ "\tappendStringInfoString(str, \" :required_outer
\");\n"
+ . "\tif (node->$f)\n"
+ . "\t\toutBitmapset(str, node->$f->ppi_req_outer);\n"
+ . "\telse\n"
+ . "\t\toutBitmapset(str, NULL);\n";
+
+ # for out and read fast
+ print $ofaf
+ "\tappendStringInfoString(str, \"
:required_outer \");\n"
+ . "\tif (node->$f)\n"
+ . "\t\toutBitmapset(str,
node->$f->ppi_req_outer);\n"
+ . "\telse\n"
+ . "\t\toutBitmapset(str, NULL);\n";
+ }
+ # node type
+ elsif (($t =~ /^(\w+)\*$/ or $t =~ /^struct\s+(\w+)\*$/)
+ and elem $1, @node_types)
+ {
+ die
+ "node type \"$1\" lacks write support, which is
required for struct \"$n\" field \"$f\"\n"
+ if (elem $1, @no_read_write or elem $1,
@nodetag_only);
+ die
+ "node type \"$1\" lacks read support, which is
required for struct \"$n\" field \"$f\"\n"
+ if (elem $1, @no_read or elem $1, @nodetag_only)
+ and !$no_read;
+
+ print $off "\tWRITE_NODE_FIELD($f);\n";
+ print $rff "\tREAD_NODE_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_NODE_FIELD($f);\n";
+ print $rfaf "\tREAD_NODE_FIELD($f);\n" unless $no_read;
+ }
+ # arrays of node pointers (currently supported for write only)
+ elsif (($t =~ /^(\w+)\*\*$/ or $t =~ /^struct\s+(\w+)\*\*$/)
+ and elem($1, @node_types))
+ {
+ if (!defined $array_size_field)
+ {
+ die "no array size defined for $n.$f of type
$t\n";
+ }
+ if
($node_type_info{$n}->{field_types}{$array_size_field} eq
+ 'List*')
+ {
+ print $off
+ "\tWRITE_NODE_ARRAY($f,
list_length(node->$array_size_field));\n";
+ print $rff
+ "\tREAD_NODE_ARRAY($f,
list_length(local_node->$array_size_field));\n"
+ unless $no_read;
+
+ # for out and read fast
+ print $ofaf
+ "\tWRITE_NODE_ARRAY($f,
list_length(node->$array_size_field));\n";
+ print $rfaf
+ "\tREAD_NODE_ARRAY($f,
list_length(local_node->$array_size_field));\n"
+ unless $no_read;
+ }
+ else
+ {
+ print $off
+ "\tWRITE_NODE_ARRAY($f,
node->$array_size_field);\n";
+ print $rff
+ "\tREAD_NODE_ARRAY($f,
local_node->$array_size_field);\n"
+ unless $no_read;
+
+ # for out and read fast
+ print $ofaf
+ "\tWRITE_NODE_ARRAY($f,
node->$array_size_field);\n";
+ print $rfaf
+ "\tREAD_NODE_ARRAY($f,
local_node->$array_size_field);\n"
+ unless $no_read;
+ }
+ }
+ elsif ($t eq 'struct CustomPathMethods*'
+ || $t eq 'struct CustomScanMethods*')
+ {
+ print $off q{
+ /* CustomName is a key to lookup CustomScanMethods */
+ appendStringInfoString(str, " :methods ");
+ outToken(str, node->methods->CustomName);
+};
+ print $rff q!
+ {
+ /* Lookup CustomScanMethods by CustomName */
+ char *custom_name;
+ const CustomScanMethods *methods;
+ token = pg_strtok(&length); /* skip methods: */
+ token = pg_strtok(&length); /* CustomName */
+ custom_name = nullable_string(token, length);
+ methods = GetCustomScanMethods(custom_name, false);
+ local_node->methods = methods;
+ }
+! unless $no_read;
+
+ # for out and read fast
+ print $ofaf q{
+ /* CustomName is a key to lookup CustomScanMethods */
+ appendStringInfoString(str, " :methods ");
+ outToken(str, node->methods->CustomName);
+};
+ print $rfaf q!
+ {
+ /* Lookup CustomScanMethods by CustomName */
+ char *custom_name;
+ const CustomScanMethods *methods;
+ READ_STRING_VAR(custom_name);
+ /* find custom scan methods from hash table. */
+ methods = GetCustomScanMethods(custom_name, false);
+ local_node->methods = methods;
+ }
+! unless $no_read;
+ }
+ elsif($t eq 'bytea*')
+ {
+ print $ofaf
+ "\tWRITE_BYTEA_FIELD($f);\n";
+ print $rfaf
+ "\tREAD_BYTEA_FIELD($f);\n"
+ unless $no_read;
+ }
Review Comment:
The code generator's out/read handling for `bytea*` only emits
`WRITE_BYTEA_FIELD`/`READ_BYTEA_FIELD` for the fast (binary) path, but emits
nothing for the regular text out/read functions. This will cause generated
`outfuncs`/`readfuncs` to silently omit `bytea*` fields (e.g.,
`RangeTblFunction.funcuserdata`), breaking nodeToString/nodeRead round-trips
and potentially corrupting serialized parse trees.
##########
src/backend/nodes/read.c:
##########
@@ -548,7 +548,7 @@ nodeRead(const char *token, int tok_len)
}
else
{
- elog(ERROR, "unrecognized token: \"%.*s\"",
tok_len, token);
+ elog(PANIC, "unrecognized token: \"%.*s\"",
tok_len, token);
Review Comment:
Escalating an unrecognized token during node deserialization from `ERROR` to
`PANIC` will crash the backend/server for what is typically malformed or
unexpected input. This should remain an `ERROR` so the session can fail cleanly
without taking down the process.
##########
src/include/commands/explain_gp.h:
##########
@@ -0,0 +1,91 @@
+/*-------------------------------------------------------------------------
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * explain_gp.h
+ *
+ * src/include/commands/explain_gp.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXPLAIN_GP_H
+#define EXPLAIN_GP_H
+
+
Review Comment:
This new public header defines structs with by-value fields of types like
`NodeTag`, `instr_time`, `TuplesortInstrumentation`, `HashInstrumentation`,
`IncrementalSortGroupInfo`, and `WalUsage`, but it doesn't include the headers
that define those types. Since `explain_gp.c` includes this header before
`utils/tuplesort.h`, this is very likely to be a compile error (incomplete
type) and/or a fragile include-order dependency. The header should include the
required definitions itself.
##########
src/backend/access/transam/xlogrecovery.c:
##########
@@ -2215,7 +2215,7 @@ CheckTablespaceDirectory(void)
snprintf(path, sizeof(path), "pg_tblspc/%s", de->d_name);
if (get_dirent_type(path, de, false, ERROR) != PGFILETYPE_LNK)
- ereport(allow_in_place_tablespaces ? WARNING : PANIC,
+ ereport(allow_in_place_tablespaces ? WARNING : WARNING,
Review Comment:
The comment says `allow_in_place_tablespaces` should turn a `PANIC` into a
`WARNING`, but the code now emits `WARNING` unconditionally. This removes the
safety check for unexpected non-symlink entries in `pg_tblspc/` and makes the
GUC ineffective; recovery should still `PANIC` when
`allow_in_place_tablespaces` is off.
##########
src/backend/commands/subscriptioncmds.c:
##########
@@ -672,6 +672,13 @@ CreateSubscription(ParseState *pstate,
CreateSubscriptionStmt *stmt,
opts.synchronous_commit = "off";
conninfo = stmt->conninfo;
+ /*
+ * conninfo can be an empty string, but the serialization
+ * doesn't distinguish an empty string from NULL. The
+ * code that executes the command in't prepared for a NULL.
Review Comment:
Typo in comment: "in't" -> "isn't".
##########
src/backend/nodes/gen_node_support.pl:
##########
@@ -889,6 +930,720 @@ sub elem
close $cfs;
close $efs;
+
+# outfuncs.c, readfuncs.c
+
+push @output_files, 'outfuncs.funcs.c';
+open my $off, '>', "$output_path/outfuncs.funcs.c$tmpext" or die $!;
+push @output_files, 'readfuncs.funcs.c';
+open my $rff, '>', "$output_path/readfuncs.funcs.c$tmpext" or die $!;
+push @output_files, 'outfuncs.switch.c';
+open my $ofs, '>', "$output_path/outfuncs.switch.c$tmpext" or die $!;
+push @output_files, 'readfuncs.switch.c';
+open my $rfs, '>', "$output_path/readfuncs.switch.c$tmpext" or die $!;
+
+printf $off $header_comment, 'outfuncs.funcs.c';
+printf $rff $header_comment, 'readfuncs.funcs.c';
+printf $ofs $header_comment, 'outfuncs.switch.c';
+printf $rfs $header_comment, 'readfuncs.switch.c';
+
+print $off $node_includes;
+print $rff $node_includes;
+
+
+push @output_files, 'outfast.funcs.c';
+open my $ofaf, '>', "$output_path/outfast.funcs.c$tmpext" or die $!;
+push @output_files, 'readfast.funcs.c';
+open my $rfaf, '>', "$output_path/readfast.funcs.c$tmpext" or die $!;
+push @output_files, 'outfast.switch.c';
+open my $ofas, '>', "$output_path/outfast.switch.c$tmpext" or die $!;
+push @output_files, 'readfast.switch.c';
+open my $rfas, '>', "$output_path/readfast.switch.c$tmpext" or die $!;
+
+printf $ofaf $header_comment, 'outfast.funcs.c';
+printf $rfaf $header_comment, 'readfast.funcs.c';
+printf $ofas $header_comment, 'outfast.switch.c';
+printf $rfas $header_comment, 'readfast.switch.c';
+
+print $ofaf $node_includes;
+print $rfaf $node_includes;
+
+foreach my $n (@node_types)
+{
+ next if elem $n, @abstract_types;
+ next if elem $n, @nodetag_only;
+ next if elem $n, @no_read_write;
+ next if elem $n, @special_read_write;
+
+ my $no_read = (elem $n, @no_read);
+
+ # output format starts with upper case node type name
+ my $N = uc $n;
+
+ print $ofs "\t\t\tcase T_${n}:\n"
+ . "\t\t\t\t_out${n}(str, obj);\n"
+ . "\t\t\t\tbreak;\n";
+
+ print $rfs "\tif (MATCH(\"$N\", "
+ . length($N) . "))\n"
+ . "\t\treturn (Node *) _read${n}();\n"
+ unless $no_read;
+
+ # for out and read fast
+ print $ofas "\t\t\tcase T_${n}:\n"
+ . "\t\t\t\t_out${n}(str, obj);\n"
+ . "\t\t\t\tbreak;\n";
+
+ print $rfas "\t\t\tcase T_${n}:\n"
+ . "\t\t\t\treturn_value = _read${n}();\n"
+ . "\t\t\t\tbreak;\n"
+ unless $no_read;
+
+ next if elem $n, @custom_read_write;
+
+ print $off "
+static void
+_out${n}(StringInfo str, const $n *node)
+{
+\tWRITE_NODE_TYPE(\"$N\");
+
+";
+ # for out fast
+ print $ofaf "
+static void
+_out${n}(StringInfo str, const $n *node)
+{
+\tWRITE_NODE_TYPE(\"$N\");
+
+";
+
+ if (!$no_read)
+ {
+ my $macro =
+ (@{ $node_type_info{$n}->{fields} } > 0)
+ ? 'READ_LOCALS'
+ : 'READ_LOCALS_NO_FIELDS';
+ print $rff "
+static $n *
+_read${n}(void)
+{
+\t$macro($n);
+
+";
+
+ # for read fast
+ my $macro =
+ (@{ $node_type_info{$n}->{fields} } > 0)
+ ? 'READ_LOCALS'
+ : 'READ_LOCALS_NO_FIELDS';
+ print $rfaf "
+static $n *
+_read${n}(void)
+{
+\t$macro($n);
+
+";
+ }
+
+ # track already-processed fields to support field order checks
+ # (this isn't quite redundant with the previous loop, since
+ # we may be considering structs that lack copy/equal support)
+ my %previous_fields;
+
+ # print instructions for each field
+ foreach my $f (@{ $node_type_info{$n}->{fields} })
+ {
+ my $t = $node_type_info{$n}->{field_types}{$f};
+ my @a = @{ $node_type_info{$n}->{field_attrs}{$f} };
+
+ # extract per-field attributes
+ my $array_size_field;
+ my $read_as_field;
+ my $read_write_ignore = 0;
+ foreach my $a (@a)
+ {
+ if ($a =~ /^array_size\(([\w.]+)\)$/)
+ {
+ $array_size_field = $1;
+ # insist that we read the array size first!
+ die
+ "array size field $array_size_field for field
$n.$f must precede $f\n"
+ if (!$previous_fields{$array_size_field} &&
!$no_read);
+ }
+ elsif ($a =~ /^read_as\(([\w.]+)\)$/)
+ {
+ $read_as_field = $1;
+ }
+ elsif ($a eq 'read_write_ignore')
+ {
+ $read_write_ignore = 1;
+ }
+ }
+
+ if ($read_write_ignore)
+ {
+ # nothing to do if no_read
+ next if $no_read;
+ # for read_write_ignore with read_as(), emit the
appropriate
+ # assignment on the read side and move on.
+ if (defined $read_as_field)
+ {
+ print $rff "\tlocal_node->$f =
$read_as_field;\n";
+
+ #for read fast
+ print $rfaf "\tlocal_node->$f =
$read_as_field;\n";
+ next;
+ }
+ # else, bad specification
+ die "$n.$f must not be marked read_write_ignore\n";
+ }
+
+ # select instructions by field type
+ if ($t eq 'bool')
+ {
+ print $off "\tWRITE_BOOL_FIELD($f);\n";
+ print $rff "\tREAD_BOOL_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_BOOL_FIELD($f);\n";
+ print $rfaf "\tREAD_BOOL_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'int' && $f =~ 'location$')
+ {
+ print $off "\tWRITE_LOCATION_FIELD($f);\n";
+ print $rff "\tREAD_LOCATION_FIELD($f);\n" unless
$no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_LOCATION_FIELD($f);\n";
+ print $rfaf "\tREAD_LOCATION_FIELD($f);\n" unless
$no_read;
+ }
+ elsif ($t eq 'int'
+ || $t eq 'int8'
+ || $t eq 'int16'
+ || $t eq 'int32'
+ || $t eq 'AttrNumber'
+ || $t eq 'StrategyNumber')
+ {
+ print $off "\tWRITE_INT_FIELD($f);\n";
+ print $rff "\tREAD_INT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_INT_FIELD($f);\n";
+ print $rfaf "\tREAD_INT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'int64')
+ {
+ print $off "\tWRITE_LONG_FIELD($f);\n";
+ print $rff "\tREAD_LONG_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_LONG_FIELD($f);\n";
+ print $rfaf "\tREAD_LONG_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'uint32'
+ || $t eq 'uint8'
+ || $t eq 'bits32'
+ || $t eq 'BlockNumber'
+ || $t eq 'Index'
+ || $t eq 'SubTransactionId')
+ {
+ print $off "\tWRITE_UINT_FIELD($f);\n";
+ print $rff "\tREAD_UINT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_UINT_FIELD($f);\n";
+ print $rfaf "\tREAD_UINT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'uint64'
+ || $t eq 'AclMode')
+ {
+ print $off "\tWRITE_UINT64_FIELD($f);\n";
+ print $rff "\tREAD_UINT64_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_UINT64_FIELD($f);\n";
+ print $rfaf "\tREAD_UINT64_FIELD($f);\n" unless
$no_read;
+ }
+ elsif ($t eq 'Oid' || $t eq 'RelFileNumber')
+ {
+ print $off "\tWRITE_OID_FIELD($f);\n";
+ print $rff "\tREAD_OID_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_OID_FIELD($f);\n";
+ print $rfaf "\tREAD_OID_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'long')
+ {
+ print $off "\tWRITE_LONG_FIELD($f);\n";
+ print $rff "\tREAD_LONG_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_LONG_FIELD($f);\n";
+ print $rfaf "\tREAD_LONG_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'char')
+ {
+ print $off "\tWRITE_CHAR_FIELD($f);\n";
+ print $rff "\tREAD_CHAR_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_CHAR_FIELD($f);\n";
+ print $rfaf "\tREAD_CHAR_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'double')
+ {
+ print $off "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rfaf "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'Cardinality')
+ {
+ print $off "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rfaf "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'Cost')
+ {
+ print $off "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rfaf "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'QualCost')
+ {
+ print $off "\tWRITE_FLOAT_FIELD($f.startup);\n";
+ print $off "\tWRITE_FLOAT_FIELD($f.per_tuple);\n";
+ print $rff "\tREAD_FLOAT_FIELD($f.startup);\n" unless
$no_read;
+ print $rff "\tREAD_FLOAT_FIELD($f.per_tuple);\n" unless
$no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_FLOAT_FIELD($f.startup);\n";
+ print $ofaf "\tWRITE_FLOAT_FIELD($f.per_tuple);\n";
+ print $rfaf "\tREAD_FLOAT_FIELD($f.startup);\n" unless
$no_read;
+ print $rfaf "\tREAD_FLOAT_FIELD($f.per_tuple);\n"
unless $no_read;
+ }
+ elsif ($t eq 'Selectivity')
+ {
+ print $off "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_FLOAT_FIELD($f);\n";
+ print $rfaf "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ }
+ elsif ($t eq 'char*')
+ {
+ print $off "\tWRITE_STRING_FIELD($f);\n";
+ print $rff "\tREAD_STRING_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_STRING_FIELD($f);\n";
+ print $rfaf "\tREAD_STRING_FIELD($f);\n" unless
$no_read;
+ }
+ elsif ($t eq 'Bitmapset*' || $t eq 'Relids')
+ {
+ print $off "\tWRITE_BITMAPSET_FIELD($f);\n";
+ print $rff "\tREAD_BITMAPSET_FIELD($f);\n" unless
$no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_BITMAPSET_FIELD($f);\n";
+ print $rfaf "\tREAD_BITMAPSET_FIELD($f);\n" unless
$no_read;
+ }
+ elsif (elem $t, @enum_types)
+ {
+ print $off "\tWRITE_ENUM_FIELD($f, $t);\n";
+ print $rff "\tREAD_ENUM_FIELD($f, $t);\n" unless
$no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_ENUM_FIELD($f, $t);\n";
+ print $rfaf "\tREAD_ENUM_FIELD($f, $t);\n" unless
$no_read;
+ }
+ # arrays of scalar types
+ elsif ($t =~ /^(\w+)(\*|\[\w+\])$/ and elem $1, @scalar_types)
+ {
+ my $tt = uc $1;
+ if (!defined $array_size_field)
+ {
+ die "no array size defined for $n.$f of type
$t\n";
+ }
+ if
($node_type_info{$n}->{field_types}{$array_size_field} eq
+ 'List*')
+ {
+ print $off
+ "\tWRITE_${tt}_ARRAY($f,
list_length(node->$array_size_field));\n";
+ print $rff
+ "\tREAD_${tt}_ARRAY($f,
list_length(local_node->$array_size_field));\n"
+ unless $no_read;
+
+ # for out and read fast
+ print $ofaf
+ "\tWRITE_${tt}_ARRAY($f,
list_length(node->$array_size_field));\n";
+ print $rfaf
+ "\tREAD_${tt}_ARRAY($f,
list_length(local_node->$array_size_field));\n"
+ unless $no_read;
+ }
+ else
+ {
+ print $off
+ "\tWRITE_${tt}_ARRAY($f,
node->$array_size_field);\n";
+ print $rff
+ "\tREAD_${tt}_ARRAY($f,
local_node->$array_size_field);\n"
+ unless $no_read;
+
+ # for out and read fast
+ print $ofaf
+ "\tWRITE_${tt}_ARRAY($f,
node->$array_size_field);\n";
+ print $rfaf
+ "\tREAD_${tt}_ARRAY($f,
local_node->$array_size_field);\n"
+ unless $no_read;
+ }
+ }
+ elsif ($t eq 'function pointer')
+ {
+ # We don't print these, and we can't read them either
+ die "cannot read function pointer in struct \"$n\"
field \"$f\"\n"
+ unless $no_read;
+ }
+ # Special treatments of several Path node fields
+ elsif ($t eq 'RelOptInfo*' && elem 'write_only_relids', @a)
+ {
+ print $off
+ "\tappendStringInfoString(str, \" :parent_relids
\");\n"
+ . "\toutBitmapset(str, node->$f->relids);\n";
+
+ # for out and read fast
+ print $ofaf
+ "\tappendStringInfoString(str, \"
:parent_relids \");\n"
+ . "\toutBitmapset(str,
node->$f->relids);\n";
+ }
+ elsif ($t eq 'PathTarget*' && elem
'write_only_nondefault_pathtarget',
+ @a)
+ {
+ (my $f2 = $f) =~ s/pathtarget/parent/;
+ print $off "\tif (node->$f != node->$f2->reltarget)\n"
+ . "\t\tWRITE_NODE_FIELD($f);\n";
+
+ # for out and read fast
+ print $ofaf "\tif (node->$f != node->$f2->reltarget)\n"
+ . "\t\tWRITE_NODE_FIELD($f);\n";
+ }
+ elsif ($t eq 'ParamPathInfo*' && elem 'write_only_req_outer',
@a)
+ {
+ print $off
+ "\tappendStringInfoString(str, \" :required_outer
\");\n"
+ . "\tif (node->$f)\n"
+ . "\t\toutBitmapset(str, node->$f->ppi_req_outer);\n"
+ . "\telse\n"
+ . "\t\toutBitmapset(str, NULL);\n";
+
+ # for out and read fast
+ print $ofaf
+ "\tappendStringInfoString(str, \"
:required_outer \");\n"
+ . "\tif (node->$f)\n"
+ . "\t\toutBitmapset(str,
node->$f->ppi_req_outer);\n"
+ . "\telse\n"
+ . "\t\toutBitmapset(str, NULL);\n";
+ }
+ # node type
+ elsif (($t =~ /^(\w+)\*$/ or $t =~ /^struct\s+(\w+)\*$/)
+ and elem $1, @node_types)
+ {
+ die
+ "node type \"$1\" lacks write support, which is
required for struct \"$n\" field \"$f\"\n"
+ if (elem $1, @no_read_write or elem $1,
@nodetag_only);
+ die
+ "node type \"$1\" lacks read support, which is
required for struct \"$n\" field \"$f\"\n"
+ if (elem $1, @no_read or elem $1, @nodetag_only)
+ and !$no_read;
+
+ print $off "\tWRITE_NODE_FIELD($f);\n";
+ print $rff "\tREAD_NODE_FIELD($f);\n" unless $no_read;
+
+ # for out and read fast
+ print $ofaf "\tWRITE_NODE_FIELD($f);\n";
+ print $rfaf "\tREAD_NODE_FIELD($f);\n" unless $no_read;
+ }
+ # arrays of node pointers (currently supported for write only)
+ elsif (($t =~ /^(\w+)\*\*$/ or $t =~ /^struct\s+(\w+)\*\*$/)
+ and elem($1, @node_types))
+ {
+ if (!defined $array_size_field)
+ {
+ die "no array size defined for $n.$f of type
$t\n";
+ }
+ if
($node_type_info{$n}->{field_types}{$array_size_field} eq
+ 'List*')
+ {
+ print $off
+ "\tWRITE_NODE_ARRAY($f,
list_length(node->$array_size_field));\n";
+ print $rff
+ "\tREAD_NODE_ARRAY($f,
list_length(local_node->$array_size_field));\n"
+ unless $no_read;
+
+ # for out and read fast
+ print $ofaf
+ "\tWRITE_NODE_ARRAY($f,
list_length(node->$array_size_field));\n";
+ print $rfaf
+ "\tREAD_NODE_ARRAY($f,
list_length(local_node->$array_size_field));\n"
+ unless $no_read;
+ }
+ else
+ {
+ print $off
+ "\tWRITE_NODE_ARRAY($f,
node->$array_size_field);\n";
+ print $rff
+ "\tREAD_NODE_ARRAY($f,
local_node->$array_size_field);\n"
+ unless $no_read;
+
+ # for out and read fast
+ print $ofaf
+ "\tWRITE_NODE_ARRAY($f,
node->$array_size_field);\n";
+ print $rfaf
+ "\tREAD_NODE_ARRAY($f,
local_node->$array_size_field);\n"
+ unless $no_read;
+ }
+ }
+ elsif ($t eq 'struct CustomPathMethods*'
+ || $t eq 'struct CustomScanMethods*')
+ {
+ print $off q{
+ /* CustomName is a key to lookup CustomScanMethods */
+ appendStringInfoString(str, " :methods ");
+ outToken(str, node->methods->CustomName);
+};
+ print $rff q!
+ {
+ /* Lookup CustomScanMethods by CustomName */
+ char *custom_name;
+ const CustomScanMethods *methods;
+ token = pg_strtok(&length); /* skip methods: */
+ token = pg_strtok(&length); /* CustomName */
+ custom_name = nullable_string(token, length);
+ methods = GetCustomScanMethods(custom_name, false);
+ local_node->methods = methods;
+ }
+! unless $no_read;
+
+ # for out and read fast
+ print $ofaf q{
+ /* CustomName is a key to lookup CustomScanMethods */
+ appendStringInfoString(str, " :methods ");
+ outToken(str, node->methods->CustomName);
+};
+ print $rfaf q!
+ {
+ /* Lookup CustomScanMethods by CustomName */
+ char *custom_name;
+ const CustomScanMethods *methods;
+ READ_STRING_VAR(custom_name);
+ /* find custom scan methods from hash table. */
+ methods = GetCustomScanMethods(custom_name, false);
+ local_node->methods = methods;
+ }
+! unless $no_read;
+ }
+ elsif($t eq 'bytea*')
+ {
+ print $ofaf
+ "\tWRITE_BYTEA_FIELD($f);\n";
+ print $rfaf
+ "\tREAD_BYTEA_FIELD($f);\n"
+ unless $no_read;
+ }
+ elsif($t eq 'CdbPathLocus')
+ {
+ print $off
+ "\t_outCdbPathLocus(str, &node->$f);\n";
+
+ # for out and read fast
+ print $ofaf
+ "\t_outCdbPathLocus(str, &node->$f);\n";
+ }
+ elsif($t eq 'ItemPointerData')
+ {
+ print $off
+ "\tWRITE_UINT_FIELD($f.ip_blkid.bi_hi);
+ \tWRITE_UINT_FIELD($f.ip_blkid.bi_lo);
+ \tWRITE_UINT_FIELD($f.ip_posid);\n";
+ print $rff
+ "\tREAD_UINT_FIELD($f.ip_blkid.bi_hi);
+ \tREAD_UINT_FIELD($f.ip_blkid.bi_lo);
+ \tREAD_UINT_FIELD($f.ip_posid);\n"
+ unless $no_read;
+
+ # for out and read fast
+ print $ofaf
+ "\tWRITE_UINT_FIELD($f.ip_blkid.bi_hi);
+ \tWRITE_UINT_FIELD($f.ip_blkid.bi_lo);
+ \tWRITE_UINT_FIELD($f.ip_posid);\n";
+ print $rfaf
+ "\tREAD_UINT_FIELD($f.ip_blkid.bi_hi);
+ \tREAD_UINT_FIELD($f.ip_blkid.bi_lo);
+ \tREAD_UINT_FIELD($f.ip_posid);\n"
+ unless $no_read;
+ }
+ elsif($t eq 'TupleDesc')
+ {
+ print $ofaf "\tfor (int i = 0; i < node->$f->natts; i++)
+ \tappendBinaryStringInfo(str, (char *) &node->$f->attrs[i],
ATTRIBUTE_FIXED_PART_SIZE);\n";
+ print $rfaf "\tlocal_node->tuple =
CreateTemplateTupleDesc(local_node->natts);
+ if (local_node->$f->natts > 0)
+ {
+ int i = 0;
+ for (; i < local_node->$f->natts; i++)
+ {
+ memcpy(&local_node->$f->attrs[i], read_str_ptr,
ATTRIBUTE_FIXED_PART_SIZE);
+ read_str_ptr+=ATTRIBUTE_FIXED_PART_SIZE;
+ }
+ }\n"
+ unless $no_read;
+ }
+ else
+ {
+ die
+ "could not handle type \"$t\" in struct \"$n\" field
\"$f\"\n";
+ }
+
+ # for read_as() without read_write_ignore, we have to read the
value
+ # that outfuncs.c wrote and then overwrite it.
+ if (defined $read_as_field)
+ {
+ print $rff "\tlocal_node->$f = $read_as_field;\n"
unless $no_read;
+
+ # for out and read fast
+ print $rff "\tlocal_node->$f = $read_as_field;\n"
unless $no_read;
+ }
Review Comment:
In the `read_as()` overwrite block, the generator prints the "fast"
assignment to `$rff` (slow read output) instead of `$rfaf` (fast read output).
This duplicates the assignment in `readfuncs.funcs.c` and fails to emit it in
`readfast.funcs.c`, so any future `read_as(...)` (without `read_write_ignore`)
will deserialize incorrectly in the fast protocol.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]