 src/backend/Makefile           |   2 +-
 src/backend/catalog/.gitignore |   1 +
 src/backend/catalog/Makefile   |   5 +-
 src/backend/catalog/genbki.pl  | 103 +++++++++++++++++++++++++++++++++++++----
 src/tools/msvc/clean.bat       |   1 +
 5 files changed, 102 insertions(+), 10 deletions(-)

diff --git a/src/backend/Makefile b/src/backend/Makefile
new file mode 100644
index aab676d..4a59e6f
*** a/src/backend/Makefile
--- b/src/backend/Makefile
*************** ifeq ($(PORTNAME), win32)
*** 321,327 ****
  endif
  
  distclean: clean
! 	rm -f port/tas.s port/dynloader.c port/pg_sema.c port/pg_shmem.c
  
  maintainer-clean: distclean
  	rm -f bootstrap/bootparse.c \
--- 321,327 ----
  endif
  
  distclean: clean
! 	rm -f port/tas.s port/dynloader.c port/pg_sema.c port/pg_shmem.c catalog/postgres.sql
  
  maintainer-clean: distclean
  	rm -f bootstrap/bootparse.c \
diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
new file mode 100644
index 557af3c..fb77833
*** a/src/backend/catalog/.gitignore
--- b/src/backend/catalog/.gitignore
***************
*** 1,4 ****
--- 1,5 ----
  /postgres.bki
+ /postgres.sql
  /postgres.description
  /postgres.shdescription
  /schemapg.h
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
new file mode 100644
index 23858b8..02693a1
*** a/src/backend/catalog/Makefile
--- b/src/backend/catalog/Makefile
*************** uninstall-data:
*** 100,104 ****
  # are in the distribution tarball, so they are not cleaned here.
  clean:
  
! maintainer-clean: clean
  	rm -f $(BKIFILES)
--- 100,107 ----
  # are in the distribution tarball, so they are not cleaned here.
  clean:
  
! distclean: clean
! 	rm -f postgres.sql
! 
! maintainer-clean: distclean
  	rm -f $(BKIFILES)
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
new file mode 100644
index 1b2a570..e98a11c
*** a/src/backend/catalog/genbki.pl
--- b/src/backend/catalog/genbki.pl
*************** my $tmpext  = ".tmp$$";
*** 68,73 ****
--- 68,76 ----
  my $bkifile = $output_path . 'postgres.bki';
  open my $bki, '>', $bkifile . $tmpext
    or die "can't open $bkifile$tmpext: $!";
+ my $sqlfile = $output_path . 'postgres.sql';
+ open my $sql, '>', $sqlfile . $tmpext
+   or die "can't open $sqlfile$tmpext: $!";
  my $schemafile = $output_path . 'schemapg.h';
  open my $schemapg, '>', $schemafile . $tmpext
    or die "can't open $schemafile$tmpext: $!";
*************** my $catalog_data = Catalog::ParseData(@d
*** 114,124 ****
  # tables here. However, if we need default values for a catalog, we
  # need to wait until the full tuples have been built.
  
! # 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;
--- 117,133 ----
  # tables here. However, if we need default values for a catalog, we
  # need to wait until the full tuples have been built.
  
! # Generate postgres.bki, postgres.sql, postgres.description,
! # and postgres.shdescription
  
  # version marker for .bki file
  print $bki "# PostgreSQL $major_version\n";
  
+ # Setup dev schema for .sql file
+ print $sql "DROP SCHEMA IF EXISTS pgdev_catalog CASCADE;\n";
+ print $sql "CREATE SCHEMA pgdev_catalog;\n\n";
+ print $sql "BEGIN;\n\n";
+ 
  # vars to hold data needed for schemapg.h
  my %schemapg_entries;
  my @tables_needing_macros;
*************** my @types;
*** 129,147 ****
  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 @attnames;
! 	my $first = 1;
  
! 	print $bki " (\n";
! 	my $schema = $catalog->{columns};
  	foreach my $column (@$schema)
  	{
  		my $attname = $column->{name};
--- 138,173 ----
  foreach my $catname (@{ $catalogs->{names} })
  {
  
! 	# CREATE command for this catalog
  	my $catalog = $catalogs->{$catname};
+ 	my $schema = $catalog->{columns};
+ 	my @attnames;
+ 
  	print $bki "create $catname $catalog->{relation_oid}"
  	  . $catalog->{shared_relation}
  	  . $catalog->{bootstrap}
  	  . $catalog->{without_oids}
! 	  . $catalog->{rowtype_oid};
! 	print $sql "CREATE TABLE pgdev_catalog.$catname";
  
! 	print $bki "\n (\n";
! 	print $sql "\n (\n";
  
! 	if (!$catalog->{without_oids})
! 	{
! 		print $sql " bootstrap_oid text ,\n";
! 	}
! 
! 	if ($catalog->{shared_relation})
! 	{
! 		print $sql " bootstrap_shdescr text ,\n";
! 	}
! 	else
! 	{
! 		print $sql " bootstrap_descr text ,\n";
! 	}
! 
! 	my $first = 1;
  	foreach my $column (@$schema)
  	{
  		my $attname = $column->{name};
*************** foreach my $catname (@{ $catalogs->{name
*** 151,161 ****
--- 177,199 ----
  		if (!$first)
  		{
  			print $bki " ,\n";
+ 			print $sql " ,\n";
  		}
  		$first = 0;
  
  		print $bki " $attname = $atttype";
  
+ 		# We can't use the intended type since some values are strings
+ 		# that are substituted either with lookups in this script, or
+ 		# at initdb time. It doesn't matter since the source
+ 		# data is purely text anyway.
+ 		print $sql " $attname text";
+ 
+ 		# Use default values to simplify writing dev insert queries.
+ 		if (defined $column->{default})
+ 		{
+ 			printf $sql " DEFAULT '%s'", $column->{default};
+ 		}
  		if (defined $column->{forcenotnull})
  		{
  			print $bki " FORCE NOT NULL";
*************** foreach my $catname (@{ $catalogs->{name
*** 166,171 ****
--- 204,210 ----
  		}
  	}
  	print $bki "\n )\n";
+ 	print $sql "\n );\n";
  
  	# Open it, unless bootstrap case (create bootstrap does this
  	# automatically)
*************** foreach my $catname (@{ $catalogs->{name
*** 183,188 ****
--- 222,231 ----
  			my %bki_values = %$row;
  			Catalog::AddDefaultValues(\%bki_values, $schema, $catname);
  
+ 			# From here on, the .bki and .sql files need separate
+ 			# copies of the data.
+ 			my %sql_values = %bki_values;
+ 
  			# Perform required substitutions on fields
  			foreach my $column (@$schema)
  			{
*************** foreach my $catname (@{ $catalogs->{name
*** 229,236 ****
  			# Add quotes where necessary.
  			format_bki_row(\%bki_values, $schema);
  
! 			# Write to postgres.bki
  			bki_insert(\%bki_values, @attnames);
  
  			# Write comments to postgres.description and
  			# postgres.shdescription
--- 272,280 ----
  			# Add quotes where necessary.
  			format_bki_row(\%bki_values, $schema);
  
! 			# Write to postgres.bki and postgres.sql
  			bki_insert(\%bki_values, @attnames);
+ 			sql_insert($catname, $catalog->{without_oids}, \%sql_values, @attnames);
  
  			# Write comments to postgres.description and
  			# postgres.shdescription
*************** foreach my $catname (@{ $catalogs->{name
*** 281,286 ****
--- 325,332 ----
  				if ($table->{bootstrap})
  				{
  					bki_insert(\%row, @attnames);
+ 					sql_insert($catname, $catalog->{without_oids},
+ 							   \%row, @attnames);
  				}
  
  				# Store schemapg entries for later.
*************** foreach my $catname (@{ $catalogs->{name
*** 320,331 ****
--- 366,380 ----
  						  && $row{attname} eq 'oid';
  
  					bki_insert(\%row, @attnames);
+ 					sql_insert($catname, $catalog->{without_oids},
+ 							   \%row, @attnames);
  				}
  			}
  		}
  	}
  
  	print $bki "close $catname\n";
+ 	print $sql "\n";
  }
  
  # Any information needed for the BKI that is not contained in a pg_*.h header
*************** foreach my $declaration (@{ $catalogs->{
*** 342,347 ****
--- 391,397 ----
  	print $bki $declaration;
  }
  
+ print $sql "COMMIT;\n";
  
  # Now generate schemapg.h
  
*************** print $schemapg "\n#endif /* SCHEMAPG_H
*** 381,392 ****
--- 431,444 ----
  
  # We're done emitting data
  close $bki;
+ close $sql;
  close $schemapg;
  close $descr;
  close $shdescr;
  
  # Finally, rename the completed files into place.
  Catalog::RenameTempFile($bkifile,     $tmpext);
+ Catalog::RenameTempFile($sqlfile,     $tmpext);
  Catalog::RenameTempFile($schemafile,  $tmpext);
  Catalog::RenameTempFile($descrfile,   $tmpext);
  Catalog::RenameTempFile($shdescrfile, $tmpext);
*************** sub bki_insert
*** 514,519 ****
--- 566,606 ----
  	printf $bki "insert %s( %s )\n", $oid, $bki_values;
  }
  
+ # Write an entry to postgres.sql.
+ sub sql_insert
+ {
+ 	my $catname      = shift;
+ 	my $without_oids = shift;
+ 	my $row          = shift;
+ 	my @attnames     = @_;
+ 
+ 	my $oid = '';
+ 	if (!$without_oids)
+ 	{
+ 		# Insert a null in cases where there is no bootstrap oid
+ 		# (e.g. pg_opclass)
+ 		$oid = $row->{oid} ? "'$row->{oid}', " : 'NULL, ';
+ 	}
+ 
+ 	# We can treat descr and shdescr the same since they both occupy
+ 	# the same column position.
+ 	my $descr = $row->{descr} ? $row->{descr} : $row->{shdescr};
+ 	if (defined $descr)
+ 	{
+ 		# Normal values with single quotes have been escaped by now,
+ 		# but not the comments.
+ 		$descr =~ s/'/''/g;
+ 		$descr = "'$descr'";
+ 	}
+ 	else
+ 	{
+ 		$descr = 'NULL';
+ 	}
+ 
+ 	my $sql_values = join ', ', map "'$row->{$_}'", @attnames;
+ 	printf $sql "INSERT INTO pgdev_catalog.$catname VALUES ( %s%s, %s );\n", $oid, $descr, $sql_values;
+ }
+ 
  # The field values of a Schema_pg_xxx declaration are similar, but not
  # quite identical, to the corresponding values in postgres.bki.
  sub emit_schemapg_row
diff --git a/src/tools/msvc/clean.bat b/src/tools/msvc/clean.bat
new file mode 100755
index 0a88b52..c44c480
*** a/src/tools/msvc/clean.bat
--- b/src/tools/msvc/clean.bat
*************** if %DIST%==1 if exist src\bin\psql\sql_h
*** 64,69 ****
--- 64,70 ----
  if %DIST%==1 if exist src\bin\psql\sql_help.h del /q src\bin\psql\sql_help.h
  if %DIST%==1 if exist src\interfaces\ecpg\preproc\preproc.y del /q src\interfaces\ecpg\preproc\preproc.y
  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.sql del /q src\backend\catalog\postgres.sql
  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
