On Sat, Mar 9, 2019 at 1:14 AM Tom Lane <t...@sss.pgh.pa.us> wrote: > I took a quick look at this. I went ahead and pushed the parts that > were just code cleanup in reformat_dat_file.pl, since that seemed > pretty uncontroversial. As far as the rest of it goes:
Okay, thanks. > * I'm really not terribly happy with sticking this functionality into > reformat_dat_file.pl. First, there's an issue of discoverability: > it's not obvious that a script named that way would have such an > ability. Second, it clutters the script in a way that seems to me > to hinder its usefulness as a basis for one-off hacks. So I'd really > rather have a separate script named something like "renumber_oids.pl", > even if there's a good deal of code duplication between it and > reformat_dat_file.pl. > * In my vision of what this might be good for, I think it's important > that it be possible to specify a range of input OIDs to renumber, not > just "everything above N". I agree the output range only needs a > starting OID. Now it looks like: perl renumber_oids.pl --first-mapped-oid 8000 --last-mapped-oid 8999 --first-target-oid 2000 *.dat To prevent a maintenance headache, I didn't copy any of the formatting logic over. You'll also have to run reformat_dat_files.pl afterwards to restore that. It seems to work, but I haven't tested thoroughly. -- John Naylor https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From c6f5a1f6016feeb7f7ea94e504be6d23a264ca07 Mon Sep 17 00:00:00 2001 From: John Naylor <jcnay...@gmail.com> Date: Mon, 11 Mar 2019 01:05:15 +0800 Subject: [PATCH v2] Provide script to renumber OIDs. Historically, It's been considered good practice to choose an OID that's at the beginning of the range shown by the unused_oids script, but nowadays that space is getting cramped, leading to merge conflicts. Instead, allow developers to use high-numbered OIDs, and remap them to a lower range at some future date. --- doc/src/sgml/bki.sgml | 16 +++ src/include/catalog/renumber_oids.pl | 193 +++++++++++++++++++++++++++ 2 files changed, 209 insertions(+) create mode 100644 src/include/catalog/renumber_oids.pl diff --git a/doc/src/sgml/bki.sgml b/doc/src/sgml/bki.sgml index 3c5830bc8a..7e553dc30d 100644 --- a/doc/src/sgml/bki.sgml +++ b/doc/src/sgml/bki.sgml @@ -392,6 +392,22 @@ at compile time.) </para> + <para> + For a variety of reasons, newly assigned OIDs should occupy the lower + end of the reserved range. Because multiple patches considered for + inclusion into <productname>PostgreSQL</productname> could be using + the same new OIDs, there is the possibilty of conflict. To mitigate + this, there is a convention that OIDs 8000 and over are reserved for + development. This reduces the effort in rebasing over the HEAD branch. + To enable committers to move these OIDs to the lower range easily, + <filename>renumber_oids.pl</filename> can map OIDs as in the following, + following, which maps any OIDs between 8000 and 8999, inclusive, to + unused OIDs starting at 2000: +<programlisting> +$ perl renumber_oids.pl --first-mapped-oid 8000 --last-mapped-oid 8999 --first-target-oid 2000 *.dat +</programlisting> + </para> + <para> The OID counter starts at 10000 at the beginning of a bootstrap run. If a row from a source other than <filename>postgres.bki</filename> diff --git a/src/include/catalog/renumber_oids.pl b/src/include/catalog/renumber_oids.pl new file mode 100644 index 0000000000..79537465bc --- /dev/null +++ b/src/include/catalog/renumber_oids.pl @@ -0,0 +1,193 @@ +#!/usr/bin/perl +#---------------------------------------------------------------------- +# +# renumber_oids.pl +# Perl script that shifts a range of high-numbered OIDs in the given +# catalog data file(s) to a lower range. +# +# Note: This does not format the output, so you will still need to +# run reformat_dat_file.pl. +# +# Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/include/catalog/renumber_oids.pl +# +#---------------------------------------------------------------------- + +use strict; +use warnings; + +use FindBin; +use Getopt::Long; +use Data::Dumper; +$Data::Dumper::Terse = 1; + +# If you copy this script to somewhere other than src/include/catalog, +# you'll need to modify this "use lib" or provide a suitable -I switch. +use lib "$FindBin::RealBin/../../backend/catalog/"; +use Catalog; + +# Must run in src/include/catalog +chdir $FindBin::RealBin or die "could not cd to $FindBin::RealBin: $!\n"; + +my $FirstGenbkiObjectId = + Catalog::FindDefinedSymbol('access/transam.h', '..', + 'FirstGenbkiObjectId'); + +# Process command line switches. +my $output_path = ''; +my $first_mapped_oid; +my $last_mapped_oid = $FirstGenbkiObjectId - 1; +my $first_target_oid = 1; + +GetOptions( + 'output:s' => \$output_path, + 'first-mapped-oid:i' => \$first_mapped_oid, + 'last-mapped-oid:i' => \$last_mapped_oid, + 'first-target-oid:i' => \$first_target_oid) || usage(); + +my $next_oid = $first_target_oid; + +# Sanity check arguments. +die "No input files.\n" unless @ARGV; +die "output range is higher than input range" + if $first_target_oid > $first_mapped_oid; + +# Make sure output_path ends in a slash. +if ($output_path ne '' && substr($output_path, -1) ne '/') +{ + $output_path .= '/'; +} + +# Read all the input files into internal data structures. +# We pass data file names as arguments and then look for matching +# headers to parse the schema from. +my %catalogs; +my %catalog_data; +my @catnames; +foreach my $datfile (@ARGV) +{ + $datfile =~ /(.+)\.dat$/ + or die "Input files need to be data (.dat) files.\n"; + + my $header = "$1.h"; + die "There in no header file corresponding to $datfile" + if !-e $header; + + my $catalog = Catalog::ParseHeader($header); + my $catname = $catalog->{catname}; + my $schema = $catalog->{columns}; + + push @catnames, $catname; + $catalogs{$catname} = $catalog; + + $catalog_data{$catname} = Catalog::ParseData($datfile, $schema, 1); +} + +# Collect all the assigned OIDs in numerical order. +my @header_files = (glob("pg_*.h"), qw(indexing.h toasting.h)); +my $oids = Catalog::FindAllOidsFromHeaders(@header_files); +my @oids = sort { $a <=> $b } @$oids; + +# Write the data. +foreach my $catname (@catnames) +{ + my $catalog = $catalogs{$catname}; + my @attnames; + my $schema = $catalog->{columns}; + + foreach my $column (@$schema) + { + my $attname = $column->{name}; + push @attnames, $attname + } + + # Write output files to specified directory. + my $datfile = "$output_path$catname.dat"; + open my $dat, '>', $datfile + or die "can't open $datfile: $!"; + + foreach my $data (@{ $catalog_data{$catname} }) + { + # Hash ref representing a data entry. + if (ref $data eq 'HASH') + { + my %values = %$data; + + $values{oid} = get_lower_oid($values{oid}) + if defined $values{oid} + && $values{oid} >= $first_mapped_oid + && $values{oid} <= $last_mapped_oid; + + $values{array_type_oid} = get_lower_oid($values{oid}) + if defined $values{array_type_oid} + && $values{array_type_oid} >= $first_mapped_oid + && $values{array_type_oid} <= $last_mapped_oid; + + print $dat Dumper(\%values); + print $dat ",\n"; + } + + # Preserve blank lines. + elsif ($data =~ /^\s*$/) + { + print $dat "\n"; + } + + # Preserve comments or brackets that are on their own line. + elsif ($data =~ /^\s*(\[|\]|#.*?)\s*$/) + { + print $dat "$1\n"; + } + } + close $dat; +} + +# Return the next available OID above $first_target_oid. +sub get_lower_oid +{ + my $old_oid = shift; + my $new_oid; + + for (;;) + { + if (scalar @oids == 0 || $next_oid < $oids[0]) + { + $new_oid = $next_oid; + warn sprintf "failed to map OID %d\n", $old_oid + if $new_oid >= $first_mapped_oid; + $next_oid++; + return $new_oid; + } + elsif ($next_oid > $oids[0]) + { + shift @oids; + } + elsif ($oids[0] == $next_oid) + { + shift @oids; + $next_oid++; + } + else + { + die "unreachable\n"; + } + } +} + +sub usage +{ + die <<EOM; +Usage: renumber_oids.pl [--output <path>] --first-mapped-oid X --last-mapped-oid Y --first-target-oid Z datafile... + +Options: + --output output directory (default '.') + --first-mapped-oid first OID to be mapped + --last-mapped-oid last OID to be mapped + --first-target-oid first OID to map to + +Expects a list of .dat files as arguments. + +EOM +} base-commit: 203749a8a66096171f808dd8e870d08d8ad57e5e -- 2.17.1