v3-0003-Generate-ObjectProperty-from-catalog-files.patch
text/plain
Filename: v3-0003-Generate-ObjectProperty-from-catalog-files.patch
Type: text/plain
Part: 2
Patch
Format: format-patch
Series: patch v3-0003
Subject: Generate ObjectProperty from catalog files
| File | + | − |
|---|---|---|
| src/backend/catalog/genbki.pl | 167 | 0 |
| src/backend/catalog/.gitignore | 1 | 0 |
| src/backend/catalog/Makefile | 1 | 1 |
| src/backend/catalog/objectaddress.c | 11 | 11 |
| src/include/catalog/meson.build | 2 | 0 |
| src/tools/pginclude/cpluspluscheck | 3 | 0 |
| src/tools/pginclude/headerscheck | 3 | 0 |
From a17faafd7c55f446bd3eb99e3451e23f74a06873 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 31 Aug 2023 09:51:28 +0200
Subject: [PATCH v3 3/3] Generate ObjectProperty from catalog files
Most of the information can be extracted from catalog files and
generated automatically.
TODO: Currently missing: object type and class description. There are
some workarounds in place.
We also now replace the linear search with a hash function generated
using PerfectHash. This would allow this lookup table to be used in
more performance-sensitive situations.
Discussion: https://www.postgresql.org/message-id/flat/75ae5875-3abc-dafc-8aec-73247ed41cde@eisentraut.org
---
src/backend/catalog/.gitignore | 1 +
src/backend/catalog/Makefile | 2 +-
src/backend/catalog/genbki.pl | 167 ++++++++++++++++++++++++++++
src/backend/catalog/objectaddress.c | 22 ++--
src/include/catalog/meson.build | 2 +
src/tools/pginclude/cpluspluscheck | 3 +
src/tools/pginclude/headerscheck | 3 +
7 files changed, 188 insertions(+), 12 deletions(-)
diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
index ff65560379..d817798dc0 100644
--- a/src/backend/catalog/.gitignore
+++ b/src/backend/catalog/.gitignore
@@ -1,3 +1,4 @@
+/objectproperty_info.c.h
/postgres.bki
/schemapg.h
/syscache_info.c.h
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 2c94126ec5..e6c5878e99 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -120,7 +120,7 @@ CATALOG_HEADERS := \
pg_subscription.h \
pg_subscription_rel.h
-GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h syscache_info.h syscache_info.c.h system_fk_info.h
+GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) objectproperty_info.c.h schemapg.h syscache_info.h syscache_info.c.h system_fk_info.h
POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/, $(CATALOG_HEADERS))
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 78f2da690e..199091305c 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -19,8 +19,10 @@
use FindBin;
use lib $FindBin::RealBin;
+use lib "$FindBin::RealBin/../../tools";
use Catalog;
+use PerfectHash;
my $output_path = '';
my $major_version;
@@ -59,6 +61,7 @@
my %syscaches;
my %oidcounts;
my @system_constraints;
+my @object_properties;
foreach my $header (@ARGV)
{
@@ -133,6 +136,7 @@
$oidcounts{ $toast->{toast_oid} }++;
$oidcounts{ $toast->{toast_index_oid} }++;
}
+ my ($oid_index, $oid_syscache, $name_syscache, $is_nsp_name_unique);
foreach my $index (@{ $catalog->{indexing} })
{
push @index_decls,
@@ -166,7 +170,136 @@
nbuckets => $index->{syscache_nbuckets},
};
}
+
+ if ($index->{index_decl} eq 'btree(oid oid_ops)')
+ {
+ $oid_index = $index->{index_oid_macro};
+ $oid_syscache = $index->{syscache_name};
+ }
+ if ($index->{index_decl} =~ /\(\w+name name_ops(, \w+namespace oid_ops)?\)/)
+ {
+ $name_syscache = $index->{syscache_name};
+ $is_nsp_name_unique = 1 if $index->{is_unique};
+ }
+ }
+
+ my ($attnum_oid, $attnum_name, $attnum_namespace, $attnum_owner, $attnum_acl);
+ foreach my $att (@$schema)
+ {
+ if ($att->{name} eq 'oid' && $att->{type} eq 'oid')
+ {
+ $attnum_oid = "Anum_${catname}_" . $att->{name};
+ }
+ elsif ($att->{name} =~ /^\w{2,4}name$/ && $att->{type} eq 'name')
+ {
+ $attnum_name = "Anum_${catname}_" . $att->{name};
+ }
+ elsif ($att->{name} =~ /^\w{2,4}namespace$/ && $att->{type} eq 'oid' && $att->{lookup} eq 'pg_namespace')
+ {
+ $attnum_namespace = "Anum_${catname}_" . $att->{name};
+ }
+ elsif ($att->{name} =~ /^\w{2,4}owner$/ && $att->{type} eq 'oid' && $att->{lookup} eq 'pg_authid')
+ {
+ $attnum_owner = "Anum_${catname}_" . $att->{name};
+ }
+ elsif ($att->{name} =~ /^\w{2,4}acl$/ && $att->{type} eq '_aclitem')
+ {
+ $attnum_acl = "Anum_${catname}_" . $att->{name};
+ }
+ }
+
+ # XXX hardcoded exceptions
+ # extension doesn't belong to extnamespace
+ $attnum_namespace = undef if $catname eq 'pg_extension';
+ # pg_database owner is spelled datdba
+ $attnum_owner = "Anum_pg_database_datdba" if $catname eq 'pg_database';
+ # XXX?
+ $name_syscache = "SUBSCRIPTIONNAME" if $catname eq 'pg_subscription';
+ # XXX?
+ $is_nsp_name_unique = 1 if $catname eq 'pg_collation';
+ $is_nsp_name_unique = 1 if $catname eq 'pg_opclass';
+ $is_nsp_name_unique = 1 if $catname eq 'pg_opfamily';
+ $is_nsp_name_unique = 1 if $catname eq 'pg_subscription';
+
+ # XXX These catalogs were not covered by the previous hand-maintained table.
+ my @skip = qw(
+ AttrDefaultRelationId EnumRelationId IndexRelationId
+ LargeObjectRelationId ParameterAclRelationId
+ PublicationNamespaceRelationId PublicationRelRelationId
+ InheritsRelationId AggregateRelationId StatisticRelationId
+ StatisticExtDataRelationId DescriptionRelationId
+ DependRelationId DbRoleSettingRelationId
+ SharedDependRelationId SharedDescriptionRelationId
+ TSConfigMapRelationId ForeignTableRelationId
+ ReplicationOriginRelationId InitPrivsRelationId
+ SecLabelRelationId SharedSecLabelRelationId
+ PartitionedRelationId RangeRelationId SequenceRelationId
+ SubscriptionRelRelationId);
+ # XXX This one neither, but if I add it to @skip, PerfectHash will fail. (???)
+ #FIXME: AttributeRelationId
+
+ # XXX hardcoded ObjectType mapping -- where to put this?
+ my %objtypes = (
+ 'AccessMethodRelationId' => 'OBJECT_ACCESS_METHOD',
+ 'AccessMethodOperatorRelationId' => 'OBJECT_AMOP',
+ 'AccessMethodProcedureRelationId' => 'OBJECT_AMPROC',
+ 'CastRelationId' => 'OBJECT_CAST',
+ 'CollationRelationId' => 'OBJECT_COLLATION',
+ 'ConversionRelationId' => 'OBJECT_CONVERSION',
+ 'DatabaseRelationId' => 'OBJECT_DATABASE',
+ 'DefaultAclRelationId' => 'OBJECT_DEFACL',
+ 'ExtensionRelationId' => 'OBJECT_EXTENSION',
+ 'ForeignDataWrapperRelationId' => 'OBJECT_FDW',
+ 'ForeignServerRelationId' => 'OBJECT_FOREIGN_SERVER',
+ 'ProcedureRelationId' => 'OBJECT_FUNCTION',
+ 'LanguageRelationId' => 'OBJECT_LANGUAGE',
+ 'LargeObjectMetadataRelationId' => 'OBJECT_LARGEOBJECT',
+ 'OperatorClassRelationId' => 'OBJECT_OPCLASS',
+ 'OperatorRelationId' => 'OBJECT_OPERATOR',
+ 'OperatorFamilyRelationId' => 'OBJECT_OPFAMILY',
+ 'AuthIdRelationId' => 'OBJECT_ROLE',
+ 'RewriteRelationId' => 'OBJECT_RULE',
+ 'NamespaceRelationId' => 'OBJECT_SCHEMA',
+ 'RelationRelationId' => 'OBJECT_TABLE',
+ 'TableSpaceRelationId' => 'OBJECT_TABLESPACE',
+ 'TransformRelationId' => 'OBJECT_TRANSFORM',
+ 'TriggerRelationId' => 'OBJECT_TRIGGER',
+ 'PolicyRelationId' => 'OBJECT_POLICY',
+ 'EventTriggerRelationId' => 'OBJECT_EVENT_TRIGGER',
+ 'TSConfigRelationId' => 'OBJECT_TSCONFIGURATION',
+ 'TSDictionaryRelationId' => 'OBJECT_TSDICTIONARY',
+ 'TSParserRelationId' => 'OBJECT_TSPARSER',
+ 'TSTemplateRelationId' => 'OBJECT_TSTEMPLATE',
+ 'TypeRelationId' => 'OBJECT_TYPE',
+ 'PublicationRelationId' => 'OBJECT_PUBLICATION',
+ 'SubscriptionRelationId' => 'OBJECT_SUBSCRIPTION',
+ 'StatisticExtRelationId' => 'OBJECT_STATISTIC_EXT',
+ 'UserMappingRelationId' => 'OBJECT_USER_MAPPING',
+ );
+ my $objtype = $objtypes{$catalog->{relation_oid_macro}};
+
+ # XXX This just uses the catalog name as a string rather than the
+ # previous natural-language description. This could be changed if
+ # we decide on a place to store this. But maybe for what we are
+ # using it, this is actually better.
+ my $class_descr = qq{"${catname}"};
+
+ push @object_properties, {
+ class_descr => $class_descr,
+ class_oid => $catalog->{relation_oid_macro},
+ _class_oid => $catalog->{relation_oid},
+ oid_index_oid => $oid_index,
+ oid_catcache_id => $oid_syscache || '-1',
+ name_catcache_id => $name_syscache || '-1',
+ attnum_oid => $attnum_oid,
+ attnum_name => $attnum_name,
+ attnum_namespace => $attnum_namespace,
+ attnum_owner => $attnum_owner,
+ attnum_acl => $attnum_acl,
+ objtype => $objtype,
+ is_nsp_name_unique => $is_nsp_name_unique ? 'true' : 'false',
}
+ unless grep { $_ eq $catalog->{relation_oid_macro} } @skip;
}
# Complain and exit if we found any duplicate OIDs.
@@ -441,6 +574,9 @@
my $syscache_info_c = $output_path . 'syscache_info.c.h';
open my $syscache_info_c_fh, '>', $syscache_info_c . $tmpext
or die "can't open $syscache_info_c$tmpext: $!";
+my $objectproperty_info = $output_path . 'objectproperty_info.c.h';
+open my $objectproperty_info_fh, '>', $objectproperty_info . $tmpext
+ or die "can't open $objectproperty_info$tmpext: $!";
# Generate postgres.bki and pg_*_d.h headers.
@@ -810,6 +946,35 @@
print $syscache_info_c_fh "};\n";
+# Now generate objectproperty_info
+
+print_boilerplate($objectproperty_info_fh, "objectproperty_info.h", "object property data");
+print $objectproperty_info_fh "\n";
+foreach my $catname (@catnames)
+{
+ print $objectproperty_info_fh qq{#include "catalog/${catname}_d.h"\n};
+}
+print $objectproperty_info_fh "\n";
+print $objectproperty_info_fh "static const ObjectPropertyType ObjectProperty[] =
+{
+";
+
+my @class_oids;
+foreach my $op (@object_properties)
+{
+ print $objectproperty_info_fh "\t{\n";
+ foreach my $p (sort keys %{$op})
+ {
+ printf $objectproperty_info_fh "\t\t.%s = %s,\n", $p, ${$op}{$p} if $p !~ /^_/ && ${$op}{$p};
+ }
+ push @class_oids, pack('N', ${$op}{_class_oid});
+ print $objectproperty_info_fh "\t},\n";
+}
+
+print $objectproperty_info_fh "};\n";
+
+print $objectproperty_info_fh "\nstatic " . PerfectHash::generate_hash_function(\@class_oids, 'objectproperty_hash_func', fixed_key_length => 4);
+
# We're done emitting data
close $bki;
close $schemapg;
@@ -817,6 +982,7 @@
close $constraints;
close $syscache_info_h_fh;
close $syscache_info_c_fh;
+close $objectproperty_info_fh;
# Finally, rename the completed files into place.
Catalog::RenameTempFile($bkifile, $tmpext);
@@ -825,6 +991,7 @@
Catalog::RenameTempFile($constraints_file, $tmpext);
Catalog::RenameTempFile($syscache_info_h, $tmpext);
Catalog::RenameTempFile($syscache_info_c, $tmpext);
+Catalog::RenameTempFile($objectproperty_info, $tmpext);
exit($num_errors != 0 ? 1 : 0);
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index bb4efcad20..6ba84ee86c 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -32,19 +32,10 @@
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_conversion.h"
-#include "catalog/pg_database.h"
#include "catalog/pg_default_acl.h"
-#include "catalog/pg_enum.h"
-#include "catalog/pg_event_trigger.h"
-#include "catalog/pg_extension.h"
-#include "catalog/pg_foreign_data_wrapper.h"
-#include "catalog/pg_foreign_server.h"
#include "catalog/pg_language.h"
#include "catalog/pg_largeobject.h"
-#include "catalog/pg_largeobject_metadata.h"
-#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
-#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_parameter_acl.h"
#include "catalog/pg_policy.h"
@@ -54,8 +45,6 @@
#include "catalog/pg_publication_rel.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_statistic_ext.h"
-#include "catalog/pg_subscription.h"
-#include "catalog/pg_tablespace.h"
#include "catalog/pg_transform.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_ts_config.h"
@@ -119,6 +108,9 @@ typedef struct
* object of this class? */
} ObjectPropertyType;
+#if 1
+#include "catalog/objectproperty_info.c.h"
+#else
static const ObjectPropertyType ObjectProperty[] =
{
{
@@ -640,6 +632,7 @@ static const ObjectPropertyType ObjectProperty[] =
false
},
};
+#endif
/*
* This struct maps the string object types as returned by
@@ -2791,6 +2784,7 @@ get_object_property_data(Oid class_id)
{
static const ObjectPropertyType *prop_last = NULL;
int index;
+ uint32 hashkey;
/*
* A shortcut to speed up multiple consecutive lookups of a particular
@@ -2799,7 +2793,13 @@ get_object_property_data(Oid class_id)
if (prop_last && prop_last->class_oid == class_id)
return prop_last;
+#if 1
+ hashkey = pg_hton32(class_id);
+ index = objectproperty_hash_func(&hashkey);
+ if (index >= 0 && index < lengthof(ObjectProperty))
+#else
for (index = 0; index < lengthof(ObjectProperty); index++)
+#endif
{
if (ObjectProperty[index].class_oid == class_id)
{
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
index 39d8e94ae2..3362733b5a 100644
--- a/src/include/catalog/meson.build
+++ b/src/include/catalog/meson.build
@@ -103,6 +103,7 @@ bki_data_f = files(bki_data)
input = []
output_files = [
+ 'objectproperty_info.c.h',
'postgres.bki',
'system_constraints.sql',
'schemapg.h',
@@ -111,6 +112,7 @@ output_files = [
'system_fk_info.h',
]
output_install = [
+ dir_data,
dir_data,
dir_data,
dir_include_server / 'catalog',
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 56ed423567..49e3ca7a7b 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -119,6 +119,9 @@ do
test "$f" = src/include/common/unicode_nonspacing_table.h && continue
test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
+ test "$f" = src/backend/catalog/objectproperty_info.c.h && continue
+ test "$f" = src/include/catalog/objectproperty_info.c.h && continue
+
test "$f" = src/backend/catalog/syscache_info.c.h && continue
test "$f" = src/backend/catalog/syscache_info.h && continue
test "$f" = src/include/catalog/syscache_info.c.h && continue
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 477e4dd7e6..a1ea2ef692 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -114,6 +114,9 @@ do
test "$f" = src/include/common/unicode_nonspacing_table.h && continue
test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue
+ test "$f" = src/backend/catalog/objectproperty_info.c.h && continue
+ test "$f" = src/include/catalog/objectproperty_info.c.h && continue
+
test "$f" = src/backend/catalog/syscache_info.c.h && continue
test "$f" = src/backend/catalog/syscache_info.h && continue
test "$f" = src/include/catalog/syscache_info.c.h && continue
--
2.41.0