1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-24 00:23:06 +03:00

Get rid of the need for manual maintenance of the initial contents of

pg_attribute, by having genbki.pl derive the information from the various
catalog header files.  This greatly simplifies modification of the
"bootstrapped" catalogs.

This patch finally kills genbki.sh and Gen_fmgrtab.sh; we now rely entirely on
Perl scripts for those build steps.  To avoid creating a Perl build dependency
where there was not one before, the output files generated by these scripts
are now treated as distprep targets, ie, they will be built and shipped in
tarballs.  But you will need a reasonably modern Perl (probably at least
5.6) if you want to build from a CVS pull.

The changes to the MSVC build process are untested, and may well break ---
we'll soon find out from the buildfarm.

John Naylor, based on ideas from Robert Haas and others
This commit is contained in:
Tom Lane
2010-01-05 01:06:57 +00:00
parent fc09fb7bcf
commit 64737e9313
66 changed files with 931 additions and 1501 deletions

View File

@@ -0,0 +1,201 @@
#----------------------------------------------------------------------
#
# Catalog.pm
# Perl module that extracts info from catalog headers into Perl
# data structures
#
# Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
# $PostgreSQL: pgsql/src/backend/catalog/Catalog.pm,v 1.1 2010/01/05 01:06:56 tgl Exp $
#
#----------------------------------------------------------------------
package Catalog;
use strict;
use warnings;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = ();
our @EXPORT_OK = qw(Catalogs RenameTempFile);
# Call this function with an array of names of header files to parse.
# Returns a nested data structure describing the data in the headers.
sub Catalogs
{
my (%catalogs, $catname, $declaring_attributes, $most_recent);
$catalogs{names} = [];
# There are a few types which are given one name in the C source, but a
# different name at the SQL level. These are enumerated here.
my %RENAME_ATTTYPE = (
'Oid' => 'oid',
'NameData' => 'name',
'TransactionId' => 'xid'
);
foreach my $input_file (@_)
{
my %catalog;
$catalog{columns} = [];
$catalog{data} = [];
open(INPUT_FILE, '<', $input_file) || die "$input_file: $!";
# Scan the input file.
while (<INPUT_FILE>)
{
# Strip C-style comments.
s;/\*(.|\n)*\*/;;g;
if (m;/\*;)
{
# handle multi-line comments properly.
my $next_line = <INPUT_FILE>;
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;
# Push the data into the appropriate data structure.
if (/^DATA\(insert(\s+OID\s+=\s+(\d+))?\s+\(\s*(.*)\s*\)\s*\)$/)
{
push @{ $catalog{data} }, {oid => $2, bki_values => $3};
}
elsif (/^DESCR\(\"(.*)\"\)$/)
{
$most_recent = $catalog{data}->[-1];
# this tests if most recent line is not a DATA() statement
if (ref $most_recent ne 'HASH')
{
die "DESCR() does not apply to any catalog ($input_file)";
}
if (!defined $most_recent->{oid})
{
die "DESCR() does not apply to any oid ($input_file)";
}
elsif ($1 ne '')
{
$most_recent->{descr} = $1;
}
}
elsif (/^SHDESCR\(\"(.*)\"\)$/)
{
$most_recent = $catalog{data}->[-1];
# this tests if most recent line is not a DATA() statement
if (ref $most_recent ne 'HASH')
{
die "SHDESCR() does not apply to any catalog ($input_file)";
}
if (!defined $most_recent->{oid})
{
die "SHDESCR() does not apply to any oid ($input_file)";
}
elsif ($1 ne '')
{
$most_recent->{shdescr} = $1;
}
}
elsif (/^DECLARE_TOAST\(\s*(\w+),\s*(\d+),\s*(\d+)\)/)
{
$catname = 'toasting';
my ($toast_name, $toast_oid, $index_oid) = ($1, $2, $3);
push @{ $catalog{data} }, "declare toast $toast_oid $index_oid on $toast_name\n";
}
elsif (/^DECLARE_(UNIQUE_)?INDEX\(\s*(\w+),\s*(\d+),\s*(.+)\)/)
{
$catname = 'indexing';
my ($is_unique, $index_name, $index_oid, $using) = ($1, $2, $3, $4);
push @{ $catalog{data} },
sprintf(
"declare %sindex %s %s %s\n",
$is_unique ? 'unique ' : '',
$index_name, $index_oid, $using
);
}
elsif (/^BUILD_INDICES/)
{
push @{ $catalog{data} }, "build indices\n";
}
elsif (/^CATALOG\(([^,]*),(\d+)\)/)
{
$catname = $1;
$catalog{relation_oid} = $2;
# Store pg_* catalog names in the same order we receive them
push @{ $catalogs{names} }, $catname;
$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/ ? 'True' : '';
$declaring_attributes = 1;
}
elsif ($declaring_attributes)
{
next if (/^{|^$/);
if (/^}/)
{
undef $declaring_attributes;
}
else
{
my ($atttype, $attname) = split /\s+/, $_;
if (exists $RENAME_ATTTYPE{$atttype})
{
$atttype = $RENAME_ATTTYPE{$atttype};
}
if ($attname =~ /(.*)\[.*\]/) # array attribute
{
$attname = $1;
$atttype .= '[]'; # variable-length only
}
push @{ $catalog{columns} }, {$attname => $atttype};
}
}
}
$catalogs{$catname} = \%catalog;
close INPUT_FILE;
}
return \%catalogs;
}
# Rename temporary files to final names, if anything has changed.
# Call this function with the final file name --- we append .tmp automatically
sub RenameTempFile
{
my $final_name = shift;
my $temp_name = $final_name . '.tmp';
if (-e $final_name && -s $temp_name == -s $final_name)
{
open TN, '<', "$temp_name" || die "$temp_name: $!";
if (open FN, '<', $final_name)
{
local $/ = undef;
my $tn = <TN>;
my $fn = <FN>;
close FN;
if ($tn eq $fn)
{
print "$final_name unchanged, not replacing\n";
close TN;
unlink($temp_name) || die "unlink: $temp_name: $!";
return;
}
}
close TN;
}
print "Writing $final_name\n";
rename($temp_name, $final_name) || die "rename: $temp_name: $!";
}
1;