Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit af119e0

Browse files
committed
Dump more fields when dumping planner internal data structures.
Commit 964d01a marked a lot of fields as read_write_ignore to stay consistent with what was dumped by the manually-maintained outfuncs.c code. However, it seems that a pretty fair number of those omissions were either flat-out oversights, or a shortcut taken because hand-written code seemed like it'd be too much trouble. Let's upgrade things where it seems to make sense to dump. To do this, we need to add support to gen_node_support.pl and outfuncs.c for variable-length arrays of Node pointers. That's pretty straightforward given the model of the existing code for arrays of scalars, but I found I needed to tighten the type-recognizing regexes in gen_node_support.pl. (As they stood, they mistook "foo **" for "foo *". Make sure they're all fully anchored to prevent additional problems.) The main thing left un-done here is that a lot of partitioning-related structs are still not dumped, because they are bare structs not Nodes. I'm not sure about the wisdom of that choice ... but changing it would be fairly invasive, so it probably requires more justification than just making planner node dumps more complete. Discussion: https://postgr.es/m/1295668.1658258637@sss.pgh.pa.us
1 parent 6c31ac0 commit af119e0

File tree

3 files changed

+123
-61
lines changed

3 files changed

+123
-61
lines changed

src/backend/nodes/gen_node_support.pl

+47-21
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@
2828

2929
my $output_path = '.';
3030

31-
GetOptions(
32-
'outdir:s' => \$output_path)
31+
GetOptions('outdir:s' => \$output_path)
3332
or die "$0: wrong arguments";
3433

3534

@@ -441,6 +440,8 @@ sub elem
441440
$type =~ s/\s*$//;
442441
# strip space between type and "*" (pointer) */
443442
$type =~ s/\s+\*$/*/;
443+
# strip space between type and "**" (array of pointers) */
444+
$type =~ s/\s+\*\*$/**/;
444445

445446
die
446447
"$infile:$lineno: cannot parse data type in \"$line\"\n"
@@ -583,7 +584,8 @@ sub elem
583584
# nodetags.h
584585

585586
push @output_files, 'nodetags.h';
586-
open my $nt, '>', "$output_path/nodetags.h$tmpext" or die "$output_path/nodetags.h$tmpext: $!";
587+
open my $nt, '>', "$output_path/nodetags.h$tmpext"
588+
or die "$output_path/nodetags.h$tmpext: $!";
587589

588590
printf $nt $header_comment, 'nodetags.h';
589591

@@ -745,8 +747,8 @@ sub elem
745747
unless $equal_ignore || $t eq 'CoercionForm';
746748
}
747749
}
748-
# scalar type pointer
749-
elsif ($t =~ /(\w+)\*/ and elem $1, @scalar_types)
750+
# arrays of scalar types
751+
elsif ($t =~ /^(\w+)\*$/ and elem $1, @scalar_types)
750752
{
751753
my $tt = $1;
752754
if (!defined $array_size_field)
@@ -780,13 +782,14 @@ sub elem
780782
print $eff "\tCOMPARE_SCALAR_FIELD($f);\n" unless $equal_ignore;
781783
}
782784
# node type
783-
elsif ($t =~ /(\w+)\*/ and elem $1, @node_types)
785+
elsif (($t =~ /^(\w+)\*$/ or $t =~ /^struct\s+(\w+)\*$/)
786+
and elem $1, @node_types)
784787
{
785788
print $cff "\tCOPY_NODE_FIELD($f);\n" unless $copy_ignore;
786789
print $eff "\tCOMPARE_NODE_FIELD($f);\n" unless $equal_ignore;
787790
}
788791
# array (inline)
789-
elsif ($t =~ /\w+\[/)
792+
elsif ($t =~ /^\w+\[\w+\]$/)
790793
{
791794
print $cff "\tCOPY_ARRAY_FIELD($f);\n" unless $copy_ignore;
792795
print $eff "\tCOMPARE_ARRAY_FIELD($f);\n" unless $equal_ignore;
@@ -894,11 +897,16 @@ sub elem
894897
my @a = @{ $node_type_info{$n}->{field_attrs}{$f} };
895898

896899
# extract per-field attributes
897-
my $read_write_ignore = 0;
900+
my $array_size_field;
898901
my $read_as_field;
902+
my $read_write_ignore = 0;
899903
foreach my $a (@a)
900904
{
901-
if ($a =~ /^read_as\(([\w.]+)\)$/)
905+
if ($a =~ /^array_size\(([\w.]+)\)$/)
906+
{
907+
$array_size_field = $1;
908+
}
909+
elsif ($a =~ /^read_as\(([\w.]+)\)$/)
902910
{
903911
$read_as_field = $1;
904912
}
@@ -1015,19 +1023,10 @@ sub elem
10151023
print $off "\tWRITE_ENUM_FIELD($f, $t);\n";
10161024
print $rff "\tREAD_ENUM_FIELD($f, $t);\n" unless $no_read;
10171025
}
1018-
# arrays
1019-
elsif ($t =~ /(\w+)(\*|\[)/ and elem $1, @scalar_types)
1026+
# arrays of scalar types
1027+
elsif ($t =~ /^(\w+)(\*|\[\w+\])$/ and elem $1, @scalar_types)
10201028
{
10211029
my $tt = uc $1;
1022-
my $array_size_field;
1023-
foreach my $a (@a)
1024-
{
1025-
if ($a =~ /^array_size\(([\w.]+)\)$/)
1026-
{
1027-
$array_size_field = $1;
1028-
last;
1029-
}
1030-
}
10311030
if (!defined $array_size_field)
10321031
{
10331032
die "no array size defined for $n.$f of type $t\n";
@@ -1080,11 +1079,38 @@ sub elem
10801079
. "\t\toutBitmapset(str, NULL);\n";
10811080
}
10821081
# node type
1083-
elsif ($t =~ /(\w+)\*/ and elem $1, @node_types)
1082+
elsif (($t =~ /^(\w+)\*$/ or $t =~ /^struct\s+(\w+)\*$/)
1083+
and elem $1, @node_types)
10841084
{
10851085
print $off "\tWRITE_NODE_FIELD($f);\n";
10861086
print $rff "\tREAD_NODE_FIELD($f);\n" unless $no_read;
10871087
}
1088+
# arrays of node pointers (currently supported for write only)
1089+
elsif (($t =~ /^(\w+)\*\*$/ or $t =~ /^struct\s+(\w+)\*\*$/)
1090+
and elem($1, @node_types))
1091+
{
1092+
if (!defined $array_size_field)
1093+
{
1094+
die "no array size defined for $n.$f of type $t\n";
1095+
}
1096+
if ($node_type_info{$n}->{field_types}{$array_size_field} eq
1097+
'List*')
1098+
{
1099+
print $off
1100+
"\tWRITE_NODE_ARRAY($f, list_length(node->$array_size_field));\n";
1101+
print $rff
1102+
"\tREAD_NODE_ARRAY($f, list_length(local_node->$array_size_field));\n"
1103+
unless $no_read;
1104+
}
1105+
else
1106+
{
1107+
print $off
1108+
"\tWRITE_NODE_ARRAY($f, node->$array_size_field);\n";
1109+
print $rff
1110+
"\tREAD_NODE_ARRAY($f, local_node->$array_size_field);\n"
1111+
unless $no_read;
1112+
}
1113+
}
10881114
elsif ($t eq 'struct CustomPathMethods*'
10891115
|| $t eq 'struct CustomScanMethods*')
10901116
{

src/backend/nodes/outfuncs.c

+28
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ static void outChar(StringInfo str, char c);
9797
(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
9898
outBitmapset(str, node->fldname))
9999

100+
/* Write a variable-length array (not a List) of Node pointers */
101+
#define WRITE_NODE_ARRAY(fldname, len) \
102+
(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
103+
writeNodeArray(str, (const Node * const *) node->fldname, len))
104+
100105
/* Write a variable-length array of AttrNumber */
101106
#define WRITE_ATTRNUMBER_ARRAY(fldname, len) \
102107
(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
@@ -208,6 +213,29 @@ WRITE_SCALAR_ARRAY(writeIndexCols, Index, " %u",)
208213
WRITE_SCALAR_ARRAY(writeIntCols, int, " %d",)
209214
WRITE_SCALAR_ARRAY(writeBoolCols, bool, " %s", booltostr)
210215

216+
/*
217+
* Print an array (not a List) of Node pointers.
218+
*
219+
* The decoration is identical to that of scalar arrays, but we can't
220+
* quite use appendStringInfo() in the loop.
221+
*/
222+
static void
223+
writeNodeArray(StringInfo str, const Node *const *arr, int len)
224+
{
225+
if (arr != NULL)
226+
{
227+
appendStringInfoChar(str, '(');
228+
for (int i = 0; i < len; i++)
229+
{
230+
appendStringInfoChar(str, ' ');
231+
outNode(str, arr[i]);
232+
}
233+
appendStringInfoChar(str, ')');
234+
}
235+
else
236+
appendStringInfoString(str, "<>");
237+
}
238+
211239
/*
212240
* Print a List.
213241
*/

src/include/nodes/pathnodes.h

+48-40
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ typedef enum UpperRelationKind
8989
* planned.
9090
*
9191
* Not all fields are printed. (In some cases, there is no print support for
92-
* the field type.)
92+
* the field type; in others, doing so would lead to infinite recursion.)
9393
*----------
9494
*/
9595
typedef struct PlannerGlobal
@@ -177,7 +177,8 @@ typedef struct PlannerGlobal
177177
* either here or in that header, whichever is read first.
178178
*
179179
* Not all fields are printed. (In some cases, there is no print support for
180-
* the field type.)
180+
* the field type; in others, doing so would lead to infinite recursion or
181+
* bloat dump output more than seems useful.)
181182
*----------
182183
*/
183184
#ifndef HAVE_PLANNERINFO_TYPEDEF
@@ -220,22 +221,24 @@ struct PlannerInfo
220221
* does not correspond to a base relation, such as a join RTE or an
221222
* unreferenced view RTE; or if the RelOptInfo hasn't been made yet.
222223
*/
223-
struct RelOptInfo **simple_rel_array pg_node_attr(read_write_ignore);
224+
struct RelOptInfo **simple_rel_array pg_node_attr(array_size(simple_rel_array_size));
224225
/* allocated size of array */
225-
int simple_rel_array_size pg_node_attr(read_write_ignore);
226+
int simple_rel_array_size;
226227

227228
/*
228229
* simple_rte_array is the same length as simple_rel_array and holds
229230
* pointers to the associated rangetable entries. Using this is a shade
230-
* faster than using rt_fetch(), mostly due to fewer indirections.
231+
* faster than using rt_fetch(), mostly due to fewer indirections. (Not
232+
* printed because it'd be redundant with parse->rtable.)
231233
*/
232234
RangeTblEntry **simple_rte_array pg_node_attr(read_write_ignore);
233235

234236
/*
235237
* append_rel_array is the same length as the above arrays, and holds
236238
* pointers to the corresponding AppendRelInfo entry indexed by
237239
* child_relid, or NULL if the rel is not an appendrel child. The array
238-
* itself is not allocated if append_rel_list is empty.
240+
* itself is not allocated if append_rel_list is empty. (Not printed
241+
* because it'd be redundant with append_rel_list.)
239242
*/
240243
struct AppendRelInfo **append_rel_array pg_node_attr(read_write_ignore);
241244

@@ -273,6 +276,9 @@ struct PlannerInfo
273276
* join_cur_level is the current level. New join-relation RelOptInfos are
274277
* automatically added to the join_rel_level[join_cur_level] list.
275278
* join_rel_level is NULL if not in use.
279+
*
280+
* Note: we've already printed all baserel and joinrel RelOptInfos above,
281+
* so we don't dump join_rel_level or other lists of RelOptInfos.
276282
*/
277283
/* lists of join-relation RelOptInfos */
278284
List **join_rel_level pg_node_attr(read_write_ignore);
@@ -403,8 +409,8 @@ struct PlannerInfo
403409
/*
404410
* Fields filled during create_plan() for use in setrefs.c
405411
*/
406-
/* for GroupingFunc fixup */
407-
AttrNumber *grouping_map pg_node_attr(array_size(update_colnos), read_write_ignore);
412+
/* for GroupingFunc fixup (can't print: array length not known here) */
413+
AttrNumber *grouping_map pg_node_attr(read_write_ignore);
408414
/* List of MinMaxAggInfos */
409415
List *minmax_aggs;
410416

@@ -458,7 +464,7 @@ struct PlannerInfo
458464
/* PARAM_EXEC ID for the work table */
459465
int wt_param_id;
460466
/* a path for non-recursive term */
461-
struct Path *non_recursive_path pg_node_attr(read_write_ignore);
467+
struct Path *non_recursive_path;
462468

463469
/*
464470
* These fields are workspace for createplan.c
@@ -470,7 +476,9 @@ struct PlannerInfo
470476

471477
/*
472478
* These fields are workspace for setrefs.c. Each is an array
473-
* corresponding to glob->subplans.
479+
* corresponding to glob->subplans. (We could probably teach
480+
* gen_node_support.pl how to determine the array length, but it doesn't
481+
* seem worth the trouble, so just mark them read_write_ignore.)
474482
*/
475483
bool *isAltSubplan pg_node_attr(read_write_ignore);
476484
bool *isUsedSubplan pg_node_attr(read_write_ignore);
@@ -928,16 +936,17 @@ typedef struct RelOptInfo
928936
* Number of partitions; -1 if not yet set; in case of a join relation 0
929937
* means it's considered unpartitioned
930938
*/
931-
int nparts pg_node_attr(read_write_ignore);
939+
int nparts;
932940
/* Partition bounds */
933941
struct PartitionBoundInfoData *boundinfo pg_node_attr(read_write_ignore);
934942
/* True if partition bounds were created by partition_bounds_merge() */
935943
bool partbounds_merged;
936944
/* Partition constraint, if not the root */
937-
List *partition_qual pg_node_attr(read_write_ignore);
945+
List *partition_qual;
938946

939947
/*
940948
* Array of RelOptInfos of partitions, stored in the same order as bounds
949+
* (don't print, too bulky and duplicative)
941950
*/
942951
struct RelOptInfo **part_rels pg_node_attr(read_write_ignore);
943952

@@ -948,6 +957,12 @@ typedef struct RelOptInfo
948957
Bitmapset *live_parts;
949958
/* Relids set of all partition relids */
950959
Relids all_partrels;
960+
961+
/*
962+
* These arrays are of length partkey->partnatts, which we don't have at
963+
* hand, so don't try to print
964+
*/
965+
951966
/* Non-nullable partition key expressions */
952967
List **partexprs pg_node_attr(read_write_ignore);
953968
/* Nullable partition key expressions */
@@ -1042,30 +1057,26 @@ struct IndexOptInfo
10421057
int nkeycolumns;
10431058

10441059
/*
1045-
* array fields aren't really worth the trouble to print
1046-
*/
1047-
1048-
/*
1049-
* column numbers of index's attributes both key and included columns, or
1050-
* 0
1060+
* table column numbers of index's columns (both key and included
1061+
* columns), or 0 for expression columns
10511062
*/
1052-
int *indexkeys pg_node_attr(read_write_ignore);
1063+
int *indexkeys pg_node_attr(array_size(ncolumns));
10531064
/* OIDs of collations of index columns */
1054-
Oid *indexcollations pg_node_attr(read_write_ignore);
1065+
Oid *indexcollations pg_node_attr(array_size(nkeycolumns));
10551066
/* OIDs of operator families for columns */
1056-
Oid *opfamily pg_node_attr(read_write_ignore);
1067+
Oid *opfamily pg_node_attr(array_size(nkeycolumns));
10571068
/* OIDs of opclass declared input data types */
1058-
Oid *opcintype pg_node_attr(read_write_ignore);
1069+
Oid *opcintype pg_node_attr(array_size(nkeycolumns));
10591070
/* OIDs of btree opfamilies, if orderable */
1060-
Oid *sortopfamily pg_node_attr(read_write_ignore);
1071+
Oid *sortopfamily pg_node_attr(array_size(nkeycolumns));
10611072
/* is sort order descending? */
1062-
bool *reverse_sort pg_node_attr(read_write_ignore);
1073+
bool *reverse_sort pg_node_attr(array_size(nkeycolumns));
10631074
/* do NULLs come first in the sort order? */
1064-
bool *nulls_first pg_node_attr(read_write_ignore);
1075+
bool *nulls_first pg_node_attr(array_size(nkeycolumns));
10651076
/* opclass-specific options for columns */
10661077
bytea **opclassoptions pg_node_attr(read_write_ignore);
10671078
/* which index cols can be returned in an index-only scan? */
1068-
bool *canreturn pg_node_attr(read_write_ignore);
1079+
bool *canreturn pg_node_attr(array_size(ncolumns));
10691080
/* OID of the access method (in pg_am) */
10701081
Oid relam;
10711082

@@ -1098,19 +1109,19 @@ struct IndexOptInfo
10981109

10991110
/*
11001111
* Remaining fields are copied from the index AM's API struct
1101-
* (IndexAmRoutine). We don't bother to dump them.
1112+
* (IndexAmRoutine).
11021113
*/
1103-
bool amcanorderbyop pg_node_attr(read_write_ignore);
1104-
bool amoptionalkey pg_node_attr(read_write_ignore);
1105-
bool amsearcharray pg_node_attr(read_write_ignore);
1106-
bool amsearchnulls pg_node_attr(read_write_ignore);
1114+
bool amcanorderbyop;
1115+
bool amoptionalkey;
1116+
bool amsearcharray;
1117+
bool amsearchnulls;
11071118
/* does AM have amgettuple interface? */
1108-
bool amhasgettuple pg_node_attr(read_write_ignore);
1119+
bool amhasgettuple;
11091120
/* does AM have amgetbitmap interface? */
1110-
bool amhasgetbitmap pg_node_attr(read_write_ignore);
1111-
bool amcanparallel pg_node_attr(read_write_ignore);
1121+
bool amhasgetbitmap;
1122+
bool amcanparallel;
11121123
/* does AM have ammarkpos interface? */
1113-
bool amcanmarkpos pg_node_attr(read_write_ignore);
1124+
bool amcanmarkpos;
11141125
/* AM's cost estimator */
11151126
/* Rather than include amapi.h here, we declare amcostestimate like this */
11161127
void (*amcostestimate) () pg_node_attr(read_write_ignore);
@@ -1184,12 +1195,9 @@ typedef struct StatisticExtInfo
11841195
Oid statOid;
11851196

11861197
/* includes child relations */
1187-
bool inherit pg_node_attr(read_write_ignore);
1198+
bool inherit;
11881199

1189-
/*
1190-
* back-link to statistic's table; don't print, infinite recursion on plan
1191-
* tree dump
1192-
*/
1200+
/* back-link to statistic's table; don't print, else infinite recursion */
11931201
RelOptInfo *rel pg_node_attr(read_write_ignore);
11941202

11951203
/* statistics kind of this entry */

0 commit comments

Comments
 (0)