From fa1e1ee90bb029882952d066e39f2f75a191c71f Mon Sep 17 00:00:00 2001 From: John Naylor Date: Wed, 20 Dec 2017 11:45:37 +0700 Subject: [PATCH v4 11/12] Reduce indentation level A previous commit removed a logical block level from Catalog.pm, but kept the indentation for the sake of patch readability. Fix that here. Separate out the pg_attribute logic of genbki.pl into its own function and skip checking if the data is defined. This both narrows and shortens the data writing loop of the script. --- src/backend/catalog/Catalog.pm | 224 +++++++++++++------------- src/backend/catalog/genbki.pl | 350 +++++++++++++++++++++-------------------- 2 files changed, 288 insertions(+), 286 deletions(-) diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm index c1ea8c6..e19a474 100644 --- a/src/backend/catalog/Catalog.pm +++ b/src/backend/catalog/Catalog.pm @@ -33,149 +33,149 @@ sub ParseHeader 'TransactionId' => 'xid', 'XLogRecPtr' => 'pg_lsn'); - my $declaring_attributes; - my %catalog; - $catalog{columns} = []; - $catalog{toasting} = []; - $catalog{indexing} = []; - my $is_varlen = 0; + my $declaring_attributes; + my %catalog; + $catalog{columns} = []; + $catalog{toasting} = []; + $catalog{indexing} = []; + my $is_varlen = 0; - open(my $ifh, '<', $input_file) || die "$input_file: $!"; + open(my $ifh, '<', $input_file) || die "$input_file: $!"; - # Scan the input file. - while (<$ifh>) + # Scan the input file. + while (<$ifh>) + { + + # Strip C-style comments. + s;/\*(.|\n)*\*/;;g; + if (m;/\*;) { - # Strip C-style comments. - s;/\*(.|\n)*\*/;;g; - if (m;/\*;) - { + # handle multi-line comments properly. + my $next_line = <$ifh>; + die "$input_file: ends within C-style comment\n" + if !defined $next_line; + $_ .= $next_line; + redo; + } - # handle multi-line comments properly. - my $next_line = <$ifh>; - die "$input_file: ends within C-style comment\n" - if !defined $next_line; - $_ .= $next_line; - redo; - } + # Strip useless whitespace and trailing semicolons. + chomp; + s/^\s+//; + s/;\s*$//; + s/\s+/ /g; - # Strip useless whitespace and trailing semicolons. - chomp; - s/^\s+//; - s/;\s*$//; - s/\s+/ /g; + # Push the data into the appropriate data structure. + if (/^DECLARE_TOAST\(\s*(\w+),\s*(\d+),\s*(\d+)\)/) + { + my ($toast_name, $toast_oid, $index_oid) = ($1, $2, $3); + push @{ $catalog{toasting} }, + "declare toast $toast_oid $index_oid on $toast_name\n"; + } + elsif (/^DECLARE_(UNIQUE_)?INDEX\(\s*(\w+),\s*(\d+),\s*(.+)\)/) + { + my ($is_unique, $index_name, $index_oid, $using) = + ($1, $2, $3, $4); + push @{ $catalog{indexing} }, + sprintf( + "declare %sindex %s %s %s\n", + $is_unique ? 'unique ' : '', + $index_name, $index_oid, $using); + } + elsif (/^BUILD_INDICES/) + { + push @{ $catalog{indexing} }, "build indices\n"; + } + elsif (/^CATALOG\(([^,]*),(\d+)\)/) + { + $catalog{catname} = $1; + $catalog{relation_oid} = $2; - # Push the data into the appropriate data structure. - if (/^DECLARE_TOAST\(\s*(\w+),\s*(\d+),\s*(\d+)\)/) - { - my ($toast_name, $toast_oid, $index_oid) = ($1, $2, $3); - push @{ $catalog{toasting} }, - "declare toast $toast_oid $index_oid on $toast_name\n"; - } - elsif (/^DECLARE_(UNIQUE_)?INDEX\(\s*(\w+),\s*(\d+),\s*(.+)\)/) + $catalog{bootstrap} = /BKI_BOOTSTRAP/ ? ' bootstrap' : ''; + $catalog{shared_relation} = + /BKI_SHARED_RELATION/ ? ' shared_relation' : ''; + $catalog{without_oids} = + /BKI_WITHOUT_OIDS/ ? ' without_oids' : ''; + $catalog{rowtype_oid} = + /BKI_ROWTYPE_OID\((\d+)\)/ ? " rowtype_oid $1" : ''; + $catalog{schema_macro} = /BKI_SCHEMA_MACRO/ ? 1 : 0; + $declaring_attributes = 1; + } + elsif ($declaring_attributes) + { + next if (/^{|^$/); + if (/^#/) { - my ($is_unique, $index_name, $index_oid, $using) = - ($1, $2, $3, $4); - push @{ $catalog{indexing} }, - sprintf( - "declare %sindex %s %s %s\n", - $is_unique ? 'unique ' : '', - $index_name, $index_oid, $using); + if (/^#ifdef\s+CATALOG_VARLEN/) + { + $is_varlen = 1; + } + next; } - elsif (/^BUILD_INDICES/) + if (/^}/) { - push @{ $catalog{indexing} }, "build indices\n"; + undef $declaring_attributes; } - elsif (/^CATALOG\(([^,]*),(\d+)\)/) + else { - $catalog{catname} = $1; - $catalog{relation_oid} = $2; + my %column; + if ($is_varlen) + { + $column{is_varlen} = 1; + } + my @attopts = split /\s+/, $_; + my $atttype = shift @attopts; + my $attname = shift @attopts; + die "parse error ($input_file)" + unless ($attname and $atttype); - $catalog{bootstrap} = /BKI_BOOTSTRAP/ ? ' bootstrap' : ''; - $catalog{shared_relation} = - /BKI_SHARED_RELATION/ ? ' shared_relation' : ''; - $catalog{without_oids} = - /BKI_WITHOUT_OIDS/ ? ' without_oids' : ''; - $catalog{rowtype_oid} = - /BKI_ROWTYPE_OID\((\d+)\)/ ? " rowtype_oid $1" : ''; - $catalog{schema_macro} = /BKI_SCHEMA_MACRO/ ? 1 : 0; - $declaring_attributes = 1; - } - elsif ($declaring_attributes) - { - next if (/^{|^$/); - if (/^#/) + if (exists $RENAME_ATTTYPE{$atttype}) { - if (/^#ifdef\s+CATALOG_VARLEN/) - { - $is_varlen = 1; - } - next; + $atttype = $RENAME_ATTTYPE{$atttype}; } - if (/^}/) + if ($attname =~ /(.*)\[.*\]/) # array attribute { - undef $declaring_attributes; + $attname = $1; + $atttype .= '[]'; } - else + + $column{type} = $atttype; + $column{name} = $attname; + + foreach my $attopt (@attopts) { - my %column; - if ($is_varlen) + if ($attopt eq 'BKI_FORCE_NULL') { - $column{is_varlen} = 1; + $column{forcenull} = 1; } - my @attopts = split /\s+/, $_; - my $atttype = shift @attopts; - my $attname = shift @attopts; - die "parse error ($input_file)" - unless ($attname and $atttype); - - if (exists $RENAME_ATTTYPE{$atttype}) + elsif ($attopt eq 'BKI_FORCE_NOT_NULL') { - $atttype = $RENAME_ATTTYPE{$atttype}; + $column{forcenotnull} = 1; } - if ($attname =~ /(.*)\[.*\]/) # array attribute + elsif ($attopt =~ /BKI_DEFAULT\((\S+)\)/) { - $attname = $1; - $atttype .= '[]'; + $column{default} = $1; } - - $column{type} = $atttype; - $column{name} = $attname; - - foreach my $attopt (@attopts) + elsif ($attopt =~ /BKI_ABBREV\((\S+)\)/) + { + $column{abbrev} = $1; + } + else { - if ($attopt eq 'BKI_FORCE_NULL') - { - $column{forcenull} = 1; - } - elsif ($attopt eq 'BKI_FORCE_NOT_NULL') - { - $column{forcenotnull} = 1; - } - elsif ($attopt =~ /BKI_DEFAULT\((\S+)\)/) - { - $column{default} = $1; - } - elsif ($attopt =~ /BKI_ABBREV\((\S+)\)/) - { - $column{abbrev} = $1; - } - else - { - die + die "unknown column option $attopt on column $attname"; - } + } - if ($column{forcenull} and $column{forcenotnull}) - { - die "$attname is forced both null and not null"; - } + if ($column{forcenull} and $column{forcenotnull}) + { + die "$attname is forced both null and not null"; } - push @{ $catalog{columns} }, \%column; } + push @{ $catalog{columns} }, \%column; } } - close $ifh; + } + close $ifh; return \%catalog; } diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl index 62bb503..2570fd3 100644 --- a/src/backend/catalog/genbki.pl +++ b/src/backend/catalog/genbki.pl @@ -252,201 +252,126 @@ foreach my $catname (@catnames) print $bki "open $catname\n"; } - if (defined $catalog_data{$catname}) - { - - # Ordinary catalog with a data file - foreach my $row (@{ $catalog_data{$catname} }) - { - my %bki_values = %$row; - - # Perform required substitutions on fields - foreach my $column (@$schema) - { - my $attname = $column->{name}; - my $atttype = $column->{type}; - - # Substitute constant values we acquired above. - # (It's intentional that this can apply to parts of a field). - $bki_values{$attname} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g; - $bki_values{$attname} =~ s/\bPGNSP\b/$PG_CATALOG_NAMESPACE/g; - - # Replace reg* columns' values with OIDs. - if ($atttype eq 'regproc') - { - my $procoid = $regprocoids{ $bki_values{$attname} }; - - # If we don't have a unique value to substitute, - # just do nothing (regprocin will complain). - $bki_values{$attname} = $procoid - if defined($procoid) && $procoid ne 'MULTIPLE'; - } - elsif ($atttype eq 'regam') - { - my $amoid = $regamoids{ $bki_values{$attname} }; - $bki_values{$attname} = $amoid - if defined($amoid); - } - elsif ($atttype eq 'regopf') - { - my $opfoid = $regopfoids{ $bki_values{$attname} }; - $bki_values{$attname} = $opfoid - if defined($opfoid); - } - elsif ($atttype eq 'regoper') - { - my $operoid = $regoperoids{ $bki_values{$attname} }; - $bki_values{$attname} = $operoid - if defined($operoid); - } - elsif ($atttype eq 'regtype') - { - my $typeoid = $regtypeoids{ $bki_values{$attname} }; - $bki_values{$attname} = $typeoid - if defined($typeoid); - } - } - - # We can't do regtype lookups in a general way for - # pg_proc, so do special handling here. - if ($catname eq 'pg_proc') - { - - # prorettype - # Note: We could handle this automatically by using the - # 'regtype' alias, but then we would have to teach - # emit_pgattr_row() to change the attribute type back to - # oid. Since we have to treat pg_proc differently anyway, - # just do the type lookup manually here. - my $rettypeoid = $regtypeoids{ $bki_values{prorettype}}; - $bki_values{prorettype} = $rettypeoid - if defined($rettypeoid); - - # proargtypes - if ($bki_values{proargtypes}) - { - my @argtypenames = split /\s+/, $bki_values{proargtypes}; - my @argtypeoids; - foreach my $argtypename (@argtypenames) - { - my $argtypeoid = $regtypeoids{$argtypename}; - push @argtypeoids, $argtypeoid; - } - $bki_values{proargtypes} = join(' ', @argtypeoids); - } - - # proallargtypes - if ($bki_values{proallargtypes} ne '_null_') - { - $bki_values{proallargtypes} =~ s/[{}]//g; - my @argtypenames = split /,/, $bki_values{proallargtypes}; - my @argtypeoids; - foreach my $argtypename (@argtypenames) - { - my $argtypeoid = $regtypeoids{$argtypename}; - push @argtypeoids, $argtypeoid; - } - $bki_values{proallargtypes} = - '{' . join(',', @argtypeoids) . '}'; - } - } - - # Add quotes where necessary. - quote_bki_values(\%bki_values, $schema); - - # Write to postgres.bki - bki_insert(\%bki_values, @attnames); - - # Write comments to postgres.description and - # postgres.shdescription - if (defined $bki_values{descr}) - { - printf $descr "%s\t%s\t0\t%s\n", - $bki_values{oid}, $catname, $bki_values{descr}; - } - if (defined $bki_values{shdescr}) - { - printf $shdescr "%s\t%s\t%s\n", - $bki_values{oid}, $catname, $bki_values{shdescr}; - } - } - } if ($catname eq 'pg_attribute') { + gen_pg_attribute($schema, @attnames); + } + + # Ordinary catalog with a data file + foreach my $row (@{ $catalog_data{$catname} }) + { + my %bki_values = %$row; - # For pg_attribute.h, we generate data entries ourselves. - foreach my $table_name (@catnames) + # Perform required substitutions on fields + foreach my $column (@$schema) { - my $table = $catalogs{$table_name}; + my $attname = $column->{name}; + my $atttype = $column->{type}; - # Currently, all bootstrapped relations also need schemapg.h - # entries, so skip if the relation isn't to be in schemapg.h. - next if !$table->{schema_macro}; + # Substitute constant values we acquired above. + # (It's intentional that this can apply to parts of a field). + $bki_values{$attname} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g; + $bki_values{$attname} =~ s/\bPGNSP\b/$PG_CATALOG_NAMESPACE/g; - $schemapg_entries{$table_name} = []; - push @tables_needing_macros, $table_name; + # Replace reg* columns' values with OIDs. + if ($atttype eq 'regproc') + { + my $procoid = $regprocoids{ $bki_values{$attname} }; - # Generate entries for user attributes. - my $attnum = 0; - my $priornotnull = 1; - my @user_attrs = @{ $table->{columns} }; - foreach my $attr (@user_attrs) + # If we don't have a unique value to substitute, + # just do nothing (regprocin will complain). + $bki_values{$attname} = $procoid + if defined($procoid) && $procoid ne 'MULTIPLE'; + } + elsif ($atttype eq 'regam') { - $attnum++; - my %row; - $row{attnum} = $attnum; - $row{attrelid} = $table->{relation_oid}; + my $amoid = $regamoids{ $bki_values{$attname} }; + $bki_values{$attname} = $amoid + if defined($amoid); + } + elsif ($atttype eq 'regopf') + { + my $opfoid = $regopfoids{ $bki_values{$attname} }; + $bki_values{$attname} = $opfoid + if defined($opfoid); + } + elsif ($atttype eq 'regoper') + { + my $operoid = $regoperoids{ $bki_values{$attname} }; + $bki_values{$attname} = $operoid + if defined($operoid); + } + elsif ($atttype eq 'regtype') + { + my $typeoid = $regtypeoids{ $bki_values{$attname} }; + $bki_values{$attname} = $typeoid + if defined($typeoid); + } + } - emit_pgattr_row(\%row, $attr, $priornotnull, $schema); - $priornotnull &= ($row{attnotnull} eq 't'); + # We can't do regtype lookups in a general way for + # pg_proc, so do special handling here. + if ($catname eq 'pg_proc') + { - # If it's bootstrapped, put an entry in postgres.bki. - if ($table->{bootstrap}) + # prorettype + # Note: We could handle this automatically by using the + # 'regtype' alias, but then we would have to teach + # emit_pgattr_row() to change the attribute type back to + # oid. Since we have to treat pg_proc differently anyway, + # just do the type lookup manually here. + my $rettypeoid = $regtypeoids{ $bki_values{prorettype}}; + $bki_values{prorettype} = $rettypeoid + if defined($rettypeoid); + + # proargtypes + if ($bki_values{proargtypes}) + { + my @argtypenames = split /\s+/, $bki_values{proargtypes}; + my @argtypeoids; + foreach my $argtypename (@argtypenames) { - bki_insert(\%row, @attnames); + my $argtypeoid = $regtypeoids{$argtypename}; + push @argtypeoids, $argtypeoid; } - - # Store schemapg entries for later. - emit_schemapg_row(\%row, $schema); - push @{ $schemapg_entries{$table_name} }, - sprintf "{ %s }", - join(', ', grep { defined $_ } @row{@attnames}); + $bki_values{proargtypes} = join(' ', @argtypeoids); } - # Generate entries for system attributes. - # We only need postgres.bki entries, not schemapg.h entries. - if ($table->{bootstrap}) + # proallargtypes + if ($bki_values{proallargtypes} ne '_null_') { - $attnum = 0; - my @SYS_ATTRS = ( - { name => 'ctid', type => 'tid' }, - { name => 'oid', type => 'oid' }, - { name => 'xmin', type => 'xid' }, - { name => 'cmin', type => 'cid' }, - { name => 'xmax', type => 'xid' }, - { name => 'cmax', type => 'cid' }, - { name => 'tableoid', type => 'oid' }); - foreach my $attr (@SYS_ATTRS) + $bki_values{proallargtypes} =~ s/[{}]//g; + my @argtypenames = split /,/, $bki_values{proallargtypes}; + my @argtypeoids; + foreach my $argtypename (@argtypenames) { - $attnum--; - my %row; - $row{attnum} = $attnum; - $row{attrelid} = $table->{relation_oid}; - $row{attstattarget} = '0'; + my $argtypeoid = $regtypeoids{$argtypename}; + push @argtypeoids, $argtypeoid; + } + $bki_values{proallargtypes} = + '{' . join(',', @argtypeoids) . '}'; + } + } - emit_pgattr_row(\%row, $attr, 1, $schema); + # Add quotes where necessary. + quote_bki_values(\%bki_values, $schema); - # some catalogs don't have oids - next - if $table->{without_oids} - && $row{attname} eq 'oid'; + # Write to postgres.bki + bki_insert(\%bki_values, @attnames); - bki_insert(\%row, @attnames); - } - } + # Write comments to postgres.description and + # postgres.shdescription + if (defined $bki_values{descr}) + { + printf $descr "%s\t%s\t0\t%s\n", + $bki_values{oid}, $catname, $bki_values{descr}; + } + if (defined $bki_values{shdescr}) + { + printf $shdescr "%s\t%s\t%s\n", + $bki_values{oid}, $catname, $bki_values{shdescr}; } } - print $bki "close $catname\n"; } @@ -557,6 +482,83 @@ sub quote_bki_values } } +# For pg_attribute.h, we generate data entries ourselves. +sub gen_pg_attribute +{ + my $schema = shift; + my @attnames = @_; + + foreach my $table_name (@catnames) + { + my $table = $catalogs{$table_name}; + + # Currently, all bootstrapped relations also need schemapg.h + # entries, so skip if the relation isn't to be in schemapg.h. + next if !$table->{schema_macro}; + + $schemapg_entries{$table_name} = []; + push @tables_needing_macros, $table_name; + + # Generate entries for user attributes. + my $attnum = 0; + my $priornotnull = 1; + my @user_attrs = @{ $table->{columns} }; + foreach my $attr (@user_attrs) + { + $attnum++; + my %row; + $row{attnum} = $attnum; + $row{attrelid} = $table->{relation_oid}; + + emit_pgattr_row(\%row, $attr, $priornotnull, $schema); + $priornotnull &= ($row{attnotnull} eq 't'); + + # If it's bootstrapped, put an entry in postgres.bki. + if ($table->{bootstrap}) + { + bki_insert(\%row, @attnames); + } + + # Store schemapg entries for later. + emit_schemapg_row(\%row, $schema); + push @{ $schemapg_entries{$table_name} }, + sprintf "{ %s }", + join(', ', grep { defined $_ } @row{@attnames}); + } + + # Generate entries for system attributes. + # We only need postgres.bki entries, not schemapg.h entries. + if ($table->{bootstrap}) + { + $attnum = 0; + my @SYS_ATTRS = ( + { name => 'ctid', type => 'tid' }, + { name => 'oid', type => 'oid' }, + { name => 'xmin', type => 'xid' }, + { name => 'cmin', type => 'cid' }, + { name => 'xmax', type => 'xid' }, + { name => 'cmax', type => 'cid' }, + { name => 'tableoid', type => 'oid' }); + foreach my $attr (@SYS_ATTRS) + { + $attnum--; + my %row; + $row{attnum} = $attnum; + $row{attrelid} = $table->{relation_oid}; + $row{attstattarget} = '0'; + + emit_pgattr_row(\%row, $attr, 1, $schema); + + # some catalogs don't have oids + next + if $table->{without_oids} + && $row{attname} eq 'oid'; + + bki_insert(\%row, @attnames); + } + } + } +} # Given the schema of pg_attribute, generate an entry for it using information # about the attribute it describes. Any value that is not handled here -- 2.7.4