Add support for custom_query_jumble as a node field attribute
authorMichael Paquier <michael@paquier.xyz>
Tue, 25 Mar 2025 05:18:00 +0000 (14:18 +0900)
committerMichael Paquier <michael@paquier.xyz>
Tue, 25 Mar 2025 05:18:00 +0000 (14:18 +0900)
This option gives the possibility for query jumble to define a custom
routine for the field of a Node, extending support for
custom_query_jumble as a node field attribute.  When dealing with
complex node structures, this can be simpler than having to enforce a
custom function across a full node.

Custom functions need to be defined in queryjumblefuncs.c, named as
_jumble${node}_${field}(), and use in input the JumbleState, the node
and its field.  The field is not really required if we have the Node,
but it makes custom implementations somewhat easier to think about.  The
code generated by gen_node_support.pl uses a macro called
JUMBLE_CUSTOM(), hiding the internals of the logic inside
queryjumblefuncs.c.

This will be used by an upcoming patch manipulating adding a custom
routine into a field of RangeTblEntry, but this facility can become
useful in more cases.

Reviewed-by: Christoph Berg <myon@debian.org>
Discussion: https://postgr.es/m/Z9y43-dRvb4EtxQ0@paquier.xyz

src/backend/nodes/gen_node_support.pl
src/backend/nodes/queryjumblefuncs.c
src/include/nodes/nodes.h

index 7e3f335ac09df8790095e1bc630a967b571df084..40994b53fb28a2360fd8f705d57e30fe6c7a4ef0 100644 (file)
@@ -471,6 +471,7 @@ foreach my $infile (@ARGV)
                                && $attr !~ /^read_as\(\w+\)$/
                                && !elem $attr,
                                qw(copy_as_scalar
+                               custom_query_jumble
                                equal_as_scalar
                                equal_ignore
                                equal_ignore_if_zero
@@ -1283,12 +1284,17 @@ _jumble${n}(JumbleState *jstate, Node *node)
        my $t = $node_type_info{$n}->{field_types}{$f};
        my @a = @{ $node_type_info{$n}->{field_attrs}{$f} };
        my $query_jumble_ignore = $struct_no_query_jumble;
+       my $query_jumble_custom = 0;
        my $query_jumble_location = 0;
        my $query_jumble_squash = 0;
 
        # extract per-field attributes
        foreach my $a (@a)
        {
+           if ($a eq 'custom_query_jumble')
+           {
+               $query_jumble_custom = 1;
+           }
            if ($a eq 'query_jumble_ignore')
            {
                $query_jumble_ignore = 1;
@@ -1304,7 +1310,12 @@ _jumble${n}(JumbleState *jstate, Node *node)
        }
 
        # node type
-       if (($t =~ /^(\w+)\*$/ or $t =~ /^struct\s+(\w+)\*$/)
+       if ($query_jumble_custom)
+       {
+           # Custom function that applies to one field of a node.
+           print $jff "\tJUMBLE_CUSTOM($n, $f);\n";
+       }
+       elsif (($t =~ /^(\w+)\*$/ or $t =~ /^struct\s+(\w+)\*$/)
            and elem $1, @node_types)
        {
            # Squash constants if requested.
index 189bfda610aa77674d23a527ab6d4c1661c28b00..f8b0f91704ba7ec12c920f31ab6d039afbb2aa5d 100644 (file)
@@ -333,6 +333,9 @@ do { \
    if (expr->str) \
        AppendJumble(jstate, (const unsigned char *) (expr->str), strlen(expr->str) + 1); \
 } while(0)
+/* Function name used for the node field attribute custom_query_jumble. */
+#define JUMBLE_CUSTOM(nodetype, item) \
+   _jumble##nodetype##_##item(jstate, expr, expr->item)
 
 #include "queryjumblefuncs.funcs.c"
 
index d18044b4e650d61de22202e664e7e040e7444ba6..fbe333d88fac97520e33997c958444e49d0d99dd 100644 (file)
@@ -54,6 +54,7 @@ typedef enum NodeTag
  *   readfuncs.c.
  *
  * - custom_query_jumble: Has custom implementation in queryjumblefuncs.c.
+ *   Also available as a node field attribute.
  *
  * - no_copy: Does not support copyObject() at all.
  *
@@ -101,6 +102,9 @@ typedef enum NodeTag
  * - equal_ignore_if_zero: Ignore the field for equality if it is zero.
  *   (Otherwise, compare normally.)
  *
+ * - custom_query_jumble: Has custom implementation in queryjumblefuncs.c
+ *   for the field of a node.  Also available as a node attribute.
+ *
  * - query_jumble_ignore: Ignore the field for the query jumbling.  Note
  *   that typmod and collation information are usually irrelevant for the
  *   query jumbling.