mirror of https://github.com/postgres/postgres
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 othersREL9_0_ALPHA4_BRANCH
parent
fc09fb7bcf
commit
64737e9313
@ -0,0 +1,4 @@ |
||||
postgres.bki |
||||
postgres.description |
||||
postgres.shdescription |
||||
schemapg.h |
@ -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; |
@ -0,0 +1,432 @@ |
||||
#!/usr/bin/perl -w |
||||
#---------------------------------------------------------------------- |
||||
# |
||||
# genbki.pl |
||||
# Perl script that generates postgres.bki, postgres.description, |
||||
# postgres.shdescription, and schemapg.h from specially formatted |
||||
# header files. The .bki files are used to initialize the postgres |
||||
# template database. |
||||
# |
||||
# Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group |
||||
# Portions Copyright (c) 1994, Regents of the University of California |
||||
# |
||||
# $PostgreSQL: pgsql/src/backend/catalog/genbki.pl,v 1.1 2010/01/05 01:06:56 tgl Exp $ |
||||
# |
||||
#---------------------------------------------------------------------- |
||||
|
||||
use Catalog; |
||||
|
||||
use strict; |
||||
use warnings; |
||||
|
||||
my @input_files; |
||||
our @include_path; |
||||
my $output_path = ''; |
||||
my $major_version; |
||||
|
||||
# Process command line switches. |
||||
while (@ARGV) |
||||
{ |
||||
my $arg = shift @ARGV; |
||||
if ($arg !~ /^-/) |
||||
{ |
||||
push @input_files, $arg; |
||||
} |
||||
elsif ($arg =~ /^-o/) |
||||
{ |
||||
$output_path = length($arg) > 2 ? substr($arg, 2) : shift @ARGV; |
||||
} |
||||
elsif ($arg =~ /^-I/) |
||||
{ |
||||
push @include_path, length($arg) > 2 ? substr($arg, 2) : shift @ARGV; |
||||
} |
||||
elsif ($arg =~ /^--set-version=(\d+\.\d+).*$/) |
||||
{ |
||||
$major_version = $1; |
||||
} |
||||
else |
||||
{ |
||||
usage(); |
||||
} |
||||
} |
||||
|
||||
# Sanity check arguments. |
||||
die "No input files.\n" if !@input_files; |
||||
die "No include path; you must specify -I at least once.\n" if !@include_path; |
||||
die "Version not specified or wrong format.\n" if !defined $major_version; |
||||
|
||||
# Make sure output_path ends in a slash. |
||||
if ($output_path ne '' && substr($output_path, -1) ne '/') |
||||
{ |
||||
$output_path .= '/'; |
||||
} |
||||
|
||||
# Open temp files |
||||
open BKI, '>', $output_path . 'postgres.bki.tmp' |
||||
|| die "can't open postgres.bki.tmp: $!"; |
||||
open SCHEMAPG, '>', $output_path . 'schemapg.h.tmp' |
||||
|| die "can't open 'schemapg.h.tmp: $!"; |
||||
open DESCR, '>', $output_path . 'postgres.description.tmp' |
||||
|| die "can't open postgres.description.tmp: $!"; |
||||
open SHDESCR, '>', $output_path . 'postgres.shdescription.tmp' |
||||
|| die "can't open postgres.shdescription.tmp: $!"; |
||||
|
||||
# Fetch some special data that we will substitute into the output file. |
||||
# CAUTION: be wary about what symbols you substitute into the .bki file here! |
||||
# It's okay to substitute things that are expected to be really constant |
||||
# within a given Postgres release, such as fixed OIDs. Do not substitute |
||||
# anything that could depend on platform or configuration. (The right place |
||||
# to handle those sorts of things is in initdb.c's bootstrap_template1().) |
||||
# NB: make sure that the files used here are known to be part of the .bki |
||||
# file's dependencies by src/backend/catalog/Makefile. |
||||
my $BOOTSTRAP_SUPERUSERID = find_defined_symbol('pg_authid.h', 'BOOTSTRAP_SUPERUSERID'); |
||||
my $PG_CATALOG_NAMESPACE = find_defined_symbol('pg_namespace.h', 'PG_CATALOG_NAMESPACE'); |
||||
|
||||
# Read all the input header files into internal data structures |
||||
my $catalogs = Catalog::Catalogs(@input_files); |
||||
|
||||
# Generate postgres.bki, postgres.description, and postgres.shdescription |
||||
|
||||
# version marker for .bki file |
||||
print BKI "# PostgreSQL $major_version\n"; |
||||
|
||||
# vars to hold data needed for schemapg.h |
||||
my %schemapg_entries; |
||||
my @tables_needing_macros; |
||||
our @types; |
||||
|
||||
# produce output, one catalog at a time |
||||
foreach my $catname ( @{ $catalogs->{names} } ) |
||||
{ |
||||
# .bki CREATE command for this catalog |
||||
my $catalog = $catalogs->{$catname}; |
||||
print BKI "create $catname $catalog->{relation_oid}" |
||||
. $catalog->{shared_relation} |
||||
. $catalog->{bootstrap} |
||||
. $catalog->{without_oids} |
||||
. $catalog->{rowtype_oid}. "\n"; |
||||
|
||||
my %bki_attr; |
||||
my @attnames; |
||||
foreach my $column ( @{ $catalog->{columns} } ) |
||||
{ |
||||
my ($attname, $atttype) = %$column; |
||||
$bki_attr{$attname} = $atttype; |
||||
push @attnames, $attname; |
||||
} |
||||
print BKI " (\n"; |
||||
print BKI join " ,\n", map(" $_ = $bki_attr{$_}", @attnames); |
||||
print BKI "\n )\n"; |
||||
|
||||
# open it, unless bootstrap case (create bootstrap does this automatically) |
||||
if ($catalog->{bootstrap} eq '') |
||||
{ |
||||
print BKI "open $catname\n"; |
||||
} |
||||
|
||||
if (defined $catalog->{data}) |
||||
{ |
||||
# Ordinary catalog with DATA line(s) |
||||
foreach my $row ( @{ $catalog->{data} } ) |
||||
{ |
||||
# substitute constant values we acquired above |
||||
$row->{bki_values} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g; |
||||
$row->{bki_values} =~ s/\bPGNSP\b/$PG_CATALOG_NAMESPACE/g; |
||||
|
||||
# Save pg_type info for pg_attribute processing below |
||||
if ($catname eq 'pg_type') |
||||
{ |
||||
my %type; |
||||
$type{oid} = $row->{oid}; |
||||
@type{@attnames} = split /\s+/, $row->{bki_values}; |
||||
push @types, \%type; |
||||
} |
||||
|
||||
# Write to postgres.bki |
||||
my $oid = $row->{oid} ? "OID = $row->{oid} " : ''; |
||||
printf BKI "insert %s( %s)\n", $oid, $row->{bki_values}; |
||||
|
||||
# Write values to postgres.description and postgres.shdescription |
||||
if (defined $row->{descr}) |
||||
{ |
||||
printf DESCR "%s\t%s\t0\t%s\n", $row->{oid}, $catname, $row->{descr}; |
||||
} |
||||
if (defined $row->{shdescr}) |
||||
{ |
||||
printf SHDESCR "%s\t%s\t%s\n", $row->{oid}, $catname, $row->{shdescr}; |
||||
} |
||||
} |
||||
} |
||||
if ($catname eq 'pg_attribute') |
||||
{ |
||||
# For pg_attribute.h, we generate DATA entries ourselves. |
||||
# NB: pg_type.h must come before pg_attribute.h in the input list |
||||
# of catalog names, since we use info from pg_type.h here. |
||||
foreach my $table_name ( @{ $catalogs->{names} } ) |
||||
{ |
||||
my $table = $catalogs->{$table_name}; |
||||
|
||||
# Build Schema_pg_xxx macros needed by relcache.c. |
||||
next if $table->{schema_macro} ne 'True'; |
||||
|
||||
$schemapg_entries{$table_name} = []; |
||||
push @tables_needing_macros, $table_name; |
||||
my $is_bootstrap = $table->{bootstrap}; |
||||
|
||||
# Both postgres.bki and schemapg.h have entries corresponding |
||||
# to user attributes |
||||
my $attnum = 0; |
||||
my @user_attrs = @{ $table->{columns} }; |
||||
foreach my $attr (@user_attrs) |
||||
{ |
||||
$attnum++; |
||||
my $row = emit_pgattr_row($table_name, $attr); |
||||
$row->{attnum} = $attnum; |
||||
$row->{attstattarget} = '-1'; |
||||
|
||||
# Of these tables, only bootstrapped ones |
||||
# have data declarations in postgres.bki |
||||
if ($is_bootstrap eq ' bootstrap') |
||||
{ |
||||
bki_insert($row, @attnames); |
||||
} |
||||
|
||||
# Store schemapg entries for later |
||||
$row = emit_schemapg_row($row, grep { $bki_attr{$_} eq 'bool' } @attnames); |
||||
push @{ $schemapg_entries{$table_name} }, |
||||
'{ ' . join(', ', map $row->{$_}, @attnames) . ' }'; |
||||
} |
||||
|
||||
# Only postgres.bki has entries corresponding to system |
||||
# attributes, so only bootstrapped relations here |
||||
if ($is_bootstrap eq ' bootstrap') |
||||
{ |
||||
$attnum = 0; |
||||
my @SYS_ATTRS = ( |
||||
{ctid => 'tid'}, |
||||
{oid => 'oid'}, |
||||
{xmin => 'xid'}, |
||||
{cmin => 'cid'}, |
||||
{xmax => 'xid'}, |
||||
{cmax => 'cid'}, |
||||
{tableoid => 'oid'} |
||||
); |
||||
foreach my $attr (@SYS_ATTRS) |
||||
{ |
||||
$attnum--; |
||||
my $row = emit_pgattr_row($table_name, $attr); |
||||
|
||||
# pg_attribute has no oids -- skip |
||||
next if $table_name eq 'pg_attribute' && $row->{attname} eq 'oid'; |
||||
|
||||
$row->{attnum} = $attnum; |
||||
$row->{attstattarget} = '0'; |
||||
bki_insert($row, @attnames); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
print BKI "close $catname\n"; |
||||
} |
||||
|
||||
# Any information needed for the BKI that is not contained in a pg_*.h header |
||||
# (i.e., not contained in a header with a CATALOG() statement) comes here |
||||
|
||||
# Write out declare toast/index statements |
||||
foreach my $declaration ( @{ $catalogs->{toasting}->{data} } ) |
||||
{ |
||||
print BKI $declaration; |
||||
} |
||||
|
||||
foreach my $declaration ( @{ $catalogs->{indexing}->{data} } ) |
||||
{ |
||||
print BKI $declaration; |
||||
} |
||||
|
||||
|
||||
# Now generate schemapg.h |
||||
|
||||
# Opening boilerplate for schemapg.h |
||||
print SCHEMAPG <<EOM; |
||||
/*------------------------------------------------------------------------- |
||||
* |
||||
* schemapg.h |
||||
* Schema_pg_xxx macros for use by relcache.c |
||||
* |
||||
* Portions Copyright (c) 1996-2010, 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 |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef SCHEMAPG_H |
||||
#define SCHEMAPG_H |
||||
EOM |
||||
|
||||
# Emit schemapg declarations |
||||
foreach my $table_name (@tables_needing_macros) |
||||
{ |
||||
print SCHEMAPG "\n#define Schema_$table_name \\\n"; |
||||
print SCHEMAPG join ", \\\n", @{ $schemapg_entries{$table_name} }; |
||||
print SCHEMAPG "\n"; |
||||
} |
||||
|
||||
# Closing boilerplate for schemapg.h |
||||
print SCHEMAPG "\n#endif /* SCHEMAPG_H */\n"; |
||||
|
||||
# We're done emitting data |
||||
close BKI; |
||||
close DESCR; |
||||
close SHDESCR; |
||||
close SCHEMAPG; |
||||
|
||||
# Rename temp files on top of final files, if they have changed |
||||
Catalog::RenameTempFile($output_path . 'postgres.bki'); |
||||
Catalog::RenameTempFile($output_path . 'postgres.description'); |
||||
Catalog::RenameTempFile($output_path . 'postgres.shdescription'); |
||||
Catalog::RenameTempFile($output_path . 'schemapg.h'); |
||||
|
||||
exit 0; |
||||
|
||||
#################### Subroutines ######################## |
||||
|
||||
|
||||
# Given a system catalog name and a reference to a key-value pair corresponding |
||||
# to the name and type of a column, generate a reference to a pg_attribute |
||||
# entry |
||||
sub emit_pgattr_row |
||||
{ |
||||
my ($table_name, $attr) = @_; |
||||
my ($attname, $atttype) = %$attr; |
||||
my %row; |
||||
|
||||
$row{attrelid} = $catalogs->{$table_name}->{relation_oid}; |
||||
$row{attname} = $attname; |
||||
|
||||
# Adjust type name for arrays: foo[] becomes _foo |
||||
# so we can look it up in pg_type |
||||
if ($atttype =~ /(.+)\[\]$/) |
||||
{ |
||||
$atttype = '_' . $1; |
||||
} |
||||
|
||||
# Copy the type data from pg_type, with minor modifications: |
||||
foreach my $type (@types) |
||||
{ |
||||
if ( defined $type->{typname} && $type->{typname} eq $atttype ) |
||||
{ |
||||
$row{atttypid} = $type->{oid}; |
||||
$row{attlen} = $type->{typlen}; |
||||
$row{attbyval} = $type->{typbyval}; |
||||
$row{attstorage} = $type->{typstorage}; |
||||
$row{attalign} = $type->{typalign}; |
||||
$row{attndims} = $type->{typcategory} eq 'A' ? '1' : '0'; |
||||
$row{attnotnull} = $type->{typstorage} eq 'x' ? 'f' : 't'; |
||||
last; |
||||
} |
||||
} |
||||
|
||||
# Add in default values for pg_attribute |
||||
my %PGATTR_DEFAULTS = ( |
||||
attdistinct => '0', |
||||
attcacheoff => '-1', |
||||
atttypmod => '-1', |
||||
atthasdef => 'f', |
||||
attisdropped => 'f', |
||||
attislocal => 't', |
||||
attinhcount => '0', |
||||
attacl => '_null_' |
||||
); |
||||
return {%PGATTR_DEFAULTS, %row}; |
||||
} |
||||
|
||||
# Write a pg_attribute entry to postgres.bki |
||||
sub bki_insert |
||||
{ |
||||
my $row = shift; |
||||
my @attnames = @_; |
||||
my $oid = $row->{oid} ? "OID = $row->{oid} " : ''; |
||||
my $bki_values = join ' ', map $row->{$_}, @attnames; |
||||
printf BKI "insert %s( %s)\n", $oid, $bki_values; |
||||
} |
||||
|
||||
# The values of a Schema_pg_xxx declaration are similar, but not |
||||
# quite identical, to the corresponding values in pg_attribute. |
||||
sub emit_schemapg_row |
||||
{ |
||||
my $row = shift; |
||||
my @bool_attrs = @_; |
||||
|
||||
# pg_index has attrelid = 0 in schemapg.h |
||||
if ($row->{attrelid} eq '2610') |
||||
{ |
||||
$row->{attrelid} = '0'; |
||||
} |
||||
|
||||
$row->{attname} = q|{"| . $row->{attname} . q|"}|; |
||||
$row->{attstorage} = q|'| . $row->{attstorage} . q|'|; |
||||
$row->{attalign} = q|'| . $row->{attalign} . q|'|; |
||||
$row->{attacl} = q|{ 0 }|; |
||||
|
||||
# Expand booleans, accounting for FLOAT4PASSBYVAL etc. |
||||
foreach my $attr (@bool_attrs) |
||||
{ |
||||
$row->{$attr} = |
||||
$row->{$attr} eq 't' ? 'true' |
||||
: $row->{$attr} eq 'f' ? 'false' |
||||
: $row->{$attr}; |
||||
} |
||||
return $row; |
||||
} |
||||
|
||||
# Find a symbol defined in a particular header file and extract the value. |
||||
sub find_defined_symbol |
||||
{ |
||||
my ($catalog_header, $symbol) = @_; |
||||
for my $path (@include_path) |
||||
{ |
||||
# Make sure include path ends in a slash. |
||||
if (substr($path, -1) ne '/') |
||||
{ |
||||
$path .= '/'; |
||||
} |
||||
my $file = $path . $catalog_header; |
||||
next if !-f $file; |
||||
open(FIND_DEFINED_SYMBOL, '<', $file) || die "$file: $!"; |
||||
while (<FIND_DEFINED_SYMBOL>) |
||||
{ |
||||
if (/^#define\s+\Q$symbol\E\s+(\S+)/) |
||||
{ |
||||
return $1; |
||||
} |
||||
} |
||||
close FIND_DEFINED_SYMBOL; |
||||
die "$file: no definition found for $symbol\n"; |
||||
} |
||||
die "$catalog_header: not found in any include directory\n"; |
||||
} |
||||
|
||||
sub usage |
||||
{ |
||||
die <<EOM; |
||||
Usage: genbki.pl [options] header... |
||||
|
||||
Options: |
||||
-I path to include files |
||||
-o output path |
||||
--set-version PostgreSQL version number for initdb cross-check |
||||
|
||||
genbki.pl generates BKI files from specially formatted |
||||
header files. These BKI files are used to initialize the |
||||
postgres template database. |
||||
|
||||
Report bugs to <pgsql-bugs\@postgresql.org>. |
||||
EOM |
||||
} |
@ -1,438 +0,0 @@ |
||||
#! /bin/sh |
||||
#------------------------------------------------------------------------- |
||||
# |
||||
# genbki.sh-- |
||||
# shell script which generates .bki files from specially formatted .h |
||||
# files. These .bki files are used to initialize the postgres template |
||||
# database. |
||||
# |
||||
# Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group |
||||
# Portions Copyright (c) 1994, Regents of the University of California |
||||
# |
||||
# |
||||
# IDENTIFICATION |
||||
# $PostgreSQL: pgsql/src/backend/catalog/genbki.sh,v 1.49 2010/01/02 16:57:36 momjian Exp $ |
||||
# |
||||
# NOTES |
||||
# non-essential whitespace is removed from the generated file. |
||||
# if this is ever a problem, then the sed script at the very |
||||
# end can be changed into another awk script or something smarter. |
||||
# |
||||
#------------------------------------------------------------------------- |
||||
|
||||
: ${AWK='awk'} |
||||
|
||||
CMDNAME=`basename $0` |
||||
|
||||
INCLUDE_DIRS= |
||||
OUTPUT_PREFIX= |
||||
INFILES= |
||||
major_version= |
||||
|
||||
# |
||||
# Process command line switches. |
||||
# |
||||
while [ $# -gt 0 ] |
||||
do |
||||
case $1 in |
||||
-I) |
||||
INCLUDE_DIRS="$INCLUDE_DIRS $2" |
||||
shift;; |
||||
-I*) |
||||
arg=`echo $1 | sed -e 's/^-I//'` |
||||
INCLUDE_DIRS="$INCLUDE_DIRS $arg" |
||||
;; |
||||
-o) |
||||
OUTPUT_PREFIX="$2" |
||||
shift;; |
||||
-o*) |
||||
OUTPUT_PREFIX=`echo $1 | sed -e 's/^-o//'` |
||||
;; |
||||
--set-version=*) |
||||
arg=`expr x"$1" : x"--set-version=\(.*\)"` |
||||
major_version=`expr x"$arg" : x'\([0-9][0-9]*\.[0-9][0-9]*\)'` |
||||
;; |
||||
--help) |
||||
echo "$CMDNAME generates system catalog bootstrapping files." |
||||
echo |
||||
echo "Usage:" |
||||
echo " $CMDNAME [ -I dir ] --set-version=VERSION -o prefix files..." |
||||
echo |
||||
echo "Options:" |
||||
echo " -I path to include files" |
||||
echo " -o prefix of output files" |
||||
echo " --set-version PostgreSQL version number for initdb cross-check" |
||||
echo |
||||
echo "The environment variable AWK determines which Awk program" |
||||
echo "to use. The default is \`awk'." |
||||
echo |
||||
echo "Report bugs to <pgsql-bugs@postgresql.org>." |
||||
exit 0 |
||||
;; |
||||
-*) |
||||
echo "$CMDNAME: invalid option: $1" |
||||
exit 1 |
||||
;; |
||||
*) |
||||
INFILES="$INFILES $1" |
||||
;; |
||||
esac |
||||
shift |
||||
done |
||||
|
||||
if [ x"$INFILES" = x"" ] ; then |
||||
echo "$CMDNAME: no input files" 1>&2 |
||||
exit 1 |
||||
fi |
||||
|
||||
if [ x"$OUTPUT_PREFIX" = x"" ] ; then |
||||
echo "$CMDNAME: no output prefix specified" 1>&2 |
||||
exit 1 |
||||
fi |
||||
|
||||
if [ x"$INCLUDE_DIRS" = x"" ] ; then |
||||
echo "$CMDNAME: path to include directory unknown" 1>&2 |
||||
exit 1 |
||||
fi |
||||
|
||||
if [ x"$major_version" = x"" ] ; then |
||||
echo "$CMDNAME: invalid or no version number specified" 1>&2 |
||||
exit 1 |
||||
fi |
||||
|
||||
|
||||
TMPFILE="genbkitmp$$.c" |
||||
|
||||
trap "rm -f $TMPFILE ${OUTPUT_PREFIX}.bki.$$ ${OUTPUT_PREFIX}.description.$$ ${OUTPUT_PREFIX}.shdescription.$$" 0 1 2 3 15 |
||||
|
||||
|
||||
# CAUTION: be wary about what symbols you substitute into the .bki file here! |
||||
# It's okay to substitute things that are expected to be really constant |
||||
# within a given Postgres release, such as fixed OIDs. Do not substitute |
||||
# anything that could depend on platform or configuration. (The right place |
||||
# to handle those sorts of things is in initdb.c's bootstrap_template1().) |
||||
|
||||
# Get BOOTSTRAP_SUPERUSERID from catalog/pg_authid.h |
||||
for dir in $INCLUDE_DIRS; do |
||||
if [ -f "$dir/catalog/pg_authid.h" ]; then |
||||
BOOTSTRAP_SUPERUSERID=`grep '^#define[ ]*BOOTSTRAP_SUPERUSERID' $dir/catalog/pg_authid.h | $AWK '{ print $3 }'` |
||||
break |
||||
fi |
||||
done |
||||
|
||||
# Get PG_CATALOG_NAMESPACE from catalog/pg_namespace.h |
||||
for dir in $INCLUDE_DIRS; do |
||||
if [ -f "$dir/catalog/pg_namespace.h" ]; then |
||||
PG_CATALOG_NAMESPACE=`grep '^#define[ ]*PG_CATALOG_NAMESPACE' $dir/catalog/pg_namespace.h | $AWK '{ print $3 }'` |
||||
break |
||||
fi |
||||
done |
||||
|
||||
touch ${OUTPUT_PREFIX}.description.$$ |
||||
touch ${OUTPUT_PREFIX}.shdescription.$$ |
||||
|
||||
# ---------------- |
||||
# Strip comments and other trash from .h |
||||
# |
||||
# Put multi-line start/end comments on a separate line |
||||
# |
||||
# Rename datatypes that have different names in .h files than in SQL |
||||
# |
||||
# Substitute values of configuration constants |
||||
# ---------------- |
||||
# |
||||
cat $INFILES | \ |
||||
sed -e 's;/\*.*\*/;;g' \ |
||||
-e 's;/\*;\ |
||||
/*\ |
||||
;g' \ |
||||
-e 's;\*/;\ |
||||
*/\ |
||||
;g' | # we must run a new sed here to see the newlines we added |
||||
sed -e "s/;[ ]*$//g" \ |
||||
-e "s/^[ ]*//" \ |
||||
-e "s/[ ]Oid/ oid/g" \ |
||||
-e "s/^Oid/oid/g" \ |
||||
-e "s/(Oid/(oid/g" \ |
||||
-e "s/[ ]NameData/ name/g" \ |
||||
-e "s/^NameData/name/g" \ |
||||
-e "s/(NameData/(name/g" \ |
||||
-e "s/[ ]TransactionId/ xid/g" \ |
||||
-e "s/^TransactionId/xid/g" \ |
||||
-e "s/(TransactionId/(xid/g" \ |
||||
-e "s/PGUID/$BOOTSTRAP_SUPERUSERID/g" \ |
||||
-e "s/PGNSP/$PG_CATALOG_NAMESPACE/g" \ |
||||
| $AWK ' |
||||
# ---------------- |
||||
# now use awk to process remaining .h file.. |
||||
# |
||||
# nc is the number of catalogs |
||||
# inside is a variable set to 1 when we are scanning the |
||||
# contents of a catalog definition. |
||||
# reln_open is a flag indicating when we are processing DATA lines. |
||||
# (i.e. have a relation open and need to close it) |
||||
# oid is the most recently seen oid, or 0 if none in the last DATA line. |
||||
# ---------------- |
||||
BEGIN { |
||||
inside = 0; |
||||
bootstrap = ""; |
||||
shared_relation = ""; |
||||
without_oids = ""; |
||||
rowtype_oid = ""; |
||||
nc = 0; |
||||
reln_open = 0; |
||||
comment_level = 0; |
||||
oid = 0; |
||||
} |
||||
|
||||
# ---------------- |
||||
# Anything in a /* .. */ block should be ignored. |
||||
# Blank lines also go. |
||||
# Note that any /* */ comment on a line by itself was removed from the line |
||||
# by the sed above. |
||||
# ---------------- |
||||
/^\/\*/ { comment_level += 1; next; } |
||||
/^\*\// { comment_level -= 1; next; } |
||||
comment_level > 0 { next; } |
||||
|
||||
/^[ ]*$/ { next; } |
||||
|
||||
# ---------------- |
||||
# DATA() statements are basically passed right through after |
||||
# stripping off the DATA( and the ) on the end. |
||||
# Remember the OID for use by DESCR() and SHDESCR(). |
||||
# ---------------- |
||||
/^DATA\(/ { |
||||
data = substr($0, 6, length($0) - 6); |
||||
oid = 0; |
||||
nf = split(data, datafields); |
||||
if (nf >= 4 && datafields[1] == "insert" && datafields[2] == "OID" && datafields[3] == "=") |
||||
{ |
||||
oid = datafields[4]; |
||||
} |
||||
print data; |
||||
next; |
||||
} |
||||
|
||||
/^DESCR\(/ { |
||||
if (oid != 0) |
||||
{ |
||||
data = substr($0, 8, length($0) - 9); |
||||
if (data != "") |
||||
printf "%d\t%s\t0\t%s\n", oid, catalog, data >>descriptionfile; |
||||
} |
||||
next; |
||||
} |
||||
|
||||
/^SHDESCR\(/ { |
||||
if (oid != 0) |
||||
{ |
||||
data = substr($0, 10, length($0) - 11); |
||||
if (data != "") |
||||
printf "%d\t%s\t%s\n", oid, catalog, data >>shdescriptionfile; |
||||
} |
||||
next; |
||||
} |
||||
|
||||
/^DECLARE_INDEX\(/ { |
||||
# ---- |
||||
# end any prior catalog data insertions before starting a define index |
||||
# ---- |
||||
if (reln_open == 1) { |
||||
print "close " catalog; |
||||
reln_open = 0; |
||||
} |
||||
|
||||
data = substr($0, 15, length($0) - 15); |
||||
pos = index(data, ","); |
||||
iname = substr(data, 1, pos-1); |
||||
data = substr(data, pos+1, length(data)-pos); |
||||
pos = index(data, ","); |
||||
oid = substr(data, 1, pos-1); |
||||
data = substr(data, pos+1, length(data)-pos); |
||||
|
||||
print "declare index " iname " " oid " " data |
||||
} |
||||
|
||||
/^DECLARE_UNIQUE_INDEX\(/ { |
||||
# ---- |
||||
# end any prior catalog data insertions before starting a define unique index |
||||
# ---- |
||||
if (reln_open == 1) { |
||||
print "close " catalog; |
||||
reln_open = 0; |
||||
} |
||||
|
||||
data = substr($0, 22, length($0) - 22); |
||||
pos = index(data, ","); |
||||
iname = substr(data, 1, pos-1); |
||||
data = substr(data, pos+1, length(data)-pos); |
||||
pos = index(data, ","); |
||||
oid = substr(data, 1, pos-1); |
||||
data = substr(data, pos+1, length(data)-pos); |
||||
|
||||
print "declare unique index " iname " " oid " " data |
||||
} |
||||
|
||||
/^DECLARE_TOAST\(/ { |
||||
# ---- |
||||
# end any prior catalog data insertions before starting a define toast |
||||
# ---- |
||||
if (reln_open == 1) { |
||||
print "close " catalog; |
||||
reln_open = 0; |
||||
} |
||||
|
||||
data = substr($0, 15, length($0) - 15); |
||||
pos = index(data, ","); |
||||
tname = substr(data, 1, pos-1); |
||||
data = substr(data, pos+1, length(data)-pos); |
||||
pos = index(data, ","); |
||||
toastoid = substr(data, 1, pos-1); |
||||
data = substr(data, pos+1, length(data)-pos); |
||||
# previous commands already removed the trailing ); |
||||
indexoid = data; |
||||
|
||||
print "declare toast " toastoid " " indexoid " on " tname |
||||
} |
||||
|
||||
/^BUILD_INDICES/ { print "build indices"; } |
||||
|
||||
# ---------------- |
||||
# CATALOG() definitions take some more work. |
||||
# ---------------- |
||||
/^CATALOG\(/ { |
||||
# ---- |
||||
# end any prior catalog data insertions before starting a new one.. |
||||
# ---- |
||||
if (reln_open == 1) { |
||||
print "close " catalog; |
||||
reln_open = 0; |
||||
} |
||||
|
||||
# ---- |
||||
# get the name and properties of the new catalog |
||||
# ---- |
||||
pos = index($1,")"); |
||||
catalogandoid = substr($1,9,pos-9); |
||||
pos = index(catalogandoid, ","); |
||||
catalog = substr(catalogandoid, 1, pos-1); |
||||
oid = substr(catalogandoid, pos+1, length(catalogandoid)-pos); |
||||
|
||||
if ($0 ~ /BKI_BOOTSTRAP/) { |
||||
bootstrap = " bootstrap"; |
||||
} |
||||
if ($0 ~ /BKI_SHARED_RELATION/) { |
||||
shared_relation = " shared_relation"; |
||||
} |
||||
if ($0 ~ /BKI_WITHOUT_OIDS/) { |
||||
without_oids = " without_oids"; |
||||
} |
||||
if ($0 ~ /BKI_ROWTYPE_OID\([0-9]*\)/) { |
||||
tmp = $0; |
||||
sub(/^.*BKI_ROWTYPE_OID\(/, "", tmp); |
||||
sub(/\).*$/, "", tmp); |
||||
rowtype_oid = " rowtype_oid " tmp; |
||||
} |
||||
|
||||
i = 1; |
||||
inside = 1; |
||||
nc++; |
||||
next; |
||||
} |
||||
|
||||
# ---------------- |
||||
# process the columns of the catalog definition |
||||
# |
||||
# attname[ x ] contains the attribute name for attribute x |
||||
# atttype[ x ] contains the attribute type fot attribute x |
||||
# ---------------- |
||||
inside == 1 { |
||||
# ---- |
||||
# ignore a leading brace line.. |
||||
# ---- |
||||
if ($1 ~ /\{/) |
||||
next; |
||||
|
||||
# ---- |
||||
# if this is the last line, then output the bki catalog stuff. |
||||
# ---- |
||||
if ($1 ~ /}/) { |
||||
print "create " catalog " " oid bootstrap shared_relation without_oids rowtype_oid; |
||||
print "\t("; |
||||
|
||||
for (j=1; j<i-1; j++) { |
||||
print "\t " attname[ j ] " = " atttype[ j ] " ,"; |
||||
} |
||||
print "\t " attname[ j ] " = " atttype[ j ] ; |
||||
print "\t)"; |
||||
|
||||
if (bootstrap == "") { |
||||
print "open " catalog; |
||||
} |
||||
|
||||
i = 1; |
||||
reln_open = 1; |
||||
inside = 0; |
||||
bootstrap = ""; |
||||
shared_relation = ""; |
||||
without_oids = ""; |
||||
rowtype_oid = ""; |
||||
next; |
||||
} |
||||
|
||||
# ---- |
||||
# we are inside the catalog definition, so keep sucking up |
||||
# attribute names and types |
||||
# ---- |
||||
if ($2 ~ /\[.*\]/) { # array attribute |
||||
idlen = index($2,"[") - 1; |
||||
atttype[ i ] = $1 "[]"; # variable-length only.. |
||||
attname[ i ] = substr($2,1,idlen); |
||||
} else { |
||||
atttype[ i ] = $1; |
||||
attname[ i ] = $2; |
||||
} |
||||
i++; |
||||
next; |
||||
} |
||||
|
||||
END { |
||||
if (reln_open == 1) { |
||||
print "close " catalog; |
||||
reln_open = 0; |
||||
} |
||||
} |
||||
' "descriptionfile=${OUTPUT_PREFIX}.description.$$" "shdescriptionfile=${OUTPUT_PREFIX}.shdescription.$$" > $TMPFILE || exit |
||||
|
||||
echo "# PostgreSQL $major_version" >${OUTPUT_PREFIX}.bki.$$ |
||||
|
||||
sed -e '/^[ ]*$/d' \ |
||||
-e 's/[ ][ ]*/ /g' $TMPFILE >>${OUTPUT_PREFIX}.bki.$$ || exit |
||||
|
||||
# |
||||
# Sanity check: if one of the sed/awk/etc commands fails, we'll probably |
||||
# end up with a .bki file that is empty or just a few lines. Cross-check |
||||
# that the files are of reasonable size. The numbers here are arbitrary, |
||||
# but are much smaller than the actual expected sizes as of Postgres 7.2. |
||||
# |
||||
if [ `wc -c < ${OUTPUT_PREFIX}.bki.$$` -lt 100000 ]; then |
||||
echo "$CMDNAME: something seems to be wrong with the .bki file" >&2 |
||||
exit 1 |
||||
fi |
||||
if [ `wc -c < ${OUTPUT_PREFIX}.description.$$` -lt 10000 ]; then |
||||
echo "$CMDNAME: something seems to be wrong with the .description file" >&2 |
||||
exit 1 |
||||
fi |
||||
if [ `wc -c < ${OUTPUT_PREFIX}.shdescription.$$` -lt 10 ]; then |
||||
echo "$CMDNAME: something seems to be wrong with the .shdescription file" >&2 |
||||
exit 1 |
||||
fi |
||||
|
||||
# Looks good, commit ... |
||||
|
||||
mv ${OUTPUT_PREFIX}.bki.$$ ${OUTPUT_PREFIX}.bki || exit |
||||
mv ${OUTPUT_PREFIX}.description.$$ ${OUTPUT_PREFIX}.description || exit |
||||
mv ${OUTPUT_PREFIX}.shdescription.$$ ${OUTPUT_PREFIX}.shdescription || exit |
||||
|
||||
exit 0 |
@ -1,253 +0,0 @@ |
||||
#! /bin/sh |
||||
#------------------------------------------------------------------------- |
||||
# |
||||
# Gen_fmgrtab.sh |
||||
# shell script to generate fmgroids.h and fmgrtab.c from pg_proc.h |
||||
# |
||||
# NOTE: if you change this, you need to fix Gen_fmgrtab.pl too! |
||||
# |
||||
# Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group |
||||
# Portions Copyright (c) 1994, Regents of the University of California |
||||
# |
||||
# |
||||
# IDENTIFICATION |
||||
# $PostgreSQL: pgsql/src/backend/utils/Gen_fmgrtab.sh,v 1.42 2010/01/02 16:57:53 momjian Exp $ |
||||
# |
||||
#------------------------------------------------------------------------- |
||||
|
||||
CMDNAME=`basename $0` |
||||
|
||||
if [ x"$AWK" = x"" ]; then |
||||
AWK=awk |
||||
fi |
||||
|
||||
cleanup(){ |
||||
[ x"$noclean" != x"t" ] && rm -f "$SORTEDFILE" "$$-$OIDSFILE" "$$-$TABLEFILE" |
||||
} |
||||
|
||||
noclean= |
||||
|
||||
# |
||||
# Process command line switches. |
||||
# |
||||
while [ $# -gt 0 ] |
||||
do |
||||
case $1 in |
||||
--noclean) |
||||
noclean=t |
||||
;; |
||||
--help) |
||||
echo "$CMDNAME generates fmgroids.h and fmgrtab.c from pg_proc.h." |
||||
echo |
||||
echo "Usage:" |
||||
echo " $CMDNAME inputfile" |
||||
echo |
||||
echo "The environment variable AWK determines which Awk program" |
||||
echo "to use. The default is \`awk'." |
||||
echo |
||||
echo "Report bugs to <pgsql-bugs@postgresql.org>." |
||||
exit 0 |
||||
;; |
||||
-*) |
||||
echo "$CMDNAME: invalid option: $1" |
||||
exit 1 |
||||
;; |
||||
*) |
||||
INFILE=$1 |
||||
;; |
||||
esac |
||||
shift |
||||
done |
||||
|
||||
|
||||
if [ x"$INFILE" = x ] ; then |
||||
echo "$CMDNAME: no input file" |
||||
exit 1 |
||||
fi |
||||
|
||||
SORTEDFILE="$$-fmgr.data" |
||||
OIDSFILE=fmgroids.h |
||||
TABLEFILE=fmgrtab.c |
||||
|
||||
|
||||
trap 'echo "Caught signal." ; cleanup ; exit 1' 1 2 15 |
||||
|
||||
# |
||||
# Collect the column numbers of the pg_proc columns we need. Because we will |
||||
# be looking at data that includes the OID as the first column, add one to |
||||
# each column number. |
||||
# |
||||
proname=`egrep '^#define Anum_pg_proc_proname[ ]' $INFILE | $AWK '{print $3+1}'` |
||||
prolang=`egrep '^#define Anum_pg_proc_prolang[ ]' $INFILE | $AWK '{print $3+1}'` |
||||
proisstrict=`egrep '^#define Anum_pg_proc_proisstrict[ ]' $INFILE | $AWK '{print $3+1}'` |
||||
proretset=`egrep '^#define Anum_pg_proc_proretset[ ]' $INFILE | $AWK '{print $3+1}'` |
||||
pronargs=`egrep '^#define Anum_pg_proc_pronargs[ ]' $INFILE | $AWK '{print $3+1}'` |
||||
prosrc=`egrep '^#define Anum_pg_proc_prosrc[ ]' $INFILE | $AWK '{print $3+1}'` |
||||
|
||||
# |
||||
# Generate the file containing raw pg_proc data. We do three things here: |
||||
# 1. Strip off the DATA macro call, leaving procedure OID as $1 |
||||
# and all the pg_proc field values as $2, $3, etc on each line. |
||||
# 2. Fold quoted fields to simple "xxx". We need this because such fields |
||||
# may contain whitespace, which would confuse awk's counting of fields. |
||||
# Fortunately, this script doesn't need to look at any fields that might |
||||
# need quoting, so this simple hack is sufficient. |
||||
# 3. Select out just the rows for internal-language procedures. |
||||
# |
||||
# Note assumption here that INTERNALlanguageId == 12. |
||||
# |
||||
egrep '^DATA' $INFILE | \ |
||||
sed -e 's/^[^O]*OID[^=]*=[ ]*//' \ |
||||
-e 's/(//' \ |
||||
-e 's/"[^"]*"/"xxx"/g' | \ |
||||
$AWK "\$$prolang == \"12\" { print }" | \ |
||||
sort -n > $SORTEDFILE |
||||
|
||||
if [ $? -ne 0 ]; then |
||||
cleanup |
||||
echo "$CMDNAME failed" |
||||
exit 1 |
||||
fi |
||||
|
||||
|
||||
cpp_define=`echo $OIDSFILE | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | sed -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'` |
||||
|
||||
# |
||||
# Generate fmgroids.h |
||||
# |
||||
cat > "$$-$OIDSFILE" <<FuNkYfMgRsTuFf |
||||
/*------------------------------------------------------------------------- |
||||
* |
||||
* $OIDSFILE |
||||
* 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. |
||||
* |
||||
* Portions Copyright (c) 1996-2010, 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 $CMDNAME |
||||
* from $INFILE |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef $cpp_define |
||||
#define $cpp_define |
||||
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
FuNkYfMgRsTuFf |
||||
|
||||
tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' < $SORTEDFILE | \ |
||||
$AWK "{ if (seenit[\$$prosrc]++ == 0) |
||||
printf \"#define F_%s %s\\n\", \$$prosrc, \$1; }" >> "$$-$OIDSFILE" |
||||
|
||||
if [ $? -ne 0 ]; then |
||||
cleanup |
||||
echo "$CMDNAME failed" |
||||
exit 1 |
||||
fi |
||||
|
||||
cat >> "$$-$OIDSFILE" <<FuNkYfMgRsTuFf |
||||
|
||||
#endif /* $cpp_define */ |
||||
FuNkYfMgRsTuFf |
||||
|
||||
# |
||||
# Generate fmgr's built-in-function table. |
||||
# |
||||
# Print out the function declarations, then the table that refers to them. |
||||
# |
||||
cat > "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF |
||||
/*------------------------------------------------------------------------- |
||||
* |
||||
* $TABLEFILE |
||||
* The function manager's table of internal functions. |
||||
* |
||||
* Portions Copyright (c) 1996-2010, 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 $CMDNAME |
||||
* from $INFILE |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#include "postgres.h" |
||||
|
||||
#include "utils/fmgrtab.h" |
||||
|
||||
FuNkYfMgRtAbStUfF |
||||
|
||||
$AWK "{ if (seenit[\$$prosrc]++ == 0) |
||||
print \"extern Datum\", \$$prosrc, \"(PG_FUNCTION_ARGS);\"; }" $SORTEDFILE >> "$$-$TABLEFILE" |
||||
|
||||
if [ $? -ne 0 ]; then |
||||
cleanup |
||||
echo "$CMDNAME failed" |
||||
exit 1 |
||||
fi |
||||
|
||||
|
||||
cat >> "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF |
||||
|
||||
const FmgrBuiltin fmgr_builtins[] = { |
||||
FuNkYfMgRtAbStUfF |
||||
|
||||
# Note: using awk arrays to translate from pg_proc values to fmgrtab values |
||||
# may seem tedious, but avoid the temptation to write a quick x?y:z |
||||
# conditional expression instead. Not all awks have conditional expressions. |
||||
|
||||
$AWK "BEGIN { |
||||
Bool[\"t\"] = \"true\"; |
||||
Bool[\"f\"] = \"false\"; |
||||
} |
||||
{ printf (\" { %d, \\\"%s\\\", %d, %s, %s, %s },\\n\"), |
||||
\$1, \$$prosrc, \$$pronargs, Bool[\$$proisstrict], Bool[\$$proretset], \$$prosrc ; |
||||
}" $SORTEDFILE >> "$$-$TABLEFILE" |
||||
|
||||
if [ $? -ne 0 ]; then |
||||
cleanup |
||||
echo "$CMDNAME failed" |
||||
exit 1 |
||||
fi |
||||
|
||||
cat >> "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF |
||||
/* 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; |
||||
FuNkYfMgRtAbStUfF |
||||
|
||||
# We use the temporary files to avoid problems with concurrent runs |
||||
# (which can happen during parallel make). |
||||
mv "$$-$OIDSFILE" $OIDSFILE |
||||
mv "$$-$TABLEFILE" $TABLEFILE |
||||
|
||||
cleanup |
||||
exit 0 |
@ -1,262 +0,0 @@ |
||||
#!/usr/bin/perl |
||||
#------------------------------------------------------------------------- |
||||
# |
||||
# Genbki.pm -- |
||||
# perl script which generates .bki files from specially formatted .h |
||||
# files. These .bki files are used to initialize the postgres template |
||||
# database. |
||||
# |
||||
# Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group |
||||
# Portions Copyright (c) 1994, Regents of the University of California |
||||
# |
||||
# |
||||
# IDENTIFICATION |
||||
# $PostgreSQL: pgsql/src/tools/msvc/Genbki.pm,v 1.9 2010/01/02 16:58:17 momjian Exp $ |
||||
# |
||||
#------------------------------------------------------------------------- |
||||
|
||||
package Genbki; |
||||
|
||||
use strict; |
||||
use warnings; |
||||
|
||||
use Exporter; |
||||
our (@ISA, @EXPORT_OK); |
||||
@ISA = qw(Exporter); |
||||
@EXPORT_OK = qw(genbki); |
||||
|
||||
sub genbki |
||||
{ |
||||
my $version = shift; |
||||
my $prefix = shift; |
||||
|
||||
$version =~ /^(\d+\.\d+)/ || die "Bad format version $version\n"; |
||||
my $majorversion = $1; |
||||
|
||||
my $pgauthid = read_file("src/include/catalog/pg_authid.h"); |
||||
$pgauthid =~ /^#define\s+BOOTSTRAP_SUPERUSERID\s+(\d+)$/mg |
||||
|| die "Could not read BOOTSTRAP_SUPERUSERID from pg_authid.h\n"; |
||||
my $bootstrapsuperuserid = $1; |
||||
|
||||
my $pgnamespace = read_file("src/include/catalog/pg_namespace.h"); |
||||
$pgnamespace =~ /^#define\s+PG_CATALOG_NAMESPACE\s+(\d+)$/mg |
||||
|| die "Could not read PG_CATALOG_NAMESPACE from pg_namespace.h\n"; |
||||
my $pgcatalognamespace = $1; |
||||
|
||||
my $indata = ""; |
||||
|
||||
while (@_) |
||||
{ |
||||
my $f = shift; |
||||
next unless $f; |
||||
$indata .= read_file($f); |
||||
$indata .= "\n"; |
||||
} |
||||
|
||||
# Strip C comments, from perl FAQ 4.27 |
||||
$indata =~ s{/\*.*?\*/}{}gs; |
||||
|
||||
$indata =~ s{;\s*$}{}gm; |
||||
$indata =~ s{^\s+}{}gm; |
||||
$indata =~ s{^Oid}{oid}gm; |
||||
$indata =~ s{\(Oid}{(oid}gm; |
||||
$indata =~ s{^NameData}{name}gm; |
||||
$indata =~ s{\(NameData}{(name}g; |
||||
$indata =~ s{^TransactionId}{xid}gm; |
||||
$indata =~ s{\(TransactionId}{(xid}g; |
||||
$indata =~ s{PGUID}{$bootstrapsuperuserid}g; |
||||
$indata =~ s{PGNSP}{$pgcatalognamespace}g; |
||||
|
||||
#print $indata; |
||||
|
||||
my $bki = ""; |
||||
my $desc = ""; |
||||
my $shdesc = ""; |
||||
|
||||
my $oid = 0; |
||||
my $catalog = 0; |
||||
my $reln_open = 0; |
||||
my $bootstrap = ""; |
||||
my $shared_relation = ""; |
||||
my $without_oids = ""; |
||||
my $rowtype_oid = ""; |
||||
my $nc = 0; |
||||
my $inside = 0; |
||||
my @attr; |
||||
my @types; |
||||
|
||||
foreach my $line (split /\n/, $indata) |
||||
{ |
||||
if ($line =~ /^DATA\((.*)\)$/m) |
||||
{ |
||||
my $data = $1; |
||||
my @fields = split /\s+/,$data; |
||||
if ($#fields >=4 && $fields[0] eq "insert" && $fields[1] eq "OID" && $fields[2] eq "=") |
||||
{ |
||||
$oid = $fields[3]; |
||||
} |
||||
else |
||||
{ |
||||
$oid = 0; |
||||
} |
||||
$data =~ s/\s+/ /g; |
||||
$bki .= $data . "\n"; |
||||
} |
||||
elsif ($line =~ /^DESCR\("(.*)"\)$/m) |
||||
{ |
||||
if ($oid != 0) |
||||
{ |
||||
$desc .= sprintf("%d\t%s\t0\t%s\n", $oid, $catalog, $1); |
||||
} |
||||
} |
||||
elsif ($line =~ /^SHDESCR\("(.*)"\)$/m) |
||||
{ |
||||
if ($oid != 0) |
||||
{ |
||||
$shdesc .= sprintf("%d\t%s\t%s\n", $oid, $catalog, $1); |
||||
} |
||||
} |
||||
elsif ($line =~ /^DECLARE_(UNIQUE_)?INDEX\((.*)\)$/m) |
||||
{ |
||||
if ($reln_open) |
||||
{ |
||||
$bki .= "close $catalog\n"; |
||||
$reln_open = 0; |
||||
} |
||||
my $u = $1?" unique":""; |
||||
my @fields = split /,/,$2,3; |
||||
$fields[0] =~ s/\s+//g; |
||||
$fields[1] =~ s/\s+//g; |
||||
$fields[2] =~ s/\s+/ /g; |
||||
$fields[2] =~ s/^\s+//; |
||||
$bki .= "declare$u index $fields[0] $fields[1] $fields[2]\n"; |
||||
} |
||||
elsif ($line =~ /^DECLARE_TOAST\((.*)\)$/m) |
||||
{ |
||||
if ($reln_open) |
||||
{ |
||||
$bki .= "close $catalog\n"; |
||||
$reln_open = 0; |
||||
} |
||||
my @fields = split /,/,$1; |
||||
$fields[1] =~ s/\s+//g; |
||||
$fields[2] =~ s/\s+//g; |
||||
$bki .= "declare toast $fields[1] $fields[2] on $fields[0]\n"; |
||||
} |
||||
elsif ($line =~ /^BUILD_INDICES/) |
||||
{ |
||||
$bki .= "build indices\n"; |
||||
} |
||||
elsif ($line =~ /^CATALOG\(([^)]*)\)(.*)$/m) |
||||
{ |
||||
if ($reln_open) |
||||
{ |
||||
$bki .= "close $catalog\n"; |
||||
$reln_open = 0; |
||||
} |
||||
my $rest = $2; |
||||
my @fields = split /,/,$1; |
||||
$catalog = $fields[0]; |
||||
$oid = $fields[1]; |
||||
$bootstrap=$shared_relation=$without_oids=$rowtype_oid=""; |
||||
if ($rest =~ /BKI_BOOTSTRAP/) |
||||
{ |
||||
$bootstrap = " bootstrap"; |
||||
} |
||||
if ($rest =~ /BKI_SHARED_RELATION/) |
||||
{ |
||||
$shared_relation = " shared_relation"; |
||||
} |
||||
if ($rest =~ /BKI_WITHOUT_OIDS/) |
||||
{ |
||||
$without_oids = " without_oids"; |
||||
} |
||||
if ($rest =~ /BKI_ROWTYPE_OID\((\d+)\)/) |
||||
{ |
||||
$rowtype_oid = " rowtype_oid $1"; |
||||
} |
||||
$nc++; |
||||
$inside = 1; |
||||
next; |
||||
} |
||||
if ($inside==1) |
||||
{ |
||||
next if ($line =~ /{/); |
||||
if ($line =~ /}/) |
||||
{ |
||||
|
||||
# Last line |
||||
$bki .= "create $catalog $oid$bootstrap$shared_relation$without_oids$rowtype_oid\n (\n"; |
||||
my $first = 1; |
||||
for (my $i = 0; $i <= $#attr; $i++) |
||||
{ |
||||
if ($first == 1) |
||||
{ |
||||
$first = 0; |
||||
} |
||||
else |
||||
{ |
||||
$bki .= " ,\n"; |
||||
} |
||||
$bki .= " " . $attr[$i] . " = " . $types[$i]; |
||||
} |
||||
$bki .= "\n )\n"; |
||||
undef(@attr); |
||||
undef(@types); |
||||
$reln_open = 1; |
||||
$inside = 0; |
||||
if ($bootstrap eq "") |
||||
{ |
||||
$bki .= "open $catalog\n"; |
||||
} |
||||
next; |
||||
} |
||||
|
||||
# inside catalog definition, so keep sucking up attributes |
||||
my @fields = split /\s+/,$line; |
||||
if ($fields[1] =~ /(.*)\[.*\]/) |
||||
{ #Array attribute |
||||
push @attr, $1; |
||||
push @types, $fields[0] . '[]'; |
||||
} |
||||
else |
||||
{ |
||||
push @attr, $fields[1]; |
||||
push @types, $fields[0]; |
||||
} |
||||
next; |
||||
} |
||||
} |
||||
if ($reln_open == 1) |
||||
{ |
||||
$bki .= "close $catalog\n"; |
||||
} |
||||
|
||||
open(O,">$prefix.bki") || die "Could not write $prefix.bki\n"; |
||||
print O "# PostgreSQL $majorversion\n"; |
||||
print O $bki; |
||||
close(O); |
||||
open(O,">$prefix.description") || die "Could not write $prefix.description\n"; |
||||
print O $desc; |
||||
close(O); |
||||
open(O,">$prefix.shdescription") || die "Could not write $prefix.shdescription\n"; |
||||
print O $shdesc; |
||||
close(O); |
||||
} |
||||
|
||||
sub read_file |
||||
{ |
||||
my $filename = shift; |
||||
my $F; |
||||
my $t = $/; |
||||
|
||||
undef $/; |
||||
open($F, $filename) || die "Could not open file $filename\n"; |
||||
my $txt = <$F>; |
||||
close($F); |
||||
$/ = $t; |
||||
|
||||
return $txt; |
||||
} |
||||
|
||||
1; |
Loading…
Reference in new issue