Re: automatically generating node support functions
От | Tom Lane |
---|---|
Тема | Re: automatically generating node support functions |
Дата | |
Msg-id | 2593369.1657759779@sss.pgh.pa.us обсуждение исходный текст |
Ответ на | Re: automatically generating node support functions (Andres Freund <andres@anarazel.de>) |
Список | pgsql-hackers |
Just one more thing here ... I really don't like the fact that gen_node_support.pl's response to unparseable input is to silently ignore it. That's maybe tolerable outside a node struct, but I think we need a higher standard inside. I experimented with promoting the commented-out "warn" to "die", and soon learned that there are two shortcomings: * We can't cope with the embedded union inside A_Const. Simplest fix is to move it outside. * We can't cope with function-pointer fields. The only real problem there is that some of them spread across multiple lines, but really that was a shortcoming we'd have to fix sometime anyway. Proposed patch attached. regards, tom lane diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl index 96af17516a..35af4e231f 100644 --- a/src/backend/nodes/gen_node_support.pl +++ b/src/backend/nodes/gen_node_support.pl @@ -213,15 +213,34 @@ foreach my $infile (@ARGV) } $file_content .= $raw_file_content; - my $lineno = 0; + my $lineno = 0; + my $prevline = ''; foreach my $line (split /\n/, $file_content) { + # per-physical-line processing $lineno++; chomp $line; $line =~ s/\s*$//; next if $line eq ''; next if $line =~ /^#(define|ifdef|endif)/; + # within a node struct, don't process until we have whole logical line + if ($in_struct && $subline > 1) + { + if ($line =~ m/;$/) + { + # found the end, re-attach any previous line(s) + $line = $prevline . $line; + $prevline = ''; + } + else + { + # set it aside for a moment + $prevline .= $line . ' '; + next; + } + } + # we are analyzing a struct definition if ($in_struct) { @@ -394,7 +413,7 @@ foreach my $infile (@ARGV) } # normal struct field elsif ($line =~ - /^\s*(.+)\s*\b(\w+)(\[\w+\])?\s*(?:pg_node_attr\(([\w(), ]*)\))?;/ + /^\s*(.+)\s*\b(\w+)(\[[\w\s+]+\])?\s*(?:pg_node_attr\(([\w(), ]*)\))?;/ ) { if ($is_node_struct) @@ -441,13 +460,46 @@ foreach my $infile (@ARGV) $my_field_attrs{$name} = \@attrs; } } - else + # function pointer field + elsif ($line =~ + /^\s*([\w\s*]+)\s*\(\*(\w+)\)\s*\((.*)\)\s*(?:pg_node_attr\(([\w(), ]*)\))?;/ + ) { if ($is_node_struct) { - #warn "$infile:$lineno: could not parse \"$line\"\n"; + my $type = $1; + my $name = $2; + my $args = $3; + my $attrs = $4; + + my @attrs; + if ($attrs) + { + @attrs = split /,\s*/, $attrs; + foreach my $attr (@attrs) + { + if ( $attr !~ /^copy_as\(\w+\)$/ + && $attr !~ /^read_as\(\w+\)$/ + && !elem $attr, + qw(equal_ignore read_write_ignore)) + { + die + "$infile:$lineno: unrecognized attribute \"$attr\"\n"; + } + } + } + + push @my_fields, $name; + $my_field_types{$name} = 'function pointer'; + $my_field_attrs{$name} = \@attrs; } } + else + { + # We're not too picky about what's outside structs, + # but we'd better understand everything inside. + die "$infile:$lineno: could not parse \"$line\"\n"; + } } # not in a struct else @@ -709,6 +761,12 @@ _equal${n}(const $n *a, const $n *b) unless $equal_ignore; } } + elsif ($t eq 'function pointer') + { + # we can copy and compare as a scalar + print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore; + print $eff "\tCOMPARE_SCALAR_FIELD($f);\n" unless $equal_ignore; + } # node type elsif ($t =~ /(\w+)\*/ and elem $1, @node_types) { @@ -980,6 +1038,12 @@ _read${n}(void) 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) { diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index b0c9c5f2ef..98fe1abaa2 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -303,26 +303,26 @@ typedef struct A_Expr /* * A_Const - a literal constant + * + * Value nodes are inline for performance. You can treat 'val' as a node, + * as in IsA(&val, Integer). 'val' is not valid if isnull is true. */ +union ValUnion +{ + Node node; + Integer ival; + Float fval; + Boolean boolval; + String sval; + BitString bsval; +}; + typedef struct A_Const { pg_node_attr(custom_copy_equal, custom_read_write, no_read) NodeTag type; - - /* - * Value nodes are inline for performance. You can treat 'val' as a node, - * as in IsA(&val, Integer). 'val' is not valid if isnull is true. - */ - union ValUnion - { - Node node; - Integer ival; - Float fval; - Boolean boolval; - String sval; - BitString bsval; - } val; + union ValUnion val; bool isnull; /* SQL NULL constant */ int location; /* token location, or -1 if unknown */ } A_Const;
В списке pgsql-hackers по дате отправления:
Предыдущее
От: Justin PryzbyДата:
Сообщение: Re: fix stats_fetch_consistency value in postgresql.conf.sample
Следующее
От: Masahiko SawadaДата:
Сообщение: Re: [BUG] Logical replication failure "ERROR: could not map filenode "base/13237/442428" to relation OID" with catalog modifying txns