mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	Teach genbki.pl to auto-generate pg_type entries for array types.
This eliminates some more tedium in adding new catalog entries, specifically the need to set up an array type when adding a new built-in data type. Now it's sufficient to assign an OID for the array type and write it in an "array_type_oid" metadata field. You don't have to fill the base type's typarray link explicitly, either. No catversion bump since the contents of pg_type aren't changed. (Well, their order might be different, but that doesn't matter.) John Naylor, reviewed and whacked around a bit by Dagfinn Ilmari Mannsåker, and some more by me. Discussion: https://postgr.es/m/CAJVSVGVTb6m9pJF49b3SuA8J+T-THO9c0hxOmoyv-yGKh-FbNg@mail.gmail.com
This commit is contained in:
		
							parent
							
								
									09e99ce86e
								
							
						
					
					
						commit
						3dc820c43e
					
				| @ -217,12 +217,14 @@ | ||||
|       <replaceable>value</replaceable> pairs.  The | ||||
|       allowed <replaceable>key</replaceable>s are the names of the catalog's | ||||
|       columns, plus the metadata keys <literal>oid</literal>, | ||||
|       <literal>oid_symbol</literal>, and <literal>descr</literal>. | ||||
|       <literal>oid_symbol</literal>, | ||||
|       <literal>array_type_oid</literal>, and <literal>descr</literal>. | ||||
|       (The use of <literal>oid</literal> and <literal>oid_symbol</literal> | ||||
|       is described in <xref linkend="system-catalog-oid-assignment"/> | ||||
|       below.  <literal>descr</literal> supplies a description string for | ||||
|       the object, which will be inserted | ||||
|       into <structname>pg_description</structname> | ||||
|       is described in <xref linkend="system-catalog-oid-assignment"/> below, | ||||
|       while <literal>array_type_oid</literal> is described in | ||||
|       <xref linkend="system-catalog-auto-array-types"/>. | ||||
|       <literal>descr</literal> supplies a description string for the object, | ||||
|       which will be inserted into <structname>pg_description</structname> | ||||
|       or <structname>pg_shdescription</structname> as appropriate.) | ||||
|       While the metadata keys are optional, the catalog's defined columns | ||||
|       must all be provided, except when the catalog's <literal>.h</literal> | ||||
| @ -282,8 +284,9 @@ | ||||
|         <para> | ||||
|          Within each pair of curly braces, the metadata | ||||
|          fields <literal>oid</literal>, <literal>oid_symbol</literal>, | ||||
|          and <literal>descr</literal> (if present) come first, in that | ||||
|          order, then the catalog's own fields appear in their defined order. | ||||
|          <literal>array_type_oid</literal>, and <literal>descr</literal> | ||||
|          (if present) come first, in that order, then the catalog's own | ||||
|          fields appear in their defined order. | ||||
|         </para> | ||||
|        </listitem> | ||||
| 
 | ||||
| @ -498,6 +501,41 @@ | ||||
|    </para> | ||||
|   </sect2> | ||||
| 
 | ||||
|   <sect2 id="system-catalog-auto-array-types"> | ||||
|    <title>Automatic Creation of Array Types</title> | ||||
| 
 | ||||
|    <para> | ||||
|     Most scalar data types should have a corresponding array type (that is, | ||||
|     a standard varlena array type whose element type is the scalar type, and | ||||
|     which is referenced by the <structfield>typarray</structfield> field of | ||||
|     the scalar type's <structname>pg_type</structname> | ||||
|     entry).  <filename>genbki.pl</filename> is able to generate | ||||
|     the <structname>pg_type</structname> entry for the array type | ||||
|     automatically in most cases. | ||||
|    </para> | ||||
| 
 | ||||
|    <para> | ||||
|     To use this facility, just write an <literal>array_type_oid | ||||
|     => <replaceable>nnnn</replaceable></literal> metadata field in the | ||||
|     scalar type's <structname>pg_type</structname> entry, specifying the OID | ||||
|     to use for the array type.  You may then omit | ||||
|     the <structfield>typarray</structfield> field, since it will be filled | ||||
|     automatically with that OID. | ||||
|    </para> | ||||
| 
 | ||||
|    <para> | ||||
|     The generated array type's name is the scalar type's name with an | ||||
|     underscore prepended.  The array entry's other fields are filled from | ||||
|     <literal>BKI_ARRAY_DEFAULT(<replaceable>value</replaceable>)</literal> | ||||
|     annotations in <filename>pg_type.h</filename>, or if there isn't one, | ||||
|     copied from the scalar type.  (There's also a special case | ||||
|     for <structfield>typalign</structfield>.)  Then | ||||
|     the <structfield>typelem</structfield> | ||||
|     and <structfield>typarray</structfield> fields of the two entries are | ||||
|     set to cross-reference each other. | ||||
|    </para> | ||||
|   </sect2> | ||||
| 
 | ||||
|   <sect2 id="system-catalog-recipes"> | ||||
|    <title>Recipes for Editing Data Files</title> | ||||
| 
 | ||||
|  | ||||
| @ -191,6 +191,11 @@ sub ParseHeader | ||||
| 					{ | ||||
| 						$column{default} = $1; | ||||
| 					} | ||||
| 					elsif ( | ||||
| 						$attopt =~ /BKI_ARRAY_DEFAULT\(['"]?([^'"]+)['"]?\)/) | ||||
| 					{ | ||||
| 						$column{array_default} = $1; | ||||
| 					} | ||||
| 					elsif ($attopt =~ /BKI_LOOKUP\((\w+)\)/) | ||||
| 					{ | ||||
| 						$column{lookup} = $1; | ||||
| @ -277,12 +282,16 @@ sub ParseData | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		# If we found a hash reference, keep it. | ||||
| 		# Only keep non-data strings if we | ||||
| 		# are told to preserve formatting. | ||||
| 		# If we found a hash reference, keep it, unless it is marked as | ||||
| 		# autogenerated; in that case it'd duplicate an entry we'll | ||||
| 		# autogenerate below.  (This makes it safe for reformat_dat_file.pl | ||||
| 		# with --full-tuples to print autogenerated entries, which seems like | ||||
| 		# useful behavior for debugging.) | ||||
| 		# | ||||
| 		# Only keep non-data strings if we are told to preserve formatting. | ||||
| 		if (defined $hash_ref) | ||||
| 		{ | ||||
| 			push @$data, $hash_ref; | ||||
| 			push @$data, $hash_ref if !$hash_ref->{autogenerated}; | ||||
| 		} | ||||
| 		elsif ($preserve_formatting) | ||||
| 		{ | ||||
| @ -290,6 +299,10 @@ sub ParseData | ||||
| 		} | ||||
| 	} | ||||
| 	close $ifd; | ||||
| 
 | ||||
| 	# If this is pg_type, auto-generate array types too. | ||||
| 	GenerateArrayTypes($schema, $data) if $catname eq 'pg_type'; | ||||
| 
 | ||||
| 	return $data; | ||||
| } | ||||
| 
 | ||||
| @ -343,6 +356,63 @@ sub AddDefaultValues | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| # If a pg_type entry has an array_type_oid metadata field, | ||||
| # auto-generate an entry for its array type. | ||||
| sub GenerateArrayTypes | ||||
| { | ||||
| 	my $pgtype_schema = shift; | ||||
| 	my $types         = shift; | ||||
| 	my @array_types; | ||||
| 
 | ||||
| 	foreach my $elem_type (@$types) | ||||
| 	{ | ||||
| 		next if !(ref $elem_type eq 'HASH'); | ||||
| 		next if !defined($elem_type->{array_type_oid}); | ||||
| 
 | ||||
| 		my %array_type; | ||||
| 
 | ||||
| 		# Set up metadata fields for array type. | ||||
| 		$array_type{oid}           = $elem_type->{array_type_oid}; | ||||
| 		$array_type{autogenerated} = 1; | ||||
| 		$array_type{line_number}   = $elem_type->{line_number}; | ||||
| 
 | ||||
| 		# Set up column values derived from the element type. | ||||
| 		$array_type{typname} = '_' . $elem_type->{typname}; | ||||
| 		$array_type{typelem} = $elem_type->{typname}; | ||||
| 
 | ||||
| 		# Arrays require INT alignment, unless the element type requires | ||||
| 		# DOUBLE alignment. | ||||
| 		$array_type{typalign} = $elem_type->{typalign} eq 'd' ? 'd' : 'i'; | ||||
| 
 | ||||
| 		# Fill in the rest of the array entry's fields. | ||||
| 		foreach my $column (@$pgtype_schema) | ||||
| 		{ | ||||
| 			my $attname = $column->{name}; | ||||
| 
 | ||||
| 			# Skip if we already set it above. | ||||
| 			next if defined $array_type{$attname}; | ||||
| 
 | ||||
| 			# Apply the BKI_ARRAY_DEFAULT setting if there is one, | ||||
| 			# otherwise copy the field from the element type. | ||||
| 			if (defined $column->{array_default}) | ||||
| 			{ | ||||
| 				$array_type{$attname} = $column->{array_default}; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				$array_type{$attname} = $elem_type->{$attname}; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		# Lastly, cross-link the array to the element type. | ||||
| 		$elem_type->{typarray} = $array_type{typname}; | ||||
| 
 | ||||
| 		push @array_types, \%array_type; | ||||
| 	} | ||||
| 
 | ||||
| 	push @$types, @array_types; | ||||
| } | ||||
| 
 | ||||
| # Rename temporary files to final names. | ||||
| # Call this function with the final file name and the .tmp extension. | ||||
| # | ||||
|  | ||||
| @ -394,7 +394,9 @@ EOM | ||||
| 			next | ||||
| 			  if $key eq "oid" | ||||
| 			  || $key eq "oid_symbol" | ||||
| 			  || $key eq "array_type_oid" | ||||
| 			  || $key eq "descr" | ||||
| 			  || $key eq "autogenerated" | ||||
| 			  || $key eq "line_number"; | ||||
| 			die sprintf "unrecognized field name \"%s\" in %s.dat line %s\n", | ||||
| 			  $key, $catname, $bki_values{line_number} | ||||
|  | ||||
| @ -34,6 +34,8 @@ | ||||
| #define BKI_FORCE_NOT_NULL | ||||
| /* Specifies a default value for a catalog field */ | ||||
| #define BKI_DEFAULT(value) | ||||
| /* Specifies a default value for auto-generated array types */ | ||||
| #define BKI_ARRAY_DEFAULT(value) | ||||
| /* Indicates how to perform name lookups for an OID or OID-array field */ | ||||
| #define BKI_LOOKUP(catalog) | ||||
| 
 | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -52,7 +52,7 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati | ||||
| 	 * "varlena" type (one that has a length word), -2 to indicate a | ||||
| 	 * null-terminated C string. | ||||
| 	 */ | ||||
| 	int16		typlen; | ||||
| 	int16		typlen BKI_ARRAY_DEFAULT(-1); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * typbyval determines whether internal Postgres routines pass a value of | ||||
| @ -62,7 +62,7 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati | ||||
| 	 * typbyval can be false even if the length would allow pass-by-value; for | ||||
| 	 * example, type macaddr8 is pass-by-ref even when Datum is 8 bytes. | ||||
| 	 */ | ||||
| 	bool		typbyval; | ||||
| 	bool		typbyval BKI_ARRAY_DEFAULT(f); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * typtype is 'b' for a base type, 'c' for a composite type (e.g., a | ||||
| @ -71,7 +71,7 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati | ||||
| 	 * | ||||
| 	 * If typtype is 'c', typrelid is the OID of the class' entry in pg_class. | ||||
| 	 */ | ||||
| 	char		typtype BKI_DEFAULT(b); | ||||
| 	char		typtype BKI_DEFAULT(b) BKI_ARRAY_DEFAULT(b); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * typcategory and typispreferred help the parser distinguish preferred | ||||
| @ -81,10 +81,10 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati | ||||
| 	 */ | ||||
| 
 | ||||
| 	/* arbitrary type classification */ | ||||
| 	char		typcategory; | ||||
| 	char		typcategory BKI_ARRAY_DEFAULT(A); | ||||
| 
 | ||||
| 	/* is type "preferred" within its category? */ | ||||
| 	bool		typispreferred BKI_DEFAULT(f); | ||||
| 	bool		typispreferred BKI_DEFAULT(f) BKI_ARRAY_DEFAULT(f); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * If typisdefined is false, the entry is only a placeholder (forward | ||||
| @ -97,7 +97,7 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati | ||||
| 	char		typdelim BKI_DEFAULT(','); | ||||
| 
 | ||||
| 	/* associated pg_class OID if a composite type, else 0 */ | ||||
| 	Oid			typrelid BKI_DEFAULT(0); | ||||
| 	Oid			typrelid BKI_DEFAULT(0) BKI_ARRAY_DEFAULT(0); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * If typelem is not 0 then it identifies another row in pg_type. The | ||||
| @ -116,19 +116,19 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati | ||||
| 	 * If there is a "true" array type having this type as element type, | ||||
| 	 * typarray links to it.  Zero if no associated "true" array type. | ||||
| 	 */ | ||||
| 	Oid			typarray BKI_DEFAULT(0) BKI_LOOKUP(pg_type); | ||||
| 	Oid			typarray BKI_DEFAULT(0) BKI_ARRAY_DEFAULT(0) BKI_LOOKUP(pg_type); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * I/O conversion procedures for the datatype. | ||||
| 	 */ | ||||
| 
 | ||||
| 	/* text format (required) */ | ||||
| 	regproc		typinput BKI_LOOKUP(pg_proc); | ||||
| 	regproc		typoutput BKI_LOOKUP(pg_proc); | ||||
| 	regproc		typinput BKI_ARRAY_DEFAULT(array_in) BKI_LOOKUP(pg_proc); | ||||
| 	regproc		typoutput BKI_ARRAY_DEFAULT(array_out) BKI_LOOKUP(pg_proc); | ||||
| 
 | ||||
| 	/* binary format (optional) */ | ||||
| 	regproc		typreceive BKI_LOOKUP(pg_proc); | ||||
| 	regproc		typsend BKI_LOOKUP(pg_proc); | ||||
| 	regproc		typreceive BKI_ARRAY_DEFAULT(array_recv) BKI_LOOKUP(pg_proc); | ||||
| 	regproc		typsend BKI_ARRAY_DEFAULT(array_send) BKI_LOOKUP(pg_proc); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * I/O functions for optional type modifiers. | ||||
| @ -139,7 +139,7 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati | ||||
| 	/*
 | ||||
| 	 * Custom ANALYZE procedure for the datatype (0 selects the default). | ||||
| 	 */ | ||||
| 	regproc		typanalyze BKI_DEFAULT(-) BKI_LOOKUP(pg_proc); | ||||
| 	regproc		typanalyze BKI_DEFAULT(-) BKI_ARRAY_DEFAULT(array_typanalyze) BKI_LOOKUP(pg_proc); | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| 	 * typalign is the alignment required when storing a value of this | ||||
| @ -177,7 +177,7 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati | ||||
| 	 * 'm' MAIN		  like 'x' but try to keep in main tuple | ||||
| 	 * ---------------- | ||||
| 	 */ | ||||
| 	char		typstorage BKI_DEFAULT(p); | ||||
| 	char		typstorage BKI_DEFAULT(p) BKI_ARRAY_DEFAULT(x); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * This flag represents a "NOT NULL" constraint against this datatype. | ||||
| @ -221,7 +221,7 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati | ||||
| 	 * a default expression for the type.  Currently this is only used for | ||||
| 	 * domains. | ||||
| 	 */ | ||||
| 	pg_node_tree typdefaultbin BKI_DEFAULT(_null_); | ||||
| 	pg_node_tree typdefaultbin BKI_DEFAULT(_null_) BKI_ARRAY_DEFAULT(_null_); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * typdefault is NULL if the type has no associated default value. If | ||||
| @ -231,7 +231,7 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati | ||||
| 	 * external representation of the type's default value, which may be fed | ||||
| 	 * to the type's input converter to produce a constant. | ||||
| 	 */ | ||||
| 	text		typdefault BKI_DEFAULT(_null_); | ||||
| 	text		typdefault BKI_DEFAULT(_null_) BKI_ARRAY_DEFAULT(_null_); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Access permissions | ||||
|  | ||||
| @ -5,9 +5,9 @@ | ||||
| #    Perl script that reads in catalog data file(s) and writes out | ||||
| #    functionally equivalent file(s) in a standard format. | ||||
| # | ||||
| #    In each entry of a reformatted file, metadata fields (if any) come | ||||
| #    first, with normal attributes starting on the following line, in | ||||
| #    the same order as the columns of the corresponding catalog. | ||||
| #    In each entry of a reformatted file, metadata fields (if present) | ||||
| #    come first, with normal attributes starting on the following line, | ||||
| #    in the same order as the columns of the corresponding catalog. | ||||
| #    Comments and blank lines are preserved. | ||||
| # | ||||
| # Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group | ||||
| @ -26,6 +26,11 @@ use FindBin; | ||||
| use lib "$FindBin::RealBin/../../backend/catalog/"; | ||||
| use Catalog; | ||||
| 
 | ||||
| # Names of the metadata fields of a catalog entry.  (line_number is also | ||||
| # a metadata field, but we never write it out, so it's not listed here.) | ||||
| my @METADATA = | ||||
|   ('oid', 'oid_symbol', 'array_type_oid', 'descr', 'autogenerated'); | ||||
| 
 | ||||
| my @input_files; | ||||
| my $output_path = ''; | ||||
| my $full_tuples = 0; | ||||
| @ -62,9 +67,6 @@ if ($output_path ne '' && substr($output_path, -1) ne '/') | ||||
| 	$output_path .= '/'; | ||||
| } | ||||
| 
 | ||||
| # Metadata of a catalog entry | ||||
| my @METADATA = ('oid', 'oid_symbol', 'descr'); | ||||
| 
 | ||||
| # Read all the input files into internal data structures. | ||||
| # We pass data file names as arguments and then look for matching | ||||
| # headers to parse the schema from. | ||||
| @ -142,6 +144,9 @@ foreach my $catname (@catnames) | ||||
| 
 | ||||
| 			if (!$full_tuples) | ||||
| 			{ | ||||
| 				# If it's an autogenerated entry, drop it completely. | ||||
| 				next if $values{autogenerated}; | ||||
| 				# Else, just drop any default/computed fields. | ||||
| 				strip_default_values(\%values, $schema, $catname); | ||||
| 			} | ||||
| 
 | ||||
| @ -162,10 +167,6 @@ foreach my $catname (@catnames) | ||||
| 			print $dat " },\n"; | ||||
| 		} | ||||
| 
 | ||||
| 		# Strings -- handle accordingly or ignore. It was necessary to | ||||
| 		# ignore bare commas during the initial data conversion. This | ||||
| 		# should be a no-op now, but we may as well keep that behavior. | ||||
| 
 | ||||
| 		# Preserve blank lines. | ||||
| 		elsif ($data =~ /^\s*$/) | ||||
| 		{ | ||||
| @ -207,6 +208,14 @@ sub strip_default_values | ||||
| 	{ | ||||
| 		delete $row->{pronargs} if defined $row->{proargtypes}; | ||||
| 	} | ||||
| 
 | ||||
| 	# If a pg_type entry has an auto-generated array type, then its | ||||
| 	# typarray field is a computed value too (see GenerateArrayTypes). | ||||
| 	if ($catname eq 'pg_type') | ||||
| 	{ | ||||
| 		delete $row->{typarray} if defined $row->{array_type_oid}; | ||||
| 	} | ||||
| 
 | ||||
| 	return; | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user