From 64737e93132b036006ca16e793c634e5939d42db Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 5 Jan 2010 01:06:57 +0000 Subject: [PATCH] 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 --- doc/src/sgml/bki.sgml | 8 +- doc/src/sgml/installation.sgml | 28 +- src/backend/Makefile | 45 +- src/backend/catalog/.cvsignore | 4 + src/backend/catalog/Catalog.pm | 201 ++++++++ src/backend/catalog/Makefile | 20 +- src/backend/catalog/README | 7 +- src/backend/catalog/genbki.pl | 432 +++++++++++++++++ src/backend/catalog/genbki.sh | 438 ------------------ src/backend/utils/Gen_fmgrtab.pl | 125 ++--- src/backend/utils/Gen_fmgrtab.sh | 253 ---------- src/backend/utils/Makefile | 19 +- src/backend/utils/cache/relcache.c | 3 +- src/include/Makefile | 4 +- src/include/catalog/genbki.h | 5 +- src/include/catalog/indexing.h | 6 +- src/include/catalog/pg_aggregate.h | 4 +- src/include/catalog/pg_am.h | 4 +- src/include/catalog/pg_amop.h | 4 +- src/include/catalog/pg_amproc.h | 4 +- src/include/catalog/pg_attrdef.h | 4 +- src/include/catalog/pg_attribute.h | 317 +------------ src/include/catalog/pg_auth_members.h | 4 +- src/include/catalog/pg_authid.h | 4 +- src/include/catalog/pg_cast.h | 4 +- src/include/catalog/pg_class.h | 6 +- src/include/catalog/pg_constraint.h | 4 +- src/include/catalog/pg_conversion.h | 4 +- src/include/catalog/pg_database.h | 6 +- src/include/catalog/pg_db_role_setting.h | 4 +- src/include/catalog/pg_default_acl.h | 4 +- src/include/catalog/pg_depend.h | 4 +- src/include/catalog/pg_description.h | 6 +- src/include/catalog/pg_enum.h | 4 +- src/include/catalog/pg_foreign_data_wrapper.h | 4 +- src/include/catalog/pg_foreign_server.h | 4 +- src/include/catalog/pg_index.h | 6 +- src/include/catalog/pg_inherits.h | 4 +- src/include/catalog/pg_language.h | 4 +- src/include/catalog/pg_largeobject.h | 4 +- src/include/catalog/pg_largeobject_metadata.h | 4 +- src/include/catalog/pg_listener.h | 4 +- src/include/catalog/pg_namespace.h | 4 +- src/include/catalog/pg_opclass.h | 4 +- src/include/catalog/pg_operator.h | 4 +- src/include/catalog/pg_opfamily.h | 4 +- src/include/catalog/pg_pltemplate.h | 4 +- src/include/catalog/pg_proc.h | 8 +- src/include/catalog/pg_rewrite.h | 4 +- src/include/catalog/pg_shdepend.h | 4 +- src/include/catalog/pg_shdescription.h | 6 +- src/include/catalog/pg_statistic.h | 4 +- src/include/catalog/pg_tablespace.h | 4 +- src/include/catalog/pg_trigger.h | 4 +- src/include/catalog/pg_ts_config.h | 4 +- src/include/catalog/pg_ts_config_map.h | 4 +- src/include/catalog/pg_ts_dict.h | 4 +- src/include/catalog/pg_ts_parser.h | 4 +- src/include/catalog/pg_ts_template.h | 4 +- src/include/catalog/pg_type.h | 10 +- src/include/catalog/pg_user_mapping.h | 4 +- src/include/catalog/toasting.h | 6 +- src/interfaces/ecpg/ecpglib/pg_type.h | 18 +- src/tools/msvc/Genbki.pm | 262 ----------- src/tools/msvc/Solution.pm | 18 +- src/tools/msvc/clean.bat | 13 +- 66 files changed, 929 insertions(+), 1499 deletions(-) create mode 100644 src/backend/catalog/.cvsignore create mode 100644 src/backend/catalog/Catalog.pm create mode 100644 src/backend/catalog/genbki.pl delete mode 100644 src/backend/catalog/genbki.sh delete mode 100644 src/backend/utils/Gen_fmgrtab.sh delete mode 100644 src/tools/msvc/Genbki.pm diff --git a/doc/src/sgml/bki.sgml b/doc/src/sgml/bki.sgml index d0c08e08d9..d747f9244e 100644 --- a/doc/src/sgml/bki.sgml +++ b/doc/src/sgml/bki.sgml @@ -1,4 +1,4 @@ - + <acronym>BKI</acronym> Backend Interface @@ -20,10 +20,10 @@ to do part of its job when creating a new database cluster. The input file used by initdb is created as part of building and installing PostgreSQL - by a program named genbki.sh, which reads some + by a program named genbki.pl, which reads some specially formatted C header files in the src/include/catalog/ - directory of the source tree. The created - BKI file is called postgres.bki and is + directory of the source tree. The created BKI file + is called postgres.bki and is normally installed in the share subdirectory of the installation tree. diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index 3074172bc5..41513dcb9a 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -1,4 +1,4 @@ - + <![%standalone-include[<productname>PostgreSQL</>]]> @@ -125,10 +125,10 @@ su - postgres <filename>libedit</filename> library is GNU <productname>Readline</productname>-compatible and is used if <filename>libreadline</filename> is not found, or if - <option>--with-libedit-preferred</option> is used as an + <option>--with-libedit-preferred</option> is used as an option to <filename>configure</>. If you are using a package-based - Linux distribution, be aware that you need both the - <literal>readline</> and <literal>readline-devel</> packages, if + Linux distribution, be aware that you need both the + <literal>readline</> and <literal>readline-devel</> packages, if those are separate in your distribution. </para> </listitem> @@ -266,7 +266,7 @@ su - postgres <listitem> <para> - <application>Kerberos</>, <productname>OpenSSL</>, + <application>Kerberos</>, <productname>OpenSSL</>, <productname>OpenLDAP</>, and/or <application>PAM</>, if you want to support authentication or encryption using these services. @@ -310,7 +310,7 @@ su - postgres <primary>perl</primary> </indexterm> - <application>Perl</> is also needed to build from a CVS checkout, + <application>Perl</> 5.8 or later is needed to build from a CVS checkout, or if you changed the input files for any of the build steps that use Perl scripts. If building on Windows you will need <application>Perl</> in any case. @@ -456,7 +456,7 @@ su - postgres delete it, in case you have trouble and need to revert to it. Keep in mind the directory might consume significant disk space. To rename the directory, use a command like this: -<screen> +<screen> <userinput>mv /usr/local/pgsql /usr/local/pgsql.old</> </screen> </para> @@ -581,7 +581,7 @@ su - postgres </para> <para> - For relocatable installs, you might want to use + For relocatable installs, you might want to use <filename>configure</filename>'s <literal>--disable-rpath</> option. Also, you will need to tell the operating system how to find the shared libraries. @@ -943,7 +943,7 @@ su - postgres <listitem> <para> Build with <acronym>LDAP</><indexterm><primary>LDAP</></> - support for authentication and connection parameter lookup (see + support for authentication and connection parameter lookup (see <![%standalone-include[the documentation about client authentication and libpq]]><![%standalone-ignore[<xref linkend="libpq-ldap"> and <xref linkend="auth-ldap">]]> for more information). On Unix, @@ -952,7 +952,7 @@ su - postgres library is used. <filename>configure</> will check for the required header files and libraries to make sure that your <productname>OpenLDAP</> installation is sufficient before - proceeding. + proceeding. </para> </listitem> </varlistentry> @@ -1381,7 +1381,7 @@ su - postgres <para> Here is a list of the significant variables that can be set in this manner: - + <variablelist> <varlistentry> <term><envar>BISON</envar></term> @@ -1635,7 +1635,7 @@ All of PostgreSQL is successfully made. Ready to install. </procedure> <formalpara> - <title>Registering <application>eventlog</> on <systemitem + <title>Registering <application>eventlog</> on <systemitem class="osname">Windows</>: To register a Windows eventlog @@ -1887,7 +1887,7 @@ postgres$ /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data At this point, if you did not use the initdb -A option, you might want to modify pg_hba.conf to control - local access to the server before you start it. The default is to + local access to the server before you start it. The default is to trust all local users. @@ -2678,7 +2678,7 @@ cc-1020 cc: ERROR File = pqcomm.c, Line = 427 MinGW. The ready-made installer files are available on the main PostgreSQL FTP servers in the binary/win32 directory. - + The native Win32 port requires a 32-bit NT-based Microsoft diff --git a/src/backend/Makefile b/src/backend/Makefile index 352357bee8..ac46d50836 100644 --- a/src/backend/Makefile +++ b/src/backend/Makefile @@ -5,7 +5,7 @@ # Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # -# $PostgreSQL: pgsql/src/backend/Makefile,v 1.137 2010/01/02 16:57:33 momjian Exp $ +# $PostgreSQL: pgsql/src/backend/Makefile,v 1.138 2010/01/05 01:06:56 tgl Exp $ # #------------------------------------------------------------------------- @@ -42,7 +42,7 @@ LIBS := $(filter-out -lz -lreadline -ledit -ltermcap -lncurses -lcurses, $(LIBS) ########################################################################## -all: submake-libpgport postgres $(POSTGRES_IMP) +all: submake-libpgport submake-schemapg postgres $(POSTGRES_IMP) ifneq ($(PORTNAME), cygwin) ifneq ($(PORTNAME), win32) @@ -111,7 +111,13 @@ endif endif # aix # Update the commonly used headers before building the subdirectories -$(SUBDIRS:%=%-recursive): $(top_builddir)/src/include/parser/gram.h $(top_builddir)/src/include/utils/fmgroids.h $(top_builddir)/src/include/utils/probes.h +$(SUBDIRS:%=%-recursive): $(top_builddir)/src/include/parser/gram.h $(top_builddir)/src/include/catalog/schemapg.h $(top_builddir)/src/include/utils/fmgroids.h $(top_builddir)/src/include/utils/probes.h + +# run this unconditionally to avoid needing to know its dependencies here: +submake-schemapg: + $(MAKE) -C catalog schemapg.h + +.PHONY: submake-schemapg # The postgres.o target is needed by the rule in Makefile.global that @@ -127,7 +133,7 @@ postgres.o: $(OBJS) parser/gram.h: parser/gram.y $(MAKE) -C parser gram.h -utils/fmgroids.h: utils/Gen_fmgrtab.sh $(top_srcdir)/src/include/catalog/pg_proc.h +utils/fmgroids.h: utils/Gen_fmgrtab.pl catalog/Catalog.pm $(top_srcdir)/src/include/catalog/pg_proc.h $(MAKE) -C utils fmgroids.h utils/probes.h: utils/probes.d @@ -136,15 +142,28 @@ utils/probes.h: utils/probes.d # Make symlinks for these headers in the include directory. That way # we can cut down on the -I options. Also, a symlink is automatically # up to date when we update the base file. +# +# The point of the prereqdir incantation in some of the rules below is to +# force the symlink to use an absolute path rather than a relative path. +# For headers which are generated by make distprep, the actual header within +# src/backend will be in the source tree, while the symlink in src/include +# will be in the build tree, so a simple ../.. reference won't work. +# For headers generated during regular builds, we prefer a relative symlink. $(top_builddir)/src/include/parser/gram.h: parser/gram.h prereqdir=`cd $(dir $<) >/dev/null && pwd` && \ cd $(dir $@) && rm -f $(notdir $@) && \ $(LN_S) "$$prereqdir/$(notdir $<)" . +$(top_builddir)/src/include/catalog/schemapg.h: catalog/schemapg.h + prereqdir=`cd $(dir $<) >/dev/null && pwd` && \ + cd $(dir $@) && rm -f $(notdir $@) && \ + $(LN_S) "$$prereqdir/$(notdir $<)" . + $(top_builddir)/src/include/utils/fmgroids.h: utils/fmgroids.h - cd $(dir $@) && rm -f $(notdir $@) && \ - $(LN_S) ../../../$(subdir)/utils/fmgroids.h . + prereqdir=`cd $(dir $<) >/dev/null && pwd` && \ + cd $(dir $@) && rm -f $(notdir $@) && \ + $(LN_S) "$$prereqdir/$(notdir $<)" . $(top_builddir)/src/include/utils/probes.h: utils/probes.h cd $(dir $@) && rm -f $(notdir $@) && \ @@ -160,6 +179,8 @@ utils/probes.o: utils/probes.d $(SUBDIROBJS) distprep: $(MAKE) -C parser gram.c gram.h scan.c $(MAKE) -C bootstrap bootparse.c bootscanner.c + $(MAKE) -C catalog schemapg.h postgres.bki postgres.description postgres.shdescription + $(MAKE) -C utils fmgrtab.c fmgroids.h $(MAKE) -C utils/misc guc-file.c @@ -243,8 +264,10 @@ endif clean: rm -f $(LOCALOBJS) postgres$(X) $(POSTGRES_IMP) \ - $(top_srcdir)/src/include/parser/gram.h \ - $(top_builddir)/src/include/utils/fmgroids.h + $(top_builddir)/src/include/parser/gram.h \ + $(top_builddir)/src/include/catalog/schemapg.h \ + $(top_builddir)/src/include/utils/fmgroids.h \ + $(top_builddir)/src/include/utils/probes.h ifeq ($(PORTNAME), cygwin) rm -f postgres.dll postgres.def libpostgres.a endif @@ -261,6 +284,12 @@ maintainer-clean: distclean parser/gram.c \ parser/scan.c \ parser/gram.h \ + catalog/schemapg.h \ + catalog/postgres.bki \ + catalog/postgres.description \ + catalog/postgres.shdescription \ + utils/fmgroids.h \ + utils/fmgrtab.c \ utils/misc/guc-file.c diff --git a/src/backend/catalog/.cvsignore b/src/backend/catalog/.cvsignore new file mode 100644 index 0000000000..242e32155f --- /dev/null +++ b/src/backend/catalog/.cvsignore @@ -0,0 +1,4 @@ +postgres.bki +postgres.description +postgres.shdescription +schemapg.h diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm new file mode 100644 index 0000000000..3b6a723faa --- /dev/null +++ b/src/backend/catalog/Catalog.pm @@ -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 () + { + # Strip C-style comments. + s;/\*(.|\n)*\*/;;g; + if (m;/\*;) + { + # handle multi-line comments properly. + my $next_line = ; + 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 = ; + my $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; diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile index 02a2b01b81..7e75a99abd 100644 --- a/src/backend/catalog/Makefile +++ b/src/backend/catalog/Makefile @@ -2,7 +2,7 @@ # # Makefile for backend/catalog # -# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.74 2009/12/11 03:34:55 itagaki Exp $ +# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.75 2010/01/05 01:06:56 tgl Exp $ # #------------------------------------------------------------------------- @@ -19,7 +19,7 @@ BKIFILES = postgres.bki postgres.description postgres.shdescription include $(top_srcdir)/src/backend/common.mk -all: $(BKIFILES) +all: $(BKIFILES) schemapg.h # Note: there are some undocumented dependencies on the ordering in which # the catalog header files are assembled into postgres.bki. In particular, @@ -41,15 +41,21 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\ toasting.h indexing.h \ ) -pg_includes = $(sort -I$(top_srcdir)/src/include -I$(top_builddir)/src/include) +# location of Catalog.pm +catalogdir = $(top_srcdir)/src/backend/catalog + +# locations of headers that genbki.pl needs to read +pg_includes = -I$(top_srcdir)/src/include/catalog -I$(top_builddir)/src/include/catalog # see explanation in ../parser/Makefile postgres.description: postgres.bki ; postgres.shdescription: postgres.bki ; -postgres.bki: genbki.sh $(POSTGRES_BKI_SRCS) $(top_builddir)/src/include/pg_config_manual.h - AWK='$(AWK)' $(SHELL) $< $(pg_includes) --set-version=$(VERSION) -o postgres $(POSTGRES_BKI_SRCS) +schemapg.h: postgres.bki ; + +postgres.bki: genbki.pl Catalog.pm $(POSTGRES_BKI_SRCS) + $(PERL) -I $(catalogdir) $< $(pg_includes) --set-version=$(VERSION) $(POSTGRES_BKI_SRCS) .PHONY: install-data install-data: $(BKIFILES) installdirs @@ -67,5 +73,9 @@ installdirs: uninstall-data: rm -f $(addprefix '$(DESTDIR)$(datadir)'/, $(BKIFILES) system_views.sql information_schema.sql sql_features.txt) +# postgres.bki, postgres.description, postgres.shdescription, and schemapg.h +# are in the distribution tarball, so they are not cleaned here. clean: + +maintainer-clean: clean rm -f $(BKIFILES) diff --git a/src/backend/catalog/README b/src/backend/catalog/README index 7b71cd582d..6d7e0e23c1 100644 --- a/src/backend/catalog/README +++ b/src/backend/catalog/README @@ -1,4 +1,4 @@ -$PostgreSQL: pgsql/src/backend/catalog/README,v 1.13 2008/03/21 13:23:28 momjian Exp $ +$PostgreSQL: pgsql/src/backend/catalog/README,v 1.14 2010/01/05 01:06:56 tgl Exp $ System Catalog ============== @@ -7,7 +7,7 @@ This directory contains .c files that manipulate the system catalogs; src/include/catalog contains the .h files that define the structure of the system catalogs. -When the compile-time scripts (such as Gen_fmgrtab.sh and genbki.sh) +When the compile-time scripts (Gen_fmgrtab.pl and genbki.pl) execute, they grep the DATA statements out of the .h files and munge these in order to generate the postgres.bki file. The .bki file is then used as input to initdb (which is just a wrapper around postgres @@ -44,7 +44,7 @@ catalog's .h file, and use the #define symbol in the C code. Writing the actual numeric value of any OID in C code is considered very bad form. Direct references to pg_proc OIDs are common enough that there's a special mechanism to create the necessary #define's automatically: see -backend/utils/Gen_fmgrtab.sh. We also have standard conventions for setting +backend/utils/Gen_fmgrtab.pl. We also have standard conventions for setting up #define's for the pg_class OIDs of system catalogs and indexes. For all the other system catalogs, you have to manually create any #define's you need. @@ -75,6 +75,7 @@ POSTGRES_BKI_SRCS variable, as these cannot be created through the standard heap_create_with_catalog process, because it needs these tables to exist already. The list of files this currently includes is: pg_proc.h pg_type.h pg_attribute.h pg_class.h +Within this list, pg_type.h must come before pg_attribute.h. Also, indexing.h must be last, since the indexes can't be created until all the tables are in place, and toasting.h should probably be next-to-last (or at least after all the tables that need toast tables). There are diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl new file mode 100644 index 0000000000..2020aeeb20 --- /dev/null +++ b/src/backend/catalog/genbki.pl @@ -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 <{$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 () + { + 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 +} diff --git a/src/backend/catalog/genbki.sh b/src/backend/catalog/genbki.sh deleted file mode 100644 index d1acfe2e6f..0000000000 --- a/src/backend/catalog/genbki.sh +++ /dev/null @@ -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 ." - 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 $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 diff --git a/src/backend/utils/Gen_fmgrtab.pl b/src/backend/utils/Gen_fmgrtab.pl index 1ba7d9d362..5b281e874e 100644 --- a/src/backend/utils/Gen_fmgrtab.pl +++ b/src/backend/utils/Gen_fmgrtab.pl @@ -2,85 +2,89 @@ #------------------------------------------------------------------------- # # Gen_fmgrtab.pl -# Perl equivalent of Gen_fmgrtab.sh -# -# Usage: perl Gen_fmgrtab.pl path-to-pg_proc.h -# -# The reason for implementing this functionality twice is that we don't -# require people to have perl to build from a tarball, but on the other -# hand Windows can't deal with shell scripts. +# Perl script that generates fmgroids.h and fmgrtab.c from pg_proc.h # # 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.pl,v 1.3 2010/01/02 16:57:53 momjian Exp $ +# $PostgreSQL: pgsql/src/backend/utils/Gen_fmgrtab.pl,v 1.4 2010/01/05 01:06:56 tgl Exp $ # #------------------------------------------------------------------------- +use Catalog; + use strict; use warnings; # Collect arguments -my $infile = shift; -defined($infile) || die "$0: missing required argument: pg_proc.h\n"; - -# Note: see Gen_fmgrtab.sh for detailed commentary on what this is doing - -# Collect column numbers for pg_proc columns we need -my ($proname, $prolang, $proisstrict, $proretset, $pronargs, $prosrc); - -open(I, $infile) || die "Could not open $infile: $!"; -while () +my $infile; # pg_proc.h +my $output_path = ''; +while (@ARGV) { - if (m/#define Anum_pg_proc_proname\s+(\d+)/) { - $proname = $1; + my $arg = shift @ARGV; + if ($arg !~ /^-/) + { + $infile = $arg; } - if (m/#define Anum_pg_proc_prolang\s+(\d+)/) { - $prolang = $1; + elsif ($arg =~ /^-o/) + { + $output_path = length($arg) > 2 ? substr($arg, 2) : shift @ARGV; } - if (m/#define Anum_pg_proc_proisstrict\s+(\d+)/) { - $proisstrict = $1; - } - if (m/#define Anum_pg_proc_proretset\s+(\d+)/) { - $proretset = $1; - } - if (m/#define Anum_pg_proc_pronargs\s+(\d+)/) { - $pronargs = $1; - } - if (m/#define Anum_pg_proc_prosrc\s+(\d+)/) { - $prosrc = $1; + else + { + usage(); } } -close(I); -# Collect the raw data +# 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, keys %$column; +} -open(I, $infile) || die "Could not open $infile: $!"; -while () +my $data = $catalogs->{pg_proc}->{data}; +foreach my $row (@$data) { - next unless (/^DATA/); - s/^[^O]*OID[^=]*=[ \t]*//; - s/\(//; - s/"[^"]*"/"xxx"/g; - my @p = split; - next if ($p[$prolang] ne "12"); + + # To construct fmgroids.h and fmgrtab.c, we need to inspect some + # of the individual data fields. Just splitting on whitespace + # won't work, because some quoted fields might contain internal + # whitespace. We handle this by folding them all to a simple + # "xxx". Fortunately, this script doesn't need to look at any + # fields that might need quoting, so this simple hack is + # sufficient. + $row->{bki_values} =~ s/"[^"]*"/"xxx"/g; + @{$row}{@attnames} = split /\s+/, $row->{bki_values}; + + # Select out just the rows for internal-language procedures. + # Note assumption here that INTERNALlanguageId is 12. + next if $row->{prolang} ne '12'; + push @fmgr, { - oid => $p[0], - proname => $p[$proname], - strict => $p[$proisstrict], - retset => $p[$proretset], - nargs => $p[$pronargs], - prosrc => $p[$prosrc], + oid => $row->{oid}, + strict => $row->{proisstrict}, + retset => $row->{proretset}, + nargs => $row->{pronargs}, + prosrc => $row->{prosrc}, }; } -close(I); # Emit headers for both files -open(H, '>', "$$-fmgroids.h") || die "Could not open $$-fmgroids.h: $!"; +open H, '>', $output_path . 'fmgroids.h.tmp' || die "Could not open fmgroids.h.tmp: $!"; print H qq|/*------------------------------------------------------------------------- * @@ -119,7 +123,7 @@ qq|/*------------------------------------------------------------------------- */ |; -open(T, '>', "$$-fmgrtab.c") || die "Could not open $$-fmgrtab.c: $!"; +open T, '>', $output_path . 'fmgrtab.c.tmp' || die "Could not open fmgrtab.c.tmp: $!"; print T qq|/*------------------------------------------------------------------------- * @@ -186,9 +190,18 @@ const int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin)) - 1; close(T); # Finally, rename the completed files into place. -rename "$$-fmgroids.h", "fmgroids.h" - || die "Could not rename $$-fmgroids.h to fmgroids.h: $!"; -rename "$$-fmgrtab.c", "fmgrtab.c" - || die "Could not rename $$-fmgrtab.c to fmgrtab.c: $!"; +Catalog::RenameTempFile($output_path . 'fmgroids.h'); +Catalog::RenameTempFile($output_path . 'fmgrtab.c'); + +sub usage +{ + die <. +EOM +} exit 0; diff --git a/src/backend/utils/Gen_fmgrtab.sh b/src/backend/utils/Gen_fmgrtab.sh deleted file mode 100644 index 96b2d21164..0000000000 --- a/src/backend/utils/Gen_fmgrtab.sh +++ /dev/null @@ -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 ." - 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" <> "$$-$OIDSFILE" - -if [ $? -ne 0 ]; then - cleanup - echo "$CMDNAME failed" - exit 1 -fi - -cat >> "$$-$OIDSFILE" < "$$-$TABLEFILE" <> "$$-$TABLEFILE" - -if [ $? -ne 0 ]; then - cleanup - echo "$CMDNAME failed" - exit 1 -fi - - -cat >> "$$-$TABLEFILE" <> "$$-$TABLEFILE" - -if [ $? -ne 0 ]; then - cleanup - echo "$CMDNAME failed" - exit 1 -fi - -cat >> "$$-$TABLEFILE" <=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; diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm index 5dc95c9925..9cd8ce557f 100644 --- a/src/tools/msvc/Solution.pm +++ b/src/tools/msvc/Solution.pm @@ -3,14 +3,12 @@ package Solution; # # Package that encapsulates a Visual C++ solution file generation # -# $PostgreSQL: pgsql/src/tools/msvc/Solution.pm,v 1.51 2010/01/01 17:34:25 mha Exp $ +# $PostgreSQL: pgsql/src/tools/msvc/Solution.pm,v 1.52 2010/01/05 01:06:57 tgl Exp $ # use Carp; use strict; use warnings; -use Genbki; - sub new { my $junk = shift; @@ -240,7 +238,7 @@ s{PG_VERSION_STR "[^"]+"}{__STRINGIFY(x) #x\n#define __STRINGIFY2(z) __STRINGIFY { print "Generating fmgrtab.c and fmgroids.h...\n"; chdir('src\backend\utils'); - system("perl Gen_fmgrtab.pl ../../../src/include/catalog/pg_proc.h"); + system("perl -I ../catalog Gen_fmgrtab.pl ../../../src/include/catalog/pg_proc.h"); chdir('..\..\..'); copyFile('src\backend\utils\fmgroids.h','src\include\utils\fmgroids.h'); } @@ -339,12 +337,12 @@ EOF next if $bki eq ""; if (IsNewer('src/backend/catalog/postgres.bki', "src/include/catalog/$bki")) { - print "Generating postgres.bki...\n"; - Genbki::genbki( - $self->{majorver}, - "src/backend/catalog/postgres", - split(/ /,join(' src/include/catalog/',@allbki)) - ); + print "Generating postgres.bki and schemapg.h...\n"; + chdir('src\backend\catalog'); + my $bki_srcs = join(' ../../../src/include/catalog/', @allbki); + system("perl genbki.pl -I../../../src/include/catalog --set-version=$self->{majorver} $bki_srcs"); + chdir('..\..\..'); + copyFile('src\backend\catalog\schemapg.h', 'src\include\catalog\schemapg.h'); last; } } diff --git a/src/tools/msvc/clean.bat b/src/tools/msvc/clean.bat index 07c9bcb4cd..09741f9e6d 100755 --- a/src/tools/msvc/clean.bat +++ b/src/tools/msvc/clean.bat @@ -1,5 +1,5 @@ @echo off -REM $PostgreSQL: pgsql/src/tools/msvc/clean.bat,v 1.17 2010/01/01 16:58:53 mha Exp $ +REM $PostgreSQL: pgsql/src/tools/msvc/clean.bat,v 1.18 2010/01/05 01:06:57 tgl Exp $ set DIST=0 if "%1"=="dist" set DIST=1 @@ -23,11 +23,12 @@ if %DIST%==1 if exist src\backend\parser\gram.h del /q src\backend\parser\gram.h if exist src\include\utils\fmgroids.h del /q src\include\utils\fmgroids.h if exist src\include\utils\probes.h del /q src\include\utils\probes.h -if exist src\backend\utils\fmgroids.h del /q src\backend\utils\fmgroids.h -if exist src\backend\utils\fmgrtab.c del /q src\backend\utils\fmgrtab.c -if exist src\backend\catalog\postgres.bki del /q src\backend\catalog\postgres.bki -if exist src\backend\catalog\postgres.description del /q src\backend\catalog\postgres.description -if exist src\backend\catalog\postgres.shdescription del /q src\backend\catalog\postgres.shdescription +if %DIST%==1 if exist src\backend\utils\fmgroids.h del /q src\backend\utils\fmgroids.h +if %DIST%==1 if exist src\backend\utils\fmgrtab.c del /q src\backend\utils\fmgrtab.c +if %DIST%==1 if exist src\backend\catalog\postgres.bki del /q src\backend\catalog\postgres.bki +if %DIST%==1 if exist src\backend\catalog\postgres.description del /q src\backend\catalog\postgres.description +if %DIST%==1 if exist src\backend\catalog\postgres.shdescription del /q src\backend\catalog\postgres.shdescription +if %DIST%==1 if exist src\backend\catalog\schemapg.h del /q src\backend\catalog\schemapg.h if %DIST%==1 if exist src\backend\parser\scan.c del /q src\backend\parser\scan.c if %DIST%==1 if exist src\backend\parser\gram.c del /q src\backend\parser\gram.c if %DIST%==1 if exist src\backend\bootstrap\bootscanner.c del /q src\backend\bootstrap\bootscanner.c -- 2.40.0