postgresql/src/backend/utils/Gen_fmgrtab.pl

241 lines
6.2 KiB
Perl
Raw Normal View History

#! /usr/bin/perl -w
#-------------------------------------------------------------------------
#
# Gen_fmgrtab.pl
# Perl script that generates fmgroids.h and fmgrtab.c from pg_proc.h
#
2017-01-03 19:48:53 +01:00
# Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
#
# IDENTIFICATION
2010-09-20 22:08:53 +02:00
# src/backend/utils/Gen_fmgrtab.pl
#
#-------------------------------------------------------------------------
use Catalog;
use strict;
use warnings;
# Collect arguments
my $infile; # pg_proc.h
my $output_path = '';
while (@ARGV)
{
my $arg = shift @ARGV;
if ($arg !~ /^-/)
{
$infile = $arg;
}
elsif ($arg =~ /^-o/)
{
$output_path = length($arg) > 2 ? substr($arg, 2) : shift @ARGV;
}
else
{
usage();
}
}
# Make sure output_path ends in a slash.
if ($output_path ne '' && substr($output_path, -1) ne '/')
{
$output_path .= '/';
}
# Read all the data from the include/catalog files.
my $catalogs = Catalog::Catalogs($infile);
# Collect the raw data from pg_proc.h.
my @fmgr = ();
my @attnames;
foreach my $column (@{ $catalogs->{pg_proc}->{columns} })
{
push @attnames, $column->{name};
}
my $data = $catalogs->{pg_proc}->{data};
foreach my $row (@$data)
{
2017-05-18 01:01:23 +02:00
Move bootstrap-time lookup of regproc OIDs into genbki.pl. Formerly, the bootstrap backend looked up the OIDs corresponding to names in regproc catalog entries using brute-force searches of pg_proc. It was somewhat remarkable that that worked at all, since it was used while populating other pretty-fundamental catalogs like pg_operator. And it was also quite slow, and getting slower as pg_proc gets bigger. This patch moves the lookup work into genbki.pl, so that the values in postgres.bki for regproc columns are always numeric OIDs, an option that regprocin() already supported. Perl isn't the world's speediest language, so this about doubles the time needed to run genbki.pl (from 0.3 to 0.6 sec on my machine). But we only do that at most once per build. The time needed to run initdb drops significantly --- on my machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is a small net win even for just one initdb per build, and it becomes quite a nice win for test sequences requiring many initdb runs. Strip out the now-dead code for brute-force catalog searching in regprocin. We'd also cargo-culted similar logic into regoperin and some (not all) of the other reg*in functions. That is all dead code too since we currently have no need to load such values during bootstrap. I removed it all, reasoning that if we ever need such functionality it'd be much better to do it in a similar way to this patch. There might be some simplifications possible in the backend now that regprocin doesn't require doing catalog reads so early in bootstrap. I've not looked into that, though. Andreas Karlsson, with some small adjustments by me Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
# Split line into tokens without interpreting their meaning.
my %bki_values;
@bki_values{@attnames} = Catalog::SplitDataLine($row->{bki_values});
# Select out just the rows for internal-language procedures.
# Note assumption here that INTERNALlanguageId is 12.
Move bootstrap-time lookup of regproc OIDs into genbki.pl. Formerly, the bootstrap backend looked up the OIDs corresponding to names in regproc catalog entries using brute-force searches of pg_proc. It was somewhat remarkable that that worked at all, since it was used while populating other pretty-fundamental catalogs like pg_operator. And it was also quite slow, and getting slower as pg_proc gets bigger. This patch moves the lookup work into genbki.pl, so that the values in postgres.bki for regproc columns are always numeric OIDs, an option that regprocin() already supported. Perl isn't the world's speediest language, so this about doubles the time needed to run genbki.pl (from 0.3 to 0.6 sec on my machine). But we only do that at most once per build. The time needed to run initdb drops significantly --- on my machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is a small net win even for just one initdb per build, and it becomes quite a nice win for test sequences requiring many initdb runs. Strip out the now-dead code for brute-force catalog searching in regprocin. We'd also cargo-culted similar logic into regoperin and some (not all) of the other reg*in functions. That is all dead code too since we currently have no need to load such values during bootstrap. I removed it all, reasoning that if we ever need such functionality it'd be much better to do it in a similar way to this patch. There might be some simplifications possible in the backend now that regprocin doesn't require doing catalog reads so early in bootstrap. I've not looked into that, though. Andreas Karlsson, with some small adjustments by me Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
next if $bki_values{prolang} ne '12';
push @fmgr,
{ oid => $row->{oid},
Move bootstrap-time lookup of regproc OIDs into genbki.pl. Formerly, the bootstrap backend looked up the OIDs corresponding to names in regproc catalog entries using brute-force searches of pg_proc. It was somewhat remarkable that that worked at all, since it was used while populating other pretty-fundamental catalogs like pg_operator. And it was also quite slow, and getting slower as pg_proc gets bigger. This patch moves the lookup work into genbki.pl, so that the values in postgres.bki for regproc columns are always numeric OIDs, an option that regprocin() already supported. Perl isn't the world's speediest language, so this about doubles the time needed to run genbki.pl (from 0.3 to 0.6 sec on my machine). But we only do that at most once per build. The time needed to run initdb drops significantly --- on my machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is a small net win even for just one initdb per build, and it becomes quite a nice win for test sequences requiring many initdb runs. Strip out the now-dead code for brute-force catalog searching in regprocin. We'd also cargo-culted similar logic into regoperin and some (not all) of the other reg*in functions. That is all dead code too since we currently have no need to load such values during bootstrap. I removed it all, reasoning that if we ever need such functionality it'd be much better to do it in a similar way to this patch. There might be some simplifications possible in the backend now that regprocin doesn't require doing catalog reads so early in bootstrap. I've not looked into that, though. Andreas Karlsson, with some small adjustments by me Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
strict => $bki_values{proisstrict},
retset => $bki_values{proretset},
nargs => $bki_values{pronargs},
prosrc => $bki_values{prosrc}, };
}
# Emit headers for both files
2017-05-18 01:01:23 +02:00
my $tmpext = ".tmp$$";
my $oidsfile = $output_path . 'fmgroids.h';
my $protosfile = $output_path . 'fmgrprotos.h';
2017-05-18 01:01:23 +02:00
my $tabfile = $output_path . 'fmgrtab.c';
2017-05-18 01:01:23 +02:00
open my $ofh, '>', $oidsfile . $tmpext
or die "Could not open $oidsfile$tmpext: $!";
open my $pfh, '>', $protosfile . $tmpext
or die "Could not open $protosfile$tmpext: $!";
open my $tfh, '>', $tabfile . $tmpext
or die "Could not open $tabfile$tmpext: $!";
print $ofh
qq|/*-------------------------------------------------------------------------
*
* fmgroids.h
* Macros that define the OIDs of built-in functions.
*
* These macros can be used to avoid a catalog lookup when a specific
* fmgr-callable function needs to be referenced.
*
2017-01-03 19:48:53 +01:00
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* NOTES
* ******************************
* *** DO NOT EDIT THIS FILE! ***
* ******************************
*
* It has been GENERATED by $0
* from $infile
*
*-------------------------------------------------------------------------
*/
#ifndef FMGROIDS_H
#define FMGROIDS_H
/*
* Constant macros for the OIDs of entries in pg_proc.
*
* NOTE: macros are named after the prosrc value, ie the actual C name
* of the implementing function, not the proname which may be overloaded.
* For example, we want to be able to assign different macro names to both
* char_text() and name_text() even though these both appear with proname
* 'text'. If the same C function appears in more than one pg_proc entry,
* its equivalent macro will be defined with the lowest OID among those
* entries.
*/
|;
print $pfh
qq|/*-------------------------------------------------------------------------
*
* fmgrprotos.h
* Prototypes for built-in functions.
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* NOTES
* ******************************
* *** DO NOT EDIT THIS FILE! ***
* ******************************
*
* It has been GENERATED by $0
* from $infile
*
*-------------------------------------------------------------------------
*/
#ifndef FMGRPROTOS_H
#define FMGRPROTOS_H
#include "fmgr.h"
|;
print $tfh
qq|/*-------------------------------------------------------------------------
*
* fmgrtab.c
* The function manager's table of internal functions.
*
2017-01-03 19:48:53 +01:00
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* NOTES
*
* ******************************
* *** DO NOT EDIT THIS FILE! ***
* ******************************
*
* It has been GENERATED by $0
* from $infile
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "utils/fmgrtab.h"
#include "utils/fmgrprotos.h"
|;
# Emit #define's and extern's -- only one per prosrc value
my %seenit;
foreach my $s (sort { $a->{oid} <=> $b->{oid} } @fmgr)
{
next if $seenit{ $s->{prosrc} };
$seenit{ $s->{prosrc} } = 1;
print $ofh "#define F_" . uc $s->{prosrc} . " $s->{oid}\n";
print $pfh "extern Datum $s->{prosrc}(PG_FUNCTION_ARGS);\n";
}
# Create the fmgr_builtins table
print $tfh "\nconst FmgrBuiltin fmgr_builtins[] = {\n";
my %bmap;
$bmap{'t'} = 'true';
$bmap{'f'} = 'false';
foreach my $s (sort { $a->{oid} <=> $b->{oid} } @fmgr)
{
print $tfh
" { $s->{oid}, \"$s->{prosrc}\", $s->{nargs}, $bmap{$s->{strict}}, $bmap{$s->{retset}}, $s->{prosrc} },\n";
}
# And add the file footers.
print $ofh "\n#endif /* FMGROIDS_H */\n";
print $pfh "\n#endif /* FMGRPROTOS_H */\n";
print $tfh
qq| /* dummy entry is easier than getting rid of comma after last real one */
/* (not that there has ever been anything wrong with *having* a
comma after the last field in an array initializer) */
{ 0, NULL, 0, false, false, NULL }
};
/* Note fmgr_nbuiltins excludes the dummy entry */
const int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin)) - 1;
|;
close($ofh);
close($pfh);
close($tfh);
# Finally, rename the completed files into place.
2017-05-18 01:01:23 +02:00
Catalog::RenameTempFile($oidsfile, $tmpext);
Catalog::RenameTempFile($protosfile, $tmpext);
2017-05-18 01:01:23 +02:00
Catalog::RenameTempFile($tabfile, $tmpext);
sub usage
{
die <<EOM;
Usage: perl -I [directory of Catalog.pm] Gen_fmgrtab.pl [path to pg_proc.h]
Gen_fmgrtab.pl generates fmgroids.h and fmgrtab.c from pg_proc.h
Report bugs to <pgsql-bugs\@postgresql.org>.
EOM
}
exit 0;