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